All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7 0/6] Enable CET support for guest
@ 2021-02-26  2:20 Yang Weijiang
  2021-02-26  2:20 ` [PATCH v7 1/6] target/i386: Change XSAVE related feature-word names Yang Weijiang
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Yang Weijiang @ 2021-02-26  2:20 UTC (permalink / raw)
  To: pbonzini, richard.henderson, ehabkost, mtosatti,
	sean.j.christopherson, qemu-devel, kvm
  Cc: Yang Weijiang

Control-flow Enforcement Technology (CET) provides protection against
Return/Jump-Oriented Programming (ROP/JOP). It includes two features:
Shadow Stack(SHSTK) and Indirect Branch Tracking(IBT).
This patch series is to enable CET related CPUID report, XSAVES/XRSTORS
support and MSR access etc. for guest.

Change in v7:
- Reverted part of XSAVE feature-word naming change per review feedback.
- Fixed an issue blocking SHSTK and IBT used as two independent features
  if OS just enables either of them.
- Other minor changes during testing and review.
- Rebased to 5.2.0 base.

CET KVM patches:
https://lkml.kernel.org/r/20210203113421.5759-1-weijiang.yang@intel.com

CET kernel patches:
https://lkml.kernel.org/r/20210217222730.15819-1-yu-cheng.yu@intel.com


Yang Weijiang (6):
  target/i386: Change XSAVE related feature-word names
  target/i386: Enable XSS feature enumeration for CPUID
  target/i386: Enable CET components support for XSAVES
  target/i386: Add user-space MSR access interface for CET
  target/i386: Add CET state support for guest migration
  target/i386: Advise CET bits in CPU/MSR feature words

 target/i386/cpu.c     | 113 +++++++++++++++++++++++------
 target/i386/cpu.h     |  55 ++++++++++++++-
 target/i386/kvm.c     |  72 +++++++++++++++++++
 target/i386/machine.c | 161 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 379 insertions(+), 22 deletions(-)

-- 
2.26.2


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v7 1/6] target/i386: Change XSAVE related feature-word names
  2021-02-26  2:20 [PATCH v7 0/6] Enable CET support for guest Yang Weijiang
@ 2021-02-26  2:20 ` Yang Weijiang
  2021-02-26  2:20 ` [PATCH v7 2/6] target/i386: Enable XSS feature enumeration for CPUID Yang Weijiang
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Yang Weijiang @ 2021-02-26  2:20 UTC (permalink / raw)
  To: pbonzini, richard.henderson, ehabkost, mtosatti,
	sean.j.christopherson, qemu-devel, kvm
  Cc: Yang Weijiang

Rename XSAVE related feature-words for introducing XSAVES related
feature-words.

Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 target/i386/cpu.c | 24 ++++++++++++------------
 target/i386/cpu.h |  4 ++--
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 5a8c96072e..89edab4240 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1073,7 +1073,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
         .cpuid = { .eax = 6, .reg = R_EAX, },
         .tcg_features = TCG_6_EAX_FEATURES,
     },
-    [FEAT_XSAVE_COMP_LO] = {
+    [FEAT_XSAVE_XCR0_LO] = {
         .type = CPUID_FEATURE_WORD,
         .cpuid = {
             .eax = 0xD,
@@ -1086,7 +1086,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
             XSTATE_OPMASK_MASK | XSTATE_ZMM_Hi256_MASK | XSTATE_Hi16_ZMM_MASK |
             XSTATE_PKRU_MASK,
     },
-    [FEAT_XSAVE_COMP_HI] = {
+    [FEAT_XSAVE_XCR0_HI] = {
         .type = CPUID_FEATURE_WORD,
         .cpuid = {
             .eax = 0xD,
@@ -1491,8 +1491,8 @@ static inline bool accel_uses_host_cpuid(void)
 
 static inline uint64_t x86_cpu_xsave_components(X86CPU *cpu)
 {
-    return ((uint64_t)cpu->env.features[FEAT_XSAVE_COMP_HI]) << 32 |
-           cpu->env.features[FEAT_XSAVE_COMP_LO];
+    return ((uint64_t)cpu->env.features[FEAT_XSAVE_XCR0_HI]) << 32 |
+           cpu->env.features[FEAT_XSAVE_XCR0_LO];
 }
 
 const char *get_register_name_32(unsigned int reg)
@@ -4663,8 +4663,8 @@ static const char *x86_cpu_feature_name(FeatureWord w, int bitnr)
     /* XSAVE components are automatically enabled by other features,
      * so return the original feature name instead
      */
-    if (w == FEAT_XSAVE_COMP_LO || w == FEAT_XSAVE_COMP_HI) {
-        int comp = (w == FEAT_XSAVE_COMP_HI) ? bitnr + 32 : bitnr;
+    if (w == FEAT_XSAVE_XCR0_LO || w == FEAT_XSAVE_XCR0_HI) {
+        int comp = (w == FEAT_XSAVE_XCR0_HI) ? bitnr + 32 : bitnr;
 
         if (comp < ARRAY_SIZE(x86_ext_save_areas) &&
             x86_ext_save_areas[comp].bits) {
@@ -5717,8 +5717,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
 
         if (count == 0) {
             *ecx = xsave_area_size(x86_cpu_xsave_components(cpu));
-            *eax = env->features[FEAT_XSAVE_COMP_LO];
-            *edx = env->features[FEAT_XSAVE_COMP_HI];
+            *eax = env->features[FEAT_XSAVE_XCR0_LO];
+            *edx = env->features[FEAT_XSAVE_XCR0_HI];
             /*
              * The initial value of xcr0 and ebx == 0, On host without kvm
              * commit 412a3c41(e.g., CentOS 6), the ebx's value always == 0
@@ -6282,8 +6282,8 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu)
     uint64_t mask;
 
     if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) {
-        env->features[FEAT_XSAVE_COMP_LO] = 0;
-        env->features[FEAT_XSAVE_COMP_HI] = 0;
+        env->features[FEAT_XSAVE_XCR0_LO] = 0;
+        env->features[FEAT_XSAVE_XCR0_HI] = 0;
         return;
     }
 
@@ -6295,8 +6295,8 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu)
         }
     }
 
-    env->features[FEAT_XSAVE_COMP_LO] = mask;
-    env->features[FEAT_XSAVE_COMP_HI] = mask >> 32;
+    env->features[FEAT_XSAVE_XCR0_LO] = mask;
+    env->features[FEAT_XSAVE_XCR0_HI] = mask >> 32;
 }
 
 /***** Steps involved on loading and filtering CPUID data
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 88e8586f8f..52f31335c4 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -527,8 +527,8 @@ typedef enum FeatureWord {
     FEAT_SVM,           /* CPUID[8000_000A].EDX */
     FEAT_XSAVE,         /* CPUID[EAX=0xd,ECX=1].EAX */
     FEAT_6_EAX,         /* CPUID[6].EAX */
-    FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */
-    FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */
+    FEAT_XSAVE_XCR0_LO, /* CPUID[EAX=0xd,ECX=0].EAX */
+    FEAT_XSAVE_XCR0_HI, /* CPUID[EAX=0xd,ECX=0].EDX */
     FEAT_ARCH_CAPABILITIES,
     FEAT_CORE_CAPABILITY,
     FEAT_PERF_CAPABILITIES,
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v7 2/6] target/i386: Enable XSS feature enumeration for CPUID
  2021-02-26  2:20 [PATCH v7 0/6] Enable CET support for guest Yang Weijiang
  2021-02-26  2:20 ` [PATCH v7 1/6] target/i386: Change XSAVE related feature-word names Yang Weijiang
@ 2021-02-26  2:20 ` Yang Weijiang
  2021-05-06 22:16     ` Eduardo Habkost
  2021-02-26  2:20 ` [PATCH v7 3/6] target/i386: Enable CET components support for XSAVES Yang Weijiang
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Yang Weijiang @ 2021-02-26  2:20 UTC (permalink / raw)
  To: pbonzini, richard.henderson, ehabkost, mtosatti,
	sean.j.christopherson, qemu-devel, kvm
  Cc: Yang Weijiang

Currently, CPUID.(EAX=0DH,ECX=01H) doesn't enumerate features in
XSS properly, add the support here. XCR0 bits indicate user-mode XSAVE
components, and XSS bits indicate supervisor-mode XSAVE components.

Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 target/i386/cpu.c | 48 ++++++++++++++++++++++++++++++++++++++++++-----
 target/i386/cpu.h | 12 ++++++++++++
 2 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 89edab4240..f3923988ed 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1058,6 +1058,24 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
         },
         .tcg_features = TCG_XSAVE_FEATURES,
     },
+    [FEAT_XSAVE_XSS_LO] = {
+        .type = CPUID_FEATURE_WORD,
+        .cpuid = {
+            .eax = 0xD,
+            .needs_ecx = true,
+            .ecx = 1,
+            .reg = R_ECX,
+        },
+    },
+    [FEAT_XSAVE_XSS_HI] = {
+        .type = CPUID_FEATURE_WORD,
+        .cpuid = {
+            .eax = 0xD,
+            .needs_ecx = true,
+            .ecx = 1,
+            .reg = R_EDX
+        },
+    },
     [FEAT_6_EAX] = {
         .type = CPUID_FEATURE_WORD,
         .feat_names = {
@@ -1478,6 +1496,9 @@ static uint32_t xsave_area_size(uint64_t mask)
     for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
         const ExtSaveArea *esa = &x86_ext_save_areas[i];
         if ((mask >> i) & 1) {
+            if (i >= 2 && !esa->offset) {
+                continue;
+            }
             ret = MAX(ret, esa->offset + esa->size);
         }
     }
@@ -1489,12 +1510,18 @@ static inline bool accel_uses_host_cpuid(void)
     return kvm_enabled() || hvf_enabled();
 }
 
-static inline uint64_t x86_cpu_xsave_components(X86CPU *cpu)
+static inline uint64_t x86_cpu_xsave_xcr0_components(X86CPU *cpu)
 {
     return ((uint64_t)cpu->env.features[FEAT_XSAVE_XCR0_HI]) << 32 |
            cpu->env.features[FEAT_XSAVE_XCR0_LO];
 }
 
+static inline uint64_t x86_cpu_xsave_xss_components(X86CPU *cpu)
+{
+    return ((uint64_t)cpu->env.features[FEAT_XSAVE_XSS_HI]) << 32 |
+           cpu->env.features[FEAT_XSAVE_XSS_LO];
+}
+
 const char *get_register_name_32(unsigned int reg)
 {
     if (reg >= CPU_NB_REGS32) {
@@ -5716,7 +5743,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         }
 
         if (count == 0) {
-            *ecx = xsave_area_size(x86_cpu_xsave_components(cpu));
+            *ecx = xsave_area_size(x86_cpu_xsave_xcr0_components(cpu));
             *eax = env->features[FEAT_XSAVE_XCR0_LO];
             *edx = env->features[FEAT_XSAVE_XCR0_HI];
             /*
@@ -5728,11 +5755,17 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
             *ebx = kvm_enabled() ? *ecx : xsave_area_size(env->xcr0);
         } else if (count == 1) {
             *eax = env->features[FEAT_XSAVE];
+            *ecx = env->features[FEAT_XSAVE_XSS_LO];
+            *edx = env->features[FEAT_XSAVE_XSS_HI];
         } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {
-            if ((x86_cpu_xsave_components(cpu) >> count) & 1) {
-                const ExtSaveArea *esa = &x86_ext_save_areas[count];
+            const ExtSaveArea *esa = &x86_ext_save_areas[count];
+            if ((x86_cpu_xsave_xcr0_components(cpu) >> count) & 1) {
                 *eax = esa->size;
                 *ebx = esa->offset;
+            } else if ((x86_cpu_xsave_xss_components(cpu) >> count) & 1) {
+                *eax = esa->size;
+                *ebx = 0;
+                *ecx = 1;
             }
         }
         break;
@@ -6059,6 +6092,9 @@ static void x86_cpu_reset(DeviceState *dev)
     }
     for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
         const ExtSaveArea *esa = &x86_ext_save_areas[i];
+        if (!esa->offset) {
+            continue;
+        }
         if (env->features[esa->feature] & esa->bits) {
             xcr0 |= 1ull << i;
         }
@@ -6295,8 +6331,10 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu)
         }
     }
 
-    env->features[FEAT_XSAVE_XCR0_LO] = mask;
+    env->features[FEAT_XSAVE_XCR0_LO] = mask & CPUID_XSTATE_XCR0_MASK;
     env->features[FEAT_XSAVE_XCR0_HI] = mask >> 32;
+    env->features[FEAT_XSAVE_XSS_LO] = mask & CPUID_XSTATE_XSS_MASK;
+    env->features[FEAT_XSAVE_XSS_HI] = mask >> 32;
 }
 
 /***** Steps involved on loading and filtering CPUID data
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 52f31335c4..8aeaa8869a 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -504,6 +504,16 @@ typedef enum X86Seg {
 #define XSTATE_Hi16_ZMM_MASK            (1ULL << XSTATE_Hi16_ZMM_BIT)
 #define XSTATE_PKRU_MASK                (1ULL << XSTATE_PKRU_BIT)
 
+/* CPUID feature bits available in XCR0 */
+#define CPUID_XSTATE_XCR0_MASK  (XSTATE_FP_MASK | XSTATE_SSE_MASK | \
+                                 XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK | \
+                                 XSTATE_BNDCSR_MASK | XSTATE_OPMASK_MASK | \
+                                 XSTATE_ZMM_Hi256_MASK | \
+                                 XSTATE_Hi16_ZMM_MASK | XSTATE_PKRU_MASK)
+
+/* CPUID feature bits available in XSS */
+#define CPUID_XSTATE_XSS_MASK    0
+
 /* CPUID feature words */
 typedef enum FeatureWord {
     FEAT_1_EDX,         /* CPUID[1].EDX */
@@ -541,6 +551,8 @@ typedef enum FeatureWord {
     FEAT_VMX_EPT_VPID_CAPS,
     FEAT_VMX_BASIC,
     FEAT_VMX_VMFUNC,
+    FEAT_XSAVE_XSS_LO,     /* CPUID[EAX=0xd,ECX=1].ECX */
+    FEAT_XSAVE_XSS_HI,     /* CPUID[EAX=0xd,ECX=1].EDX */
     FEATURE_WORDS,
 } FeatureWord;
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v7 3/6] target/i386: Enable CET components support for XSAVES
  2021-02-26  2:20 [PATCH v7 0/6] Enable CET support for guest Yang Weijiang
  2021-02-26  2:20 ` [PATCH v7 1/6] target/i386: Change XSAVE related feature-word names Yang Weijiang
  2021-02-26  2:20 ` [PATCH v7 2/6] target/i386: Enable XSS feature enumeration for CPUID Yang Weijiang
@ 2021-02-26  2:20 ` Yang Weijiang
  2021-02-26  2:20 ` [PATCH v7 4/6] target/i386: Add user-space MSR access interface for CET Yang Weijiang
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Yang Weijiang @ 2021-02-26  2:20 UTC (permalink / raw)
  To: pbonzini, richard.henderson, ehabkost, mtosatti,
	sean.j.christopherson, qemu-devel, kvm
  Cc: Yang Weijiang

CET Shadow Stack(SHSTK) and Indirect Branch Tracking(IBT) are enumerated
via CPUID.(EAX=07H,ECX=0H):ECX[bit 7] and EDX[bit 20] respectively.
Two CET bits (bit 11 and 12) are defined in MSR_IA32_XSS for XSAVES.
They correspond to CET states in user and supervisor mode respectively.

Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 target/i386/cpu.c | 35 +++++++++++++++++++++++++++++++++++
 target/i386/cpu.h | 23 ++++++++++++++++++++++-
 2 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index f3923988ed..ef786b920e 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1060,6 +1060,16 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
     },
     [FEAT_XSAVE_XSS_LO] = {
         .type = CPUID_FEATURE_WORD,
+        .feat_names = {
+            NULL, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
+            NULL, NULL, NULL, "cet-u",
+            "cet-s", NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
+            NULL, NULL, NULL, NULL,
+        },
         .cpuid = {
             .eax = 0xD,
             .needs_ecx = true,
@@ -1486,6 +1496,14 @@ static const ExtSaveArea x86_ext_save_areas[] = {
           { .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_PKU,
             .offset = offsetof(X86XSaveArea, pkru_state),
             .size = sizeof(XSavePKRU) },
+    [XSTATE_CET_U_BIT] = {
+            .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_CET_SHSTK,
+            .offset = 0,
+            .size = sizeof(XSavesCETU) },
+    [XSTATE_CET_S_BIT] = {
+            .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_CET_SHSTK,
+            .offset = 0,
+            .size = sizeof(XSavesCETS) },
 };
 
 static uint32_t xsave_area_size(uint64_t mask)
@@ -6329,6 +6347,23 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu)
         if (env->features[esa->feature] & esa->bits) {
             mask |= (1ULL << i);
         }
+
+        /*
+         * Both CET SHSTK and IBT feature requires XSAVES support, but two
+         * features can be controlled independently by kernel, and we only
+         * have one correlated bit set in x86_ext_save_areas, so if either
+         * of two features is enabled, we set the XSAVES support bit to make
+         * the enabled feature work.
+         */
+        if (i == XSTATE_CET_U_BIT || i == XSTATE_CET_S_BIT) {
+            uint64_t ecx = env->features[FEAT_7_0_ECX];
+            uint64_t edx = env->features[FEAT_7_0_EDX];
+
+            if ((ecx & CPUID_7_0_ECX_CET_SHSTK) ||
+                (edx & CPUID_7_0_EDX_CET_IBT)) {
+                mask |= (1ULL << i);
+            }
+        }
     }
 
     env->features[FEAT_XSAVE_XCR0_LO] = mask & CPUID_XSTATE_XCR0_MASK;
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 8aeaa8869a..a43fb6d597 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -493,6 +493,8 @@ typedef enum X86Seg {
 #define XSTATE_ZMM_Hi256_BIT            6
 #define XSTATE_Hi16_ZMM_BIT             7
 #define XSTATE_PKRU_BIT                 9
+#define XSTATE_CET_U_BIT                11
+#define XSTATE_CET_S_BIT                12
 
 #define XSTATE_FP_MASK                  (1ULL << XSTATE_FP_BIT)
 #define XSTATE_SSE_MASK                 (1ULL << XSTATE_SSE_BIT)
@@ -503,6 +505,8 @@ typedef enum X86Seg {
 #define XSTATE_ZMM_Hi256_MASK           (1ULL << XSTATE_ZMM_Hi256_BIT)
 #define XSTATE_Hi16_ZMM_MASK            (1ULL << XSTATE_Hi16_ZMM_BIT)
 #define XSTATE_PKRU_MASK                (1ULL << XSTATE_PKRU_BIT)
+#define XSTATE_CET_U_MASK               (1ULL << XSTATE_CET_U_BIT)
+#define XSTATE_CET_S_MASK               (1ULL << XSTATE_CET_S_BIT)
 
 /* CPUID feature bits available in XCR0 */
 #define CPUID_XSTATE_XCR0_MASK  (XSTATE_FP_MASK | XSTATE_SSE_MASK | \
@@ -512,7 +516,7 @@ typedef enum X86Seg {
                                  XSTATE_Hi16_ZMM_MASK | XSTATE_PKRU_MASK)
 
 /* CPUID feature bits available in XSS */
-#define CPUID_XSTATE_XSS_MASK    0
+#define CPUID_XSTATE_XSS_MASK    (XSTATE_CET_U_MASK)
 
 /* CPUID feature words */
 typedef enum FeatureWord {
@@ -760,6 +764,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_7_0_ECX_WAITPKG           (1U << 5)
 /* Additional AVX-512 Vector Byte Manipulation Instruction */
 #define CPUID_7_0_ECX_AVX512_VBMI2      (1U << 6)
+/* CET SHSTK feature */
+#define CPUID_7_0_ECX_CET_SHSTK         (1U << 7)
 /* Galois Field New Instructions */
 #define CPUID_7_0_ECX_GFNI              (1U << 8)
 /* Vector AES Instructions */
@@ -795,6 +801,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_7_0_EDX_SERIALIZE         (1U << 14)
 /* TSX Suspend Load Address Tracking instruction */
 #define CPUID_7_0_EDX_TSX_LDTRK         (1U << 16)
+/* CET IBT feature */
+#define CPUID_7_0_EDX_CET_IBT           (1U << 20)
 /* Speculation Control */
 #define CPUID_7_0_EDX_SPEC_CTRL         (1U << 26)
 /* Single Thread Indirect Branch Predictors */
@@ -1285,6 +1293,19 @@ typedef struct XSavePKRU {
     uint32_t padding;
 } XSavePKRU;
 
+/* Ext. save area 11: User mode CET state */
+typedef struct XSavesCETU {
+    uint64_t u_cet;
+    uint64_t user_ssp;
+} XSavesCETU;
+
+/* Ext. save area 12: Supervisor mode CET state */
+typedef struct XSavesCETS {
+    uint64_t kernel_ssp;
+    uint64_t pl1_ssp;
+    uint64_t pl2_ssp;
+} XSavesCETS;
+
 typedef struct X86XSaveArea {
     X86LegacyXSaveArea legacy;
     X86XSaveHeader header;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v7 4/6] target/i386: Add user-space MSR access interface for CET
  2021-02-26  2:20 [PATCH v7 0/6] Enable CET support for guest Yang Weijiang
                   ` (2 preceding siblings ...)
  2021-02-26  2:20 ` [PATCH v7 3/6] target/i386: Enable CET components support for XSAVES Yang Weijiang
@ 2021-02-26  2:20 ` Yang Weijiang
  2021-02-26  2:20 ` [PATCH v7 5/6] target/i386: Add CET state support for guest migration Yang Weijiang
  2021-02-26  2:20 ` [PATCH v7 6/6] target/i386: Advise CET bits in CPU/MSR feature words Yang Weijiang
  5 siblings, 0 replies; 11+ messages in thread
From: Yang Weijiang @ 2021-02-26  2:20 UTC (permalink / raw)
  To: pbonzini, richard.henderson, ehabkost, mtosatti,
	sean.j.christopherson, qemu-devel, kvm
  Cc: Yang Weijiang

CET states are divided into user-mode and supervisor-mode states,
MSR_KVM_GUEST_SSP holds current SHSTK pointer in use, MSR_IA32_U_CET and
MSR_IA32_PL3_SSP are for user-mode states, others are for supervisor-mode
states. Expose access according to current CET supported bits in CPUID
and XSS.

Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 target/i386/cpu.h | 18 ++++++++++++
 target/i386/kvm.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index a43fb6d597..83628e823c 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -484,6 +484,15 @@ typedef enum X86Seg {
 #define MSR_IA32_VMX_TRUE_ENTRY_CTLS     0x00000490
 #define MSR_IA32_VMX_VMFUNC             0x00000491
 
+#define MSR_IA32_U_CET                  0x000006a0
+#define MSR_IA32_S_CET                  0x000006a2
+#define MSR_IA32_PL0_SSP                0x000006a4
+#define MSR_IA32_PL1_SSP                0x000006a5
+#define MSR_IA32_PL2_SSP                0x000006a6
+#define MSR_IA32_PL3_SSP                0x000006a7
+#define MSR_IA32_SSP_TBL                0x000006a8
+#define MSR_KVM_GUEST_SSP               0x4b564d08
+
 #define XSTATE_FP_BIT                   0
 #define XSTATE_SSE_BIT                  1
 #define XSTATE_YMM_BIT                  2
@@ -1584,6 +1593,15 @@ typedef struct CPUX86State {
 
     uintptr_t retaddr;
 
+    uint64_t u_cet;
+    uint64_t s_cet;
+    uint64_t pl0_ssp;
+    uint64_t pl1_ssp;
+    uint64_t pl2_ssp;
+    uint64_t pl3_ssp;
+    uint64_t ssp_tbl;
+    uint64_t guest_ssp;
+
     /* Fields up to this point are cleared by a CPU reset */
     struct {} end_reset_fields;
 
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index a2934dda02..67d5203d19 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -2992,6 +2992,30 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
         }
     }
 
+    if (((env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_CET_SHSTK) ||
+        (env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_CET_IBT)) &&
+        (env->features[FEAT_XSAVE_XSS_LO] & XSTATE_CET_U_MASK)) {
+        kvm_msr_entry_add(cpu, MSR_IA32_U_CET, env->u_cet);
+        kvm_msr_entry_add(cpu, MSR_IA32_PL3_SSP, env->pl3_ssp);
+    }
+
+    if (env->features[FEAT_XSAVE_XSS_LO] & XSTATE_CET_S_MASK) {
+        if (env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_CET_SHSTK) {
+            kvm_msr_entry_add(cpu, MSR_IA32_PL0_SSP, env->pl0_ssp);
+            kvm_msr_entry_add(cpu, MSR_IA32_PL1_SSP, env->pl1_ssp);
+            kvm_msr_entry_add(cpu, MSR_IA32_PL2_SSP, env->pl2_ssp);
+            kvm_msr_entry_add(cpu, MSR_IA32_SSP_TBL, env->ssp_tbl);
+        }
+
+        kvm_msr_entry_add(cpu, MSR_IA32_S_CET, env->s_cet);
+    }
+
+    if ((env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_CET_SHSTK) &&
+        (env->features[FEAT_XSAVE_XSS_LO] & (XSTATE_CET_U_MASK |
+        XSTATE_CET_S_MASK))) {
+        kvm_msr_entry_add(cpu, MSR_KVM_GUEST_SSP, env->guest_ssp);
+    }
+
     return kvm_buf_set_msrs(cpu);
 }
 
@@ -3311,6 +3335,30 @@ static int kvm_get_msrs(X86CPU *cpu)
         }
     }
 
+    if (((env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_CET_SHSTK) ||
+        (env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_CET_IBT)) &&
+        (env->features[FEAT_XSAVE_XSS_LO] & XSTATE_CET_U_MASK)) {
+        kvm_msr_entry_add(cpu, MSR_IA32_U_CET, 0);
+        kvm_msr_entry_add(cpu, MSR_IA32_PL3_SSP, 0);
+    }
+
+    if (env->features[FEAT_XSAVE_XSS_LO] & XSTATE_CET_S_MASK) {
+        if (env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_CET_SHSTK) {
+            kvm_msr_entry_add(cpu, MSR_IA32_PL0_SSP, 0);
+            kvm_msr_entry_add(cpu, MSR_IA32_PL1_SSP, 0);
+            kvm_msr_entry_add(cpu, MSR_IA32_PL2_SSP, 0);
+            kvm_msr_entry_add(cpu, MSR_IA32_SSP_TBL, 0);
+        }
+
+        kvm_msr_entry_add(cpu, MSR_IA32_S_CET, 0);
+    }
+
+    if ((env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_CET_SHSTK) &&
+        (env->features[FEAT_XSAVE_XSS_LO] & (XSTATE_CET_U_MASK |
+        XSTATE_CET_S_MASK))) {
+        kvm_msr_entry_add(cpu, MSR_KVM_GUEST_SSP, 0);
+    }
+
     ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, cpu->kvm_msr_buf);
     if (ret < 0) {
         return ret;
@@ -3597,6 +3645,30 @@ static int kvm_get_msrs(X86CPU *cpu)
         case MSR_IA32_RTIT_ADDR0_A ... MSR_IA32_RTIT_ADDR3_B:
             env->msr_rtit_addrs[index - MSR_IA32_RTIT_ADDR0_A] = msrs[i].data;
             break;
+        case MSR_IA32_U_CET:
+            env->u_cet = msrs[i].data;
+            break;
+        case MSR_IA32_S_CET:
+            env->s_cet = msrs[i].data;
+            break;
+        case MSR_IA32_PL0_SSP:
+            env->pl0_ssp = msrs[i].data;
+            break;
+        case MSR_IA32_PL1_SSP:
+            env->pl1_ssp = msrs[i].data;
+            break;
+        case MSR_IA32_PL2_SSP:
+            env->pl2_ssp = msrs[i].data;
+            break;
+        case MSR_IA32_PL3_SSP:
+            env->pl3_ssp = msrs[i].data;
+            break;
+        case MSR_IA32_SSP_TBL:
+            env->ssp_tbl = msrs[i].data;
+            break;
+        case MSR_KVM_GUEST_SSP:
+            env->guest_ssp = msrs[i].data;
+            break;
         }
     }
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v7 5/6] target/i386: Add CET state support for guest migration
  2021-02-26  2:20 [PATCH v7 0/6] Enable CET support for guest Yang Weijiang
                   ` (3 preceding siblings ...)
  2021-02-26  2:20 ` [PATCH v7 4/6] target/i386: Add user-space MSR access interface for CET Yang Weijiang
@ 2021-02-26  2:20 ` Yang Weijiang
  2021-02-26  2:20 ` [PATCH v7 6/6] target/i386: Advise CET bits in CPU/MSR feature words Yang Weijiang
  5 siblings, 0 replies; 11+ messages in thread
From: Yang Weijiang @ 2021-02-26  2:20 UTC (permalink / raw)
  To: pbonzini, richard.henderson, ehabkost, mtosatti,
	sean.j.christopherson, qemu-devel, kvm
  Cc: Yang Weijiang

Save the MSRs being used on source machine and restore them
on destination machine.

Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 target/i386/machine.c | 161 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 161 insertions(+)

diff --git a/target/i386/machine.c b/target/i386/machine.c
index 233e46bb70..c76a7caeec 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -980,6 +980,159 @@ static const VMStateDescription vmstate_umwait = {
     }
 };
 
+static bool u_cet_needed(void *opaque)
+{
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
+
+    return env->u_cet != 0;
+}
+
+static const VMStateDescription vmstate_u_cet = {
+    .name = "cpu/u_cet",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = u_cet_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(env.u_cet, X86CPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static bool s_cet_needed(void *opaque)
+{
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
+
+    return env->s_cet != 0;
+}
+
+static const VMStateDescription vmstate_s_cet = {
+    .name = "cpu/s_cet",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = s_cet_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(env.s_cet, X86CPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static bool pl0_ssp_needed(void *opaque)
+{
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
+
+    return env->pl0_ssp != 0;
+}
+
+static const VMStateDescription vmstate_pl0_ssp = {
+    .name = "cpu/pl0_ssp",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = pl0_ssp_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(env.pl0_ssp, X86CPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static bool pl1_ssp_needed(void *opaque)
+{
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
+
+    return env->pl1_ssp != 0;
+}
+
+static const VMStateDescription vmstate_pl1_ssp = {
+    .name = "cpu/pl1_ssp",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = pl1_ssp_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(env.pl1_ssp, X86CPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static bool pl2_ssp_needed(void *opaque)
+{
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
+
+    return env->pl2_ssp != 0;
+}
+
+static const VMStateDescription vmstate_pl2_ssp = {
+    .name = "cpu/pl2_ssp",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = pl2_ssp_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(env.pl2_ssp, X86CPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+
+static bool pl3_ssp_needed(void *opaque)
+{
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
+
+    return env->pl3_ssp != 0;
+}
+
+static const VMStateDescription vmstate_pl3_ssp = {
+    .name = "cpu/pl3_ssp",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = pl3_ssp_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(env.pl3_ssp, X86CPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static bool ssp_tbl_needed(void *opaque)
+{
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
+
+    return env->ssp_tbl != 0;
+}
+
+static const VMStateDescription vmstate_ssp_tbl = {
+    .name = "cpu/ssp_tbl",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = ssp_tbl_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(env.ssp_tbl, X86CPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static bool guest_ssp_needed(void *opaque)
+{
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
+
+    return env->guest_ssp != 0;
+}
+
+static const VMStateDescription vmstate_guest_ssp = {
+    .name = "cpu/guest_ssp",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = guest_ssp_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(env.guest_ssp, X86CPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 #ifdef TARGET_X86_64
 static bool pkru_needed(void *opaque)
 {
@@ -1495,6 +1648,14 @@ VMStateDescription vmstate_x86_cpu = {
         &vmstate_nested_state,
 #endif
         &vmstate_msr_tsx_ctrl,
+        &vmstate_u_cet,
+        &vmstate_s_cet,
+        &vmstate_pl0_ssp,
+        &vmstate_pl1_ssp,
+        &vmstate_pl2_ssp,
+        &vmstate_pl3_ssp,
+        &vmstate_ssp_tbl,
+        &vmstate_guest_ssp,
         NULL
     }
 };
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v7 6/6] target/i386: Advise CET bits in CPU/MSR feature words
  2021-02-26  2:20 [PATCH v7 0/6] Enable CET support for guest Yang Weijiang
                   ` (4 preceding siblings ...)
  2021-02-26  2:20 ` [PATCH v7 5/6] target/i386: Add CET state support for guest migration Yang Weijiang
@ 2021-02-26  2:20 ` Yang Weijiang
  5 siblings, 0 replies; 11+ messages in thread
From: Yang Weijiang @ 2021-02-26  2:20 UTC (permalink / raw)
  To: pbonzini, richard.henderson, ehabkost, mtosatti,
	sean.j.christopherson, qemu-devel, kvm
  Cc: Yang Weijiang

CET SHSTK and IBT feature are enumerated via CPUID.(EAX=07H,ECX=0H):ECX[bit 7]
and EDX[bit 20]. CET state load/restore at vmentry/vmexit are enabled via
VMX_ENTRY_CTLS[bit 20] and VMX_EXIT_CTLS[bit 28].

Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 target/i386/cpu.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index ef786b920e..d1dcc7210d 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -954,7 +954,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
         .type = CPUID_FEATURE_WORD,
         .feat_names = {
             NULL, "avx512vbmi", "umip", "pku",
-            NULL /* ospke */, "waitpkg", "avx512vbmi2", NULL,
+            NULL /* ospke */, "waitpkg", "avx512vbmi2", "shstk",
             "gfni", "vaes", "vpclmulqdq", "avx512vnni",
             "avx512bitalg", NULL, "avx512-vpopcntdq", NULL,
             "la57", NULL, NULL, NULL,
@@ -977,7 +977,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
             "avx512-vp2intersect", NULL, "md-clear", NULL,
             NULL, NULL, "serialize", NULL,
             "tsx-ldtrk", NULL, NULL /* pconfig */, NULL,
-            NULL, NULL, NULL, NULL,
+            "ibt", NULL, NULL, NULL,
             NULL, NULL, "spec-ctrl", "stibp",
             NULL, "arch-capabilities", "core-capability", "ssbd",
         },
@@ -1239,7 +1239,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
             "vmx-exit-save-efer", "vmx-exit-load-efer",
                 "vmx-exit-save-preemption-timer", "vmx-exit-clear-bndcfgs",
             NULL, "vmx-exit-clear-rtit-ctl", NULL, NULL,
-            NULL, NULL, NULL, NULL,
+            "vmx-exit-save-cet-ctl", NULL, NULL, NULL,
         },
         .msr = {
             .index = MSR_IA32_VMX_TRUE_EXIT_CTLS,
@@ -1254,7 +1254,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
             NULL, "vmx-entry-ia32e-mode", NULL, NULL,
             NULL, "vmx-entry-load-perf-global-ctrl", "vmx-entry-load-pat", "vmx-entry-load-efer",
             "vmx-entry-load-bndcfgs", NULL, "vmx-entry-load-rtit-ctl", NULL,
-            NULL, NULL, NULL, NULL,
+            "vmx-entry-load-cet-ctl", NULL, NULL, NULL,
             NULL, NULL, NULL, NULL,
             NULL, NULL, NULL, NULL,
         },
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v7 2/6] target/i386: Enable XSS feature enumeration for CPUID
  2021-02-26  2:20 ` [PATCH v7 2/6] target/i386: Enable XSS feature enumeration for CPUID Yang Weijiang
@ 2021-05-06 22:16     ` Eduardo Habkost
  0 siblings, 0 replies; 11+ messages in thread
From: Eduardo Habkost @ 2021-05-06 22:16 UTC (permalink / raw)
  To: Yang Weijiang
  Cc: pbonzini, richard.henderson, mtosatti, sean.j.christopherson,
	qemu-devel, kvm

On Fri, Feb 26, 2021 at 10:20:54AM +0800, Yang Weijiang wrote:
> Currently, CPUID.(EAX=0DH,ECX=01H) doesn't enumerate features in
> XSS properly, add the support here. XCR0 bits indicate user-mode XSAVE
> components, and XSS bits indicate supervisor-mode XSAVE components.
> 
> Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
> ---
>  target/i386/cpu.c | 48 ++++++++++++++++++++++++++++++++++++++++++-----
>  target/i386/cpu.h | 12 ++++++++++++
>  2 files changed, 55 insertions(+), 5 deletions(-)
> 
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 89edab4240..f3923988ed 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -1058,6 +1058,24 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
>          },
>          .tcg_features = TCG_XSAVE_FEATURES,
>      },
> +    [FEAT_XSAVE_XSS_LO] = {
> +        .type = CPUID_FEATURE_WORD,
> +        .cpuid = {
> +            .eax = 0xD,
> +            .needs_ecx = true,
> +            .ecx = 1,
> +            .reg = R_ECX,
> +        },
> +    },
> +    [FEAT_XSAVE_XSS_HI] = {
> +        .type = CPUID_FEATURE_WORD,
> +        .cpuid = {
> +            .eax = 0xD,
> +            .needs_ecx = true,
> +            .ecx = 1,
> +            .reg = R_EDX
> +        },
> +    },
>      [FEAT_6_EAX] = {
>          .type = CPUID_FEATURE_WORD,
>          .feat_names = {
> @@ -1478,6 +1496,9 @@ static uint32_t xsave_area_size(uint64_t mask)
>      for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
>          const ExtSaveArea *esa = &x86_ext_save_areas[i];
>          if ((mask >> i) & 1) {
> +            if (i >= 2 && !esa->offset) {

Maybe a few comments at the definition of ExtSaveArea to explain
that offset can now be zero (and what it means when it's zero)
would be helpful.  I took a while to understand why this is safe.

Would it be valid to say "ExtSaveArea.offset has a valid offset
only if the component is in CPUID_XSTATE_XCR0_MASK"?  If so,
can't this check be simply replaced with:
  if ((1 << i) & CPUID_XSTATE_XCR0_MASK)
?

Or maybe this function should just contain a:
  assert(!(mask & CPUID_XSTATE_XCR0_MASK));
at the beginning?


> +                continue;
> +            }
>              ret = MAX(ret, esa->offset + esa->size);
>          }
>      }
> @@ -1489,12 +1510,18 @@ static inline bool accel_uses_host_cpuid(void)
>      return kvm_enabled() || hvf_enabled();
>  }
>  
> -static inline uint64_t x86_cpu_xsave_components(X86CPU *cpu)
> +static inline uint64_t x86_cpu_xsave_xcr0_components(X86CPU *cpu)
>  {
>      return ((uint64_t)cpu->env.features[FEAT_XSAVE_XCR0_HI]) << 32 |
>             cpu->env.features[FEAT_XSAVE_XCR0_LO];
>  }
>  
> +static inline uint64_t x86_cpu_xsave_xss_components(X86CPU *cpu)
> +{
> +    return ((uint64_t)cpu->env.features[FEAT_XSAVE_XSS_HI]) << 32 |
> +           cpu->env.features[FEAT_XSAVE_XSS_LO];
> +}
> +
>  const char *get_register_name_32(unsigned int reg)
>  {
>      if (reg >= CPU_NB_REGS32) {
> @@ -5716,7 +5743,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
>          }
>  
>          if (count == 0) {
> -            *ecx = xsave_area_size(x86_cpu_xsave_components(cpu));
> +            *ecx = xsave_area_size(x86_cpu_xsave_xcr0_components(cpu));
>              *eax = env->features[FEAT_XSAVE_XCR0_LO];
>              *edx = env->features[FEAT_XSAVE_XCR0_HI];
>              /*
> @@ -5728,11 +5755,17 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
>              *ebx = kvm_enabled() ? *ecx : xsave_area_size(env->xcr0);
>          } else if (count == 1) {
>              *eax = env->features[FEAT_XSAVE];
> +            *ecx = env->features[FEAT_XSAVE_XSS_LO];
> +            *edx = env->features[FEAT_XSAVE_XSS_HI];

What about EBX?  It is documented as "The size in bytes of the
XSAVE area containing all states enabled by XCRO | IA32_XSS".

The Intel SDM is not clear, but I assume this would be
necessarily the size of the area in compacted format?


>          } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {
> -            if ((x86_cpu_xsave_components(cpu) >> count) & 1) {
> -                const ExtSaveArea *esa = &x86_ext_save_areas[count];
> +            const ExtSaveArea *esa = &x86_ext_save_areas[count];
> +            if ((x86_cpu_xsave_xcr0_components(cpu) >> count) & 1) {
>                  *eax = esa->size;
>                  *ebx = esa->offset;
> +            } else if ((x86_cpu_xsave_xss_components(cpu) >> count) & 1) {
> +                *eax = esa->size;
> +                *ebx = 0;
> +                *ecx = 1;
>              }
>          }
>          break;
> @@ -6059,6 +6092,9 @@ static void x86_cpu_reset(DeviceState *dev)
>      }
>      for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
>          const ExtSaveArea *esa = &x86_ext_save_areas[i];
> +        if (!esa->offset) {
> +            continue;

Most of the comments at the xsave_area_size() hunk would apply
here.  I miss some clarity on what esa->offset==0 really means.

Would it be valid to replace this with a check for
  ((1 << i) & CPUID_XSTATE_XCR0_MASK)
?

> +        }
>          if (env->features[esa->feature] & esa->bits) {
>              xcr0 |= 1ull << i;
>          }
> @@ -6295,8 +6331,10 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu)
>          }
>      }
>  
> -    env->features[FEAT_XSAVE_XCR0_LO] = mask;
> +    env->features[FEAT_XSAVE_XCR0_LO] = mask & CPUID_XSTATE_XCR0_MASK;
>      env->features[FEAT_XSAVE_XCR0_HI] = mask >> 32;
> +    env->features[FEAT_XSAVE_XSS_LO] = mask & CPUID_XSTATE_XSS_MASK;
> +    env->features[FEAT_XSAVE_XSS_HI] = mask >> 32;
>  }
>  
>  /***** Steps involved on loading and filtering CPUID data
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index 52f31335c4..8aeaa8869a 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -504,6 +504,16 @@ typedef enum X86Seg {
>  #define XSTATE_Hi16_ZMM_MASK            (1ULL << XSTATE_Hi16_ZMM_BIT)
>  #define XSTATE_PKRU_MASK                (1ULL << XSTATE_PKRU_BIT)
>  
> +/* CPUID feature bits available in XCR0 */
> +#define CPUID_XSTATE_XCR0_MASK  (XSTATE_FP_MASK | XSTATE_SSE_MASK | \
> +                                 XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK | \
> +                                 XSTATE_BNDCSR_MASK | XSTATE_OPMASK_MASK | \
> +                                 XSTATE_ZMM_Hi256_MASK | \
> +                                 XSTATE_Hi16_ZMM_MASK | XSTATE_PKRU_MASK)
> +
> +/* CPUID feature bits available in XSS */
> +#define CPUID_XSTATE_XSS_MASK    0

Do you expect this to be used outside target/i386/cpu.c?  If not,
maybe it could be moved close to the x86_ext_save_areas[]
definition, as any updates to x86_ext_save_areas will require an
update to these macros.

> +
>  /* CPUID feature words */
>  typedef enum FeatureWord {
>      FEAT_1_EDX,         /* CPUID[1].EDX */
> @@ -541,6 +551,8 @@ typedef enum FeatureWord {
>      FEAT_VMX_EPT_VPID_CAPS,
>      FEAT_VMX_BASIC,
>      FEAT_VMX_VMFUNC,
> +    FEAT_XSAVE_XSS_LO,     /* CPUID[EAX=0xd,ECX=1].ECX */
> +    FEAT_XSAVE_XSS_HI,     /* CPUID[EAX=0xd,ECX=1].EDX */
>      FEATURE_WORDS,
>  } FeatureWord;
>  
> -- 
> 2.26.2
> 
> 

-- 
Eduardo


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v7 2/6] target/i386: Enable XSS feature enumeration for CPUID
@ 2021-05-06 22:16     ` Eduardo Habkost
  0 siblings, 0 replies; 11+ messages in thread
From: Eduardo Habkost @ 2021-05-06 22:16 UTC (permalink / raw)
  To: Yang Weijiang
  Cc: kvm, mtosatti, richard.henderson, qemu-devel,
	sean.j.christopherson, pbonzini

On Fri, Feb 26, 2021 at 10:20:54AM +0800, Yang Weijiang wrote:
> Currently, CPUID.(EAX=0DH,ECX=01H) doesn't enumerate features in
> XSS properly, add the support here. XCR0 bits indicate user-mode XSAVE
> components, and XSS bits indicate supervisor-mode XSAVE components.
> 
> Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
> ---
>  target/i386/cpu.c | 48 ++++++++++++++++++++++++++++++++++++++++++-----
>  target/i386/cpu.h | 12 ++++++++++++
>  2 files changed, 55 insertions(+), 5 deletions(-)
> 
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 89edab4240..f3923988ed 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -1058,6 +1058,24 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
>          },
>          .tcg_features = TCG_XSAVE_FEATURES,
>      },
> +    [FEAT_XSAVE_XSS_LO] = {
> +        .type = CPUID_FEATURE_WORD,
> +        .cpuid = {
> +            .eax = 0xD,
> +            .needs_ecx = true,
> +            .ecx = 1,
> +            .reg = R_ECX,
> +        },
> +    },
> +    [FEAT_XSAVE_XSS_HI] = {
> +        .type = CPUID_FEATURE_WORD,
> +        .cpuid = {
> +            .eax = 0xD,
> +            .needs_ecx = true,
> +            .ecx = 1,
> +            .reg = R_EDX
> +        },
> +    },
>      [FEAT_6_EAX] = {
>          .type = CPUID_FEATURE_WORD,
>          .feat_names = {
> @@ -1478,6 +1496,9 @@ static uint32_t xsave_area_size(uint64_t mask)
>      for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
>          const ExtSaveArea *esa = &x86_ext_save_areas[i];
>          if ((mask >> i) & 1) {
> +            if (i >= 2 && !esa->offset) {

Maybe a few comments at the definition of ExtSaveArea to explain
that offset can now be zero (and what it means when it's zero)
would be helpful.  I took a while to understand why this is safe.

Would it be valid to say "ExtSaveArea.offset has a valid offset
only if the component is in CPUID_XSTATE_XCR0_MASK"?  If so,
can't this check be simply replaced with:
  if ((1 << i) & CPUID_XSTATE_XCR0_MASK)
?

Or maybe this function should just contain a:
  assert(!(mask & CPUID_XSTATE_XCR0_MASK));
at the beginning?


> +                continue;
> +            }
>              ret = MAX(ret, esa->offset + esa->size);
>          }
>      }
> @@ -1489,12 +1510,18 @@ static inline bool accel_uses_host_cpuid(void)
>      return kvm_enabled() || hvf_enabled();
>  }
>  
> -static inline uint64_t x86_cpu_xsave_components(X86CPU *cpu)
> +static inline uint64_t x86_cpu_xsave_xcr0_components(X86CPU *cpu)
>  {
>      return ((uint64_t)cpu->env.features[FEAT_XSAVE_XCR0_HI]) << 32 |
>             cpu->env.features[FEAT_XSAVE_XCR0_LO];
>  }
>  
> +static inline uint64_t x86_cpu_xsave_xss_components(X86CPU *cpu)
> +{
> +    return ((uint64_t)cpu->env.features[FEAT_XSAVE_XSS_HI]) << 32 |
> +           cpu->env.features[FEAT_XSAVE_XSS_LO];
> +}
> +
>  const char *get_register_name_32(unsigned int reg)
>  {
>      if (reg >= CPU_NB_REGS32) {
> @@ -5716,7 +5743,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
>          }
>  
>          if (count == 0) {
> -            *ecx = xsave_area_size(x86_cpu_xsave_components(cpu));
> +            *ecx = xsave_area_size(x86_cpu_xsave_xcr0_components(cpu));
>              *eax = env->features[FEAT_XSAVE_XCR0_LO];
>              *edx = env->features[FEAT_XSAVE_XCR0_HI];
>              /*
> @@ -5728,11 +5755,17 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
>              *ebx = kvm_enabled() ? *ecx : xsave_area_size(env->xcr0);
>          } else if (count == 1) {
>              *eax = env->features[FEAT_XSAVE];
> +            *ecx = env->features[FEAT_XSAVE_XSS_LO];
> +            *edx = env->features[FEAT_XSAVE_XSS_HI];

What about EBX?  It is documented as "The size in bytes of the
XSAVE area containing all states enabled by XCRO | IA32_XSS".

The Intel SDM is not clear, but I assume this would be
necessarily the size of the area in compacted format?


>          } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {
> -            if ((x86_cpu_xsave_components(cpu) >> count) & 1) {
> -                const ExtSaveArea *esa = &x86_ext_save_areas[count];
> +            const ExtSaveArea *esa = &x86_ext_save_areas[count];
> +            if ((x86_cpu_xsave_xcr0_components(cpu) >> count) & 1) {
>                  *eax = esa->size;
>                  *ebx = esa->offset;
> +            } else if ((x86_cpu_xsave_xss_components(cpu) >> count) & 1) {
> +                *eax = esa->size;
> +                *ebx = 0;
> +                *ecx = 1;
>              }
>          }
>          break;
> @@ -6059,6 +6092,9 @@ static void x86_cpu_reset(DeviceState *dev)
>      }
>      for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
>          const ExtSaveArea *esa = &x86_ext_save_areas[i];
> +        if (!esa->offset) {
> +            continue;

Most of the comments at the xsave_area_size() hunk would apply
here.  I miss some clarity on what esa->offset==0 really means.

Would it be valid to replace this with a check for
  ((1 << i) & CPUID_XSTATE_XCR0_MASK)
?

> +        }
>          if (env->features[esa->feature] & esa->bits) {
>              xcr0 |= 1ull << i;
>          }
> @@ -6295,8 +6331,10 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu)
>          }
>      }
>  
> -    env->features[FEAT_XSAVE_XCR0_LO] = mask;
> +    env->features[FEAT_XSAVE_XCR0_LO] = mask & CPUID_XSTATE_XCR0_MASK;
>      env->features[FEAT_XSAVE_XCR0_HI] = mask >> 32;
> +    env->features[FEAT_XSAVE_XSS_LO] = mask & CPUID_XSTATE_XSS_MASK;
> +    env->features[FEAT_XSAVE_XSS_HI] = mask >> 32;
>  }
>  
>  /***** Steps involved on loading and filtering CPUID data
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index 52f31335c4..8aeaa8869a 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -504,6 +504,16 @@ typedef enum X86Seg {
>  #define XSTATE_Hi16_ZMM_MASK            (1ULL << XSTATE_Hi16_ZMM_BIT)
>  #define XSTATE_PKRU_MASK                (1ULL << XSTATE_PKRU_BIT)
>  
> +/* CPUID feature bits available in XCR0 */
> +#define CPUID_XSTATE_XCR0_MASK  (XSTATE_FP_MASK | XSTATE_SSE_MASK | \
> +                                 XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK | \
> +                                 XSTATE_BNDCSR_MASK | XSTATE_OPMASK_MASK | \
> +                                 XSTATE_ZMM_Hi256_MASK | \
> +                                 XSTATE_Hi16_ZMM_MASK | XSTATE_PKRU_MASK)
> +
> +/* CPUID feature bits available in XSS */
> +#define CPUID_XSTATE_XSS_MASK    0

Do you expect this to be used outside target/i386/cpu.c?  If not,
maybe it could be moved close to the x86_ext_save_areas[]
definition, as any updates to x86_ext_save_areas will require an
update to these macros.

> +
>  /* CPUID feature words */
>  typedef enum FeatureWord {
>      FEAT_1_EDX,         /* CPUID[1].EDX */
> @@ -541,6 +551,8 @@ typedef enum FeatureWord {
>      FEAT_VMX_EPT_VPID_CAPS,
>      FEAT_VMX_BASIC,
>      FEAT_VMX_VMFUNC,
> +    FEAT_XSAVE_XSS_LO,     /* CPUID[EAX=0xd,ECX=1].ECX */
> +    FEAT_XSAVE_XSS_HI,     /* CPUID[EAX=0xd,ECX=1].EDX */
>      FEATURE_WORDS,
>  } FeatureWord;
>  
> -- 
> 2.26.2
> 
> 

-- 
Eduardo



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v7 2/6] target/i386: Enable XSS feature enumeration for CPUID
  2021-05-06 22:16     ` Eduardo Habkost
@ 2021-05-07  6:25       ` Yang Weijiang
  -1 siblings, 0 replies; 11+ messages in thread
From: Yang Weijiang @ 2021-05-07  6:25 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Yang Weijiang, pbonzini, richard.henderson, mtosatti,
	sean.j.christopherson, qemu-devel, kvm

On Thu, May 06, 2021 at 06:16:47PM -0400, Eduardo Habkost wrote:
> On Fri, Feb 26, 2021 at 10:20:54AM +0800, Yang Weijiang wrote:
> > Currently, CPUID.(EAX=0DH,ECX=01H) doesn't enumerate features in
> > XSS properly, add the support here. XCR0 bits indicate user-mode XSAVE
> > components, and XSS bits indicate supervisor-mode XSAVE components.
> > 
> > Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
> > ---
> >  target/i386/cpu.c | 48 ++++++++++++++++++++++++++++++++++++++++++-----
> >  target/i386/cpu.h | 12 ++++++++++++
> >  2 files changed, 55 insertions(+), 5 deletions(-)
> >
 
[...]

> > @@ -1478,6 +1496,9 @@ static uint32_t xsave_area_size(uint64_t mask)
> >      for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
> >          const ExtSaveArea *esa = &x86_ext_save_areas[i];
> >          if ((mask >> i) & 1) {
> > +            if (i >= 2 && !esa->offset) {
> 
> Maybe a few comments at the definition of ExtSaveArea to explain
> that offset can now be zero (and what it means when it's zero)
> would be helpful.  I took a while to understand why this is safe.
>
Thanks Eduardo!

Sure, I'll add some comments in next version.
 
> Would it be valid to say "ExtSaveArea.offset has a valid offset
> only if the component is in CPUID_XSTATE_XCR0_MASK"?  If so,
> can't this check be simply replaced with:
>   if ((1 << i) & CPUID_XSTATE_XCR0_MASK)
> ?
> 
> Or maybe this function should just contain a:
>   assert(!(mask & CPUID_XSTATE_XCR0_MASK));
> at the beginning?
> 

Maybe I need to modifiy the function a bit to accommodate compacted format
size calculation for CPUID(0xD,1).EBX.
> 
> > +                continue;
> > +            }
> >              ret = MAX(ret, esa->offset + esa->size);
> >          }
> >      }
> > @@ -1489,12 +1510,18 @@ static inline bool accel_uses_host_cpuid(void)
> >      return kvm_enabled() || hvf_enabled();
> >  }

[...]

> >  
> > @@ -5716,7 +5743,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
> >          }
> >  
> >          if (count == 0) {
> > -            *ecx = xsave_area_size(x86_cpu_xsave_components(cpu));
> > +            *ecx = xsave_area_size(x86_cpu_xsave_xcr0_components(cpu));
> >              *eax = env->features[FEAT_XSAVE_XCR0_LO];
> >              *edx = env->features[FEAT_XSAVE_XCR0_HI];
> >              /*
> > @@ -5728,11 +5755,17 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
> >              *ebx = kvm_enabled() ? *ecx : xsave_area_size(env->xcr0);
> >          } else if (count == 1) {
> >              *eax = env->features[FEAT_XSAVE];
> > +            *ecx = env->features[FEAT_XSAVE_XSS_LO];
> > +            *edx = env->features[FEAT_XSAVE_XSS_HI];
> 
> What about EBX?  It is documented as "The size in bytes of the
> XSAVE area containing all states enabled by XCRO | IA32_XSS".
> 
> The Intel SDM is not clear, but I assume this would be
> necessarily the size of the area in compacted format?

Yes, I'll add ebx assignment.
> 
> 
> >          } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {
> > -            if ((x86_cpu_xsave_components(cpu) >> count) & 1) {
> > -                const ExtSaveArea *esa = &x86_ext_save_areas[count];
> > +            const ExtSaveArea *esa = &x86_ext_save_areas[count];
> > +            if ((x86_cpu_xsave_xcr0_components(cpu) >> count) & 1) {
> >                  *eax = esa->size;
> >                  *ebx = esa->offset;
> > +            } else if ((x86_cpu_xsave_xss_components(cpu) >> count) & 1) {
> > +                *eax = esa->size;
> > +                *ebx = 0;
> > +                *ecx = 1;
> >              }
> >          }
> >          break;
> > @@ -6059,6 +6092,9 @@ static void x86_cpu_reset(DeviceState *dev)
> >      }
> >      for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
> >          const ExtSaveArea *esa = &x86_ext_save_areas[i];
> > +        if (!esa->offset) {
> > +            continue;
> 
> Most of the comments at the xsave_area_size() hunk would apply
> here.  I miss some clarity on what esa->offset==0 really means.
> 
> Would it be valid to replace this with a check for
>   ((1 << i) & CPUID_XSTATE_XCR0_MASK)
> ?

Sure, I'll use this check to make things clearer, thanks for the comments!

> 
> > +        }
> >          if (env->features[esa->feature] & esa->bits) {
> >              xcr0 |= 1ull << i;
> >          }

[...]
  
> > +/* CPUID feature bits available in XCR0 */
> > +#define CPUID_XSTATE_XCR0_MASK  (XSTATE_FP_MASK | XSTATE_SSE_MASK | \
> > +                                 XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK | \
> > +                                 XSTATE_BNDCSR_MASK | XSTATE_OPMASK_MASK | \
> > +                                 XSTATE_ZMM_Hi256_MASK | \
> > +                                 XSTATE_Hi16_ZMM_MASK | XSTATE_PKRU_MASK)
> > +
> > +/* CPUID feature bits available in XSS */
> > +#define CPUID_XSTATE_XSS_MASK    0
> 
> Do you expect this to be used outside target/i386/cpu.c?  If not,
> maybe it could be moved close to the x86_ext_save_areas[]
> definition, as any updates to x86_ext_save_areas will require an
> update to these macros.
> 
> > +
> >  /* CPUID feature words */
> >  typedef enum FeatureWord {
> >      FEAT_1_EDX,         /* CPUID[1].EDX */
> > @@ -541,6 +551,8 @@ typedef enum FeatureWord {
> >      FEAT_VMX_EPT_VPID_CAPS,
> >      FEAT_VMX_BASIC,
> >      FEAT_VMX_VMFUNC,
> > +    FEAT_XSAVE_XSS_LO,     /* CPUID[EAX=0xd,ECX=1].ECX */
> > +    FEAT_XSAVE_XSS_HI,     /* CPUID[EAX=0xd,ECX=1].EDX */
> >      FEATURE_WORDS,
> >  } FeatureWord;
> >  
> > -- 
> > 2.26.2
> > 
> > 
> 
> -- 
> Eduardo

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v7 2/6] target/i386: Enable XSS feature enumeration for CPUID
@ 2021-05-07  6:25       ` Yang Weijiang
  0 siblings, 0 replies; 11+ messages in thread
From: Yang Weijiang @ 2021-05-07  6:25 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: kvm, mtosatti, richard.henderson, qemu-devel,
	sean.j.christopherson, Yang Weijiang, pbonzini

On Thu, May 06, 2021 at 06:16:47PM -0400, Eduardo Habkost wrote:
> On Fri, Feb 26, 2021 at 10:20:54AM +0800, Yang Weijiang wrote:
> > Currently, CPUID.(EAX=0DH,ECX=01H) doesn't enumerate features in
> > XSS properly, add the support here. XCR0 bits indicate user-mode XSAVE
> > components, and XSS bits indicate supervisor-mode XSAVE components.
> > 
> > Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
> > ---
> >  target/i386/cpu.c | 48 ++++++++++++++++++++++++++++++++++++++++++-----
> >  target/i386/cpu.h | 12 ++++++++++++
> >  2 files changed, 55 insertions(+), 5 deletions(-)
> >
 
[...]

> > @@ -1478,6 +1496,9 @@ static uint32_t xsave_area_size(uint64_t mask)
> >      for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
> >          const ExtSaveArea *esa = &x86_ext_save_areas[i];
> >          if ((mask >> i) & 1) {
> > +            if (i >= 2 && !esa->offset) {
> 
> Maybe a few comments at the definition of ExtSaveArea to explain
> that offset can now be zero (and what it means when it's zero)
> would be helpful.  I took a while to understand why this is safe.
>
Thanks Eduardo!

Sure, I'll add some comments in next version.
 
> Would it be valid to say "ExtSaveArea.offset has a valid offset
> only if the component is in CPUID_XSTATE_XCR0_MASK"?  If so,
> can't this check be simply replaced with:
>   if ((1 << i) & CPUID_XSTATE_XCR0_MASK)
> ?
> 
> Or maybe this function should just contain a:
>   assert(!(mask & CPUID_XSTATE_XCR0_MASK));
> at the beginning?
> 

Maybe I need to modifiy the function a bit to accommodate compacted format
size calculation for CPUID(0xD,1).EBX.
> 
> > +                continue;
> > +            }
> >              ret = MAX(ret, esa->offset + esa->size);
> >          }
> >      }
> > @@ -1489,12 +1510,18 @@ static inline bool accel_uses_host_cpuid(void)
> >      return kvm_enabled() || hvf_enabled();
> >  }

[...]

> >  
> > @@ -5716,7 +5743,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
> >          }
> >  
> >          if (count == 0) {
> > -            *ecx = xsave_area_size(x86_cpu_xsave_components(cpu));
> > +            *ecx = xsave_area_size(x86_cpu_xsave_xcr0_components(cpu));
> >              *eax = env->features[FEAT_XSAVE_XCR0_LO];
> >              *edx = env->features[FEAT_XSAVE_XCR0_HI];
> >              /*
> > @@ -5728,11 +5755,17 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
> >              *ebx = kvm_enabled() ? *ecx : xsave_area_size(env->xcr0);
> >          } else if (count == 1) {
> >              *eax = env->features[FEAT_XSAVE];
> > +            *ecx = env->features[FEAT_XSAVE_XSS_LO];
> > +            *edx = env->features[FEAT_XSAVE_XSS_HI];
> 
> What about EBX?  It is documented as "The size in bytes of the
> XSAVE area containing all states enabled by XCRO | IA32_XSS".
> 
> The Intel SDM is not clear, but I assume this would be
> necessarily the size of the area in compacted format?

Yes, I'll add ebx assignment.
> 
> 
> >          } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {
> > -            if ((x86_cpu_xsave_components(cpu) >> count) & 1) {
> > -                const ExtSaveArea *esa = &x86_ext_save_areas[count];
> > +            const ExtSaveArea *esa = &x86_ext_save_areas[count];
> > +            if ((x86_cpu_xsave_xcr0_components(cpu) >> count) & 1) {
> >                  *eax = esa->size;
> >                  *ebx = esa->offset;
> > +            } else if ((x86_cpu_xsave_xss_components(cpu) >> count) & 1) {
> > +                *eax = esa->size;
> > +                *ebx = 0;
> > +                *ecx = 1;
> >              }
> >          }
> >          break;
> > @@ -6059,6 +6092,9 @@ static void x86_cpu_reset(DeviceState *dev)
> >      }
> >      for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
> >          const ExtSaveArea *esa = &x86_ext_save_areas[i];
> > +        if (!esa->offset) {
> > +            continue;
> 
> Most of the comments at the xsave_area_size() hunk would apply
> here.  I miss some clarity on what esa->offset==0 really means.
> 
> Would it be valid to replace this with a check for
>   ((1 << i) & CPUID_XSTATE_XCR0_MASK)
> ?

Sure, I'll use this check to make things clearer, thanks for the comments!

> 
> > +        }
> >          if (env->features[esa->feature] & esa->bits) {
> >              xcr0 |= 1ull << i;
> >          }

[...]
  
> > +/* CPUID feature bits available in XCR0 */
> > +#define CPUID_XSTATE_XCR0_MASK  (XSTATE_FP_MASK | XSTATE_SSE_MASK | \
> > +                                 XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK | \
> > +                                 XSTATE_BNDCSR_MASK | XSTATE_OPMASK_MASK | \
> > +                                 XSTATE_ZMM_Hi256_MASK | \
> > +                                 XSTATE_Hi16_ZMM_MASK | XSTATE_PKRU_MASK)
> > +
> > +/* CPUID feature bits available in XSS */
> > +#define CPUID_XSTATE_XSS_MASK    0
> 
> Do you expect this to be used outside target/i386/cpu.c?  If not,
> maybe it could be moved close to the x86_ext_save_areas[]
> definition, as any updates to x86_ext_save_areas will require an
> update to these macros.
> 
> > +
> >  /* CPUID feature words */
> >  typedef enum FeatureWord {
> >      FEAT_1_EDX,         /* CPUID[1].EDX */
> > @@ -541,6 +551,8 @@ typedef enum FeatureWord {
> >      FEAT_VMX_EPT_VPID_CAPS,
> >      FEAT_VMX_BASIC,
> >      FEAT_VMX_VMFUNC,
> > +    FEAT_XSAVE_XSS_LO,     /* CPUID[EAX=0xd,ECX=1].ECX */
> > +    FEAT_XSAVE_XSS_HI,     /* CPUID[EAX=0xd,ECX=1].EDX */
> >      FEATURE_WORDS,
> >  } FeatureWord;
> >  
> > -- 
> > 2.26.2
> > 
> > 
> 
> -- 
> Eduardo


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2021-05-07  6:12 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-26  2:20 [PATCH v7 0/6] Enable CET support for guest Yang Weijiang
2021-02-26  2:20 ` [PATCH v7 1/6] target/i386: Change XSAVE related feature-word names Yang Weijiang
2021-02-26  2:20 ` [PATCH v7 2/6] target/i386: Enable XSS feature enumeration for CPUID Yang Weijiang
2021-05-06 22:16   ` Eduardo Habkost
2021-05-06 22:16     ` Eduardo Habkost
2021-05-07  6:25     ` Yang Weijiang
2021-05-07  6:25       ` Yang Weijiang
2021-02-26  2:20 ` [PATCH v7 3/6] target/i386: Enable CET components support for XSAVES Yang Weijiang
2021-02-26  2:20 ` [PATCH v7 4/6] target/i386: Add user-space MSR access interface for CET Yang Weijiang
2021-02-26  2:20 ` [PATCH v7 5/6] target/i386: Add CET state support for guest migration Yang Weijiang
2021-02-26  2:20 ` [PATCH v7 6/6] target/i386: Advise CET bits in CPU/MSR feature words Yang Weijiang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.