All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel][PATCH v5 0/4] Enable CET support for guest
@ 2020-05-10  1:42 Yang Weijiang
  2020-05-10  1:42 ` [Qemu-devel][PATCH v5 1/4] x86/cpu: Add CET CPUID/XSAVES flags and data structures Yang Weijiang
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Yang Weijiang @ 2020-05-10  1:42 UTC (permalink / raw)
  To: qemu-devel, pbonzini; +Cc: Yang Weijiang

Control-flow Enforcement Technology (CET) provides protection against 
return/jump-oriented programming (ROP/JOP). It includes two
sub-features: Shadow Stack(SHSTK) and Indirect Branch Tracking(IBT).
This patchset is to enable CET related CPUID report, XSAVES/XRSTORS
support and MSR access etc. for guest.

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

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

v5:
  - Checked CET states before access related MSRs.
  - Added new MSR MSR_KVM_GUEST_SSP for live-migration.
  - Refactored patches to make them more structured.

v4:
  - Added MSR read/write interface for PL1_SSP/PL2_SSP.
  - Removed CET structures from X86XSaveArea.
  - Cleared ebx in return of CPUID.(EAX=d, ECX=1).
 
v3:
  - Add CET MSR save/restore support for live-migration.
 
v2:
  - In CPUID.(EAX=d, ECX=1), set return ECX[n] = 0 if bit n corresponds
    to a bit in MSR_IA32_XSS.
  - In CPUID.(EAX=d, ECX=n), set return ECX = 1 if bit n corresponds
    to a bit in MSR_IA32_XSS.
  - Skip Supervisor mode xsave component when calculate User mode
    xave component size in xsave_area_size() and x86_cpu_reset().

Yang Weijiang (4):
  x86/cpu: Add CET CPUID/XSAVES flags and data structures
  x86/cpuid: Add XSAVES feature words and CET related state bits
  x86/cpuid: Add support for XSAVES dependent feature enumeration
  x86/cpu: Add user space access interface for CET MSRs

 target/i386/cpu.c     |  57 ++++++++++++++-
 target/i386/cpu.h     |  53 ++++++++++++++
 target/i386/kvm.c     |  73 +++++++++++++++++++
 target/i386/machine.c | 161 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 341 insertions(+), 3 deletions(-)

-- 
2.17.2



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

* [Qemu-devel][PATCH v5 1/4] x86/cpu: Add CET CPUID/XSAVES flags and data structures
  2020-05-10  1:42 [Qemu-devel][PATCH v5 0/4] Enable CET support for guest Yang Weijiang
@ 2020-05-10  1:42 ` Yang Weijiang
  2020-07-15  7:10   ` Xiaoyao Li
  2020-05-10  1:42 ` [Qemu-devel][PATCH v5 2/4] x86/cpuid: Add XSAVES feature words and CET related state bits Yang Weijiang
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Yang Weijiang @ 2020-05-10  1:42 UTC (permalink / raw)
  To: qemu-devel, pbonzini; +Cc: Yang Weijiang

CET feature SHSTK and IBT are enumerated via CPUID(EAX=0x7,0):ECX[bit 7]
and EDX[bit 20] respectively. Two CET bits (bit 11 and 12) are defined in
MSR_IA32_XSS to support XSAVES/XRSTORS. CPUID(EAX=0xd, 1):ECX[bit 11] and
ECX[bit 12] correspond to CET states in user and supervisor mode respectively.

Signed-off-by: Zhang Yi <yi.z.zhang@linux.intel.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 target/i386/cpu.h | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index e818fc712a..ed03cd1760 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -489,6 +489,9 @@ typedef enum X86Seg {
 #define XSTATE_ZMM_Hi256_BIT            6
 #define XSTATE_Hi16_ZMM_BIT             7
 #define XSTATE_PKRU_BIT                 9
+#define XSTATE_RESERVED_BIT             10
+#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)
@@ -499,6 +502,19 @@ 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_RESERVED_MASK            (1ULL << XSTATE_RESERVED_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_USER_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_KERNEL_MASK    (XSTATE_CET_U_MASK)
 
 /* CPUID feature words */
 typedef enum FeatureWord {
@@ -536,6 +552,8 @@ typedef enum FeatureWord {
     FEAT_VMX_EPT_VPID_CAPS,
     FEAT_VMX_BASIC,
     FEAT_VMX_VMFUNC,
+    FEAT_XSAVES_LO,     /* CPUID[EAX=0xd,ECX=1].ECX */
+    FEAT_XSAVES_HI,     /* CPUID[EAX=0xd,ECX=1].EDX */
     FEATURE_WORDS,
 } FeatureWord;
 
@@ -743,6 +761,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 */
@@ -770,6 +790,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_7_0_EDX_AVX512_4VNNIW     (1U << 2)
 /* AVX512 Multiply Accumulation Single Precision */
 #define CPUID_7_0_EDX_AVX512_4FMAPS     (1U << 3)
+/* 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 */
@@ -1260,6 +1282,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.17.2



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

* [Qemu-devel][PATCH v5 2/4] x86/cpuid: Add XSAVES feature words and CET related state bits
  2020-05-10  1:42 [Qemu-devel][PATCH v5 0/4] Enable CET support for guest Yang Weijiang
  2020-05-10  1:42 ` [Qemu-devel][PATCH v5 1/4] x86/cpu: Add CET CPUID/XSAVES flags and data structures Yang Weijiang
@ 2020-05-10  1:42 ` Yang Weijiang
  2020-07-15  7:22   ` Xiaoyao Li
  2020-05-10  1:42 ` [Qemu-devel][PATCH v5 3/4] x86/cpuid: Add support for XSAVES dependent feature enumeration Yang Weijiang
  2020-05-10  1:42 ` [Qemu-devel][PATCH v5 4/4] x86/cpu: Add user space access interface for CET MSRs Yang Weijiang
  3 siblings, 1 reply; 7+ messages in thread
From: Yang Weijiang @ 2020-05-10  1:42 UTC (permalink / raw)
  To: qemu-devel, pbonzini; +Cc: Yang Weijiang

CET SHSTK/IBT MSRs can be saved/restored with XSAVES/XRSTORS, but
currently the related feature words are not supported, so add the
new entries. XSAVES/RSTORS always use compacted storage format, which
means the supervisor states' offsets are always 0, ignore them while
calculating stardard format storage size.

Signed-off-by: Zhang Yi <yi.z.zhang@linux.intel.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 target/i386/cpu.c | 38 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 36 insertions(+), 2 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 90ffc5f3b1..3174e05482 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -965,7 +965,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,
@@ -988,7 +988,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
             NULL, NULL, "md-clear", NULL,
             NULL, NULL, NULL, NULL,
             NULL, NULL, NULL /* pconfig */, NULL,
-            NULL, NULL, NULL, NULL,
+            "ibt", NULL, NULL, NULL,
             NULL, NULL, "spec-ctrl", "stibp",
             NULL, "arch-capabilities", "core-capability", "ssbd",
         },
@@ -1069,6 +1069,26 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
         },
         .tcg_features = TCG_XSAVE_FEATURES,
     },
+    /* Below are xsaves feature words */
+    [FEAT_XSAVES_LO] = {
+        .type = CPUID_FEATURE_WORD,
+        .cpuid = {
+            .eax = 0xD,
+            .needs_ecx = true,
+            .ecx = 1,
+            .reg = R_ECX,
+        },
+        .migratable_flags = XSTATE_CET_U_MASK,
+    },
+    [FEAT_XSAVES_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 = {
@@ -1455,6 +1475,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 /*supervisor mode component, offset = 0 */,
+            .size = sizeof(XSavesCETU) },
+    [XSTATE_CET_S_BIT] = {
+            .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_CET_SHSTK,
+            .offset = 0 /*supervisor mode component, offset = 0 */,
+            .size = sizeof(XSavesCETS) },
 };
 
 static uint32_t xsave_area_size(uint64_t mask)
@@ -1465,6 +1493,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);
         }
     }
@@ -6008,6 +6039,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;
         }
-- 
2.17.2



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

* [Qemu-devel][PATCH v5 3/4] x86/cpuid: Add support for XSAVES dependent feature enumeration
  2020-05-10  1:42 [Qemu-devel][PATCH v5 0/4] Enable CET support for guest Yang Weijiang
  2020-05-10  1:42 ` [Qemu-devel][PATCH v5 1/4] x86/cpu: Add CET CPUID/XSAVES flags and data structures Yang Weijiang
  2020-05-10  1:42 ` [Qemu-devel][PATCH v5 2/4] x86/cpuid: Add XSAVES feature words and CET related state bits Yang Weijiang
@ 2020-05-10  1:42 ` Yang Weijiang
  2020-05-10  1:42 ` [Qemu-devel][PATCH v5 4/4] x86/cpu: Add user space access interface for CET MSRs Yang Weijiang
  3 siblings, 0 replies; 7+ messages in thread
From: Yang Weijiang @ 2020-05-10  1:42 UTC (permalink / raw)
  To: qemu-devel, pbonzini; +Cc: Yang Weijiang

Currently XSAVES dependent features are not supported in CPUID enumeration,
update CPUID(0xD,n>=1) to enable it.

CET XSAVES related enumeration includes:
CPUID(0xD,1):ECX[bit 11]: user mode CET state, controls bit 11 in XSS.
CPUID(0xD,1):ECX[bit 12]: supervisor mode CET state, controls bit 12 in XSS.
CPUID(0xD,11): user mode CET state sub-leaf, reports the state size.
CPUID(0xD,12): supervisor mode CE state sub-leaf, reports the state size.

Signed-off-by: Zhang Yi <yi.z.zhang@linux.intel.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 target/i386/cpu.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 3174e05482..881c84a3b3 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1513,6 +1513,12 @@ static inline uint64_t x86_cpu_xsave_components(X86CPU *cpu)
            cpu->env.features[FEAT_XSAVE_COMP_LO];
 }
 
+static inline uint64_t x86_cpu_xsave_sv_components(X86CPU *cpu)
+{
+    return ((uint64_t)cpu->env.features[FEAT_XSAVES_HI]) << 32 |
+           cpu->env.features[FEAT_XSAVES_LO];
+}
+
 const char *get_register_name_32(unsigned int reg)
 {
     if (reg >= CPU_NB_REGS32) {
@@ -5722,13 +5728,22 @@ 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) {
+            /* ebx is updated in kvm.*/
             *eax = env->features[FEAT_XSAVE];
+            *ecx = env->features[FEAT_XSAVES_LO];
+            *edx = env->features[FEAT_XSAVES_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];
                 *eax = esa->size;
                 *ebx = esa->offset;
             }
+            if ((x86_cpu_xsave_sv_components(cpu) >> count) & 1) {
+                const ExtSaveArea *esa_sv = &x86_ext_save_areas[count];
+                *eax = esa_sv->size;
+                *ebx = 0;
+                *ecx = 1;
+            }
         }
         break;
     }
@@ -6280,8 +6295,10 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu)
         }
     }
 
-    env->features[FEAT_XSAVE_COMP_LO] = mask;
+    env->features[FEAT_XSAVE_COMP_LO] = mask & CPUID_XSTATE_USER_MASK;
     env->features[FEAT_XSAVE_COMP_HI] = mask >> 32;
+    env->features[FEAT_XSAVES_LO] = mask & CPUID_XSTATE_KERNEL_MASK;
+    env->features[FEAT_XSAVES_HI] = mask >> 32;
 }
 
 /***** Steps involved on loading and filtering CPUID data
-- 
2.17.2



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

* [Qemu-devel][PATCH v5 4/4] x86/cpu: Add user space access interface for CET MSRs
  2020-05-10  1:42 [Qemu-devel][PATCH v5 0/4] Enable CET support for guest Yang Weijiang
                   ` (2 preceding siblings ...)
  2020-05-10  1:42 ` [Qemu-devel][PATCH v5 3/4] x86/cpuid: Add support for XSAVES dependent feature enumeration Yang Weijiang
@ 2020-05-10  1:42 ` Yang Weijiang
  3 siblings, 0 replies; 7+ messages in thread
From: Yang Weijiang @ 2020-05-10  1:42 UTC (permalink / raw)
  To: qemu-devel, pbonzini; +Cc: Yang Weijiang

Added interface for CET MSR_IA32_{U,S}_CET, MSR_IA32_PL{0,1,2,3}_SSP,
MSR_IA32_INTR_SSP_TBL and MSR_KVM_GUEST_SSP save/restore. Check if
corresponding CET features are available before access the MSRs.

Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
---
 target/i386/cpu.h     |  18 +++++
 target/i386/kvm.c     |  73 +++++++++++++++++++
 target/i386/machine.c | 161 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 252 insertions(+)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index ed03cd1760..51577a04ca 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -480,6 +480,15 @@ typedef enum X86Seg {
 #define MSR_IA32_VMX_TRUE_ENTRY_CTLS     0x00000490
 #define MSR_IA32_VMX_VMFUNC             0x00000491
 
+#define MSR_IA32_U_CET                  0x6a0
+#define MSR_IA32_S_CET                  0x6a2
+#define MSR_IA32_PL0_SSP                0x6a4
+#define MSR_IA32_PL1_SSP                0x6a5
+#define MSR_IA32_PL2_SSP                0x6a6
+#define MSR_IA32_PL3_SSP                0x6a7
+#define MSR_IA32_SSP_TBL                0x6a8
+#define MSR_KVM_GUEST_SSP               0x4b564d06
+
 #define XSTATE_FP_BIT                   0
 #define XSTATE_SSE_BIT                  1
 #define XSTATE_YMM_BIT                  2
@@ -1567,6 +1576,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 4901c6dd74..0735981558 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -2979,6 +2979,31 @@ 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_XSAVES_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_XSAVES_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);
+        }
+
+        if (env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_CET_IBT) {
+            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_XSAVES_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);
 }
 
@@ -3295,6 +3320,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_XSAVES_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_XSAVES_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);
+        }
+
+        if (env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_CET_IBT) {
+            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_XSAVES_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;
@@ -3578,6 +3627,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;
         }
     }
 
diff --git a/target/i386/machine.c b/target/i386/machine.c
index 0c96531a56..3e1d8b6eb9 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -962,6 +962,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)
 {
@@ -1447,6 +1600,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.17.2



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

* Re: [Qemu-devel][PATCH v5 1/4] x86/cpu: Add CET CPUID/XSAVES flags and data structures
  2020-05-10  1:42 ` [Qemu-devel][PATCH v5 1/4] x86/cpu: Add CET CPUID/XSAVES flags and data structures Yang Weijiang
@ 2020-07-15  7:10   ` Xiaoyao Li
  0 siblings, 0 replies; 7+ messages in thread
From: Xiaoyao Li @ 2020-07-15  7:10 UTC (permalink / raw)
  To: Yang Weijiang, qemu-devel, pbonzini

On 5/10/2020 9:42 AM, Yang Weijiang wrote:
> CET feature SHSTK and IBT are enumerated via CPUID(EAX=0x7,0):ECX[bit 7]
> and EDX[bit 20] respectively. Two CET bits (bit 11 and 12) are defined in
> MSR_IA32_XSS to support XSAVES/XRSTORS. CPUID(EAX=0xd, 1):ECX[bit 11] and
> ECX[bit 12] correspond to CET states in user and supervisor mode respectively.
> 
> Signed-off-by: Zhang Yi <yi.z.zhang@linux.intel.com>
> Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
> ---
>   target/i386/cpu.h | 35 +++++++++++++++++++++++++++++++++++
>   1 file changed, 35 insertions(+)
> 
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index e818fc712a..ed03cd1760 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -489,6 +489,9 @@ typedef enum X86Seg {
>   #define XSTATE_ZMM_Hi256_BIT            6
>   #define XSTATE_Hi16_ZMM_BIT             7
>   #define XSTATE_PKRU_BIT                 9
> +#define XSTATE_RESERVED_BIT             10

I think this is unnecessary. bit 8 and so many other undefined bits are 
reserved too.

> +#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)
> @@ -499,6 +502,19 @@ 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_RESERVED_MASK            (1ULL << XSTATE_RESERVED_BIT)

Ditto.

> +#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_USER_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_KERNEL_MASK    (XSTATE_CET_U_MASK)

How about we name it XSTATE_XCR0_MASK and XSTATE_XSS_MASK.

They are not CPUID feature bit, at least the CPUID_ prefix needs to be 
removed.

>   
>   /* CPUID feature words */
>   typedef enum FeatureWord {
> @@ -536,6 +552,8 @@ typedef enum FeatureWord {
>       FEAT_VMX_EPT_VPID_CAPS,
>       FEAT_VMX_BASIC,
>       FEAT_VMX_VMFUNC,
> +    FEAT_XSAVES_LO,     /* CPUID[EAX=0xd,ECX=1].ECX */
> +    FEAT_XSAVES_HI,     /* CPUID[EAX=0xd,ECX=1].EDX */

I don't think *XSAVES* is a good name, because XSAVES and manipulate the 
features masked by XCR0 | MSR_IA32_XSS. But this CPUID leaf only 
enumerated XSTATE features for XSS.

How about name it FEAT_XSS_LO/HI? or FEAT_XSAVES_XSS_HO/HI

>       FEATURE_WORDS,
>   } FeatureWord;
>   
> @@ -743,6 +761,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 */
> @@ -770,6 +790,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
>   #define CPUID_7_0_EDX_AVX512_4VNNIW     (1U << 2)
>   /* AVX512 Multiply Accumulation Single Precision */
>   #define CPUID_7_0_EDX_AVX512_4FMAPS     (1U << 3)
> +/* 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 */
> @@ -1260,6 +1282,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;
> 



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

* Re: [Qemu-devel][PATCH v5 2/4] x86/cpuid: Add XSAVES feature words and CET related state bits
  2020-05-10  1:42 ` [Qemu-devel][PATCH v5 2/4] x86/cpuid: Add XSAVES feature words and CET related state bits Yang Weijiang
@ 2020-07-15  7:22   ` Xiaoyao Li
  0 siblings, 0 replies; 7+ messages in thread
From: Xiaoyao Li @ 2020-07-15  7:22 UTC (permalink / raw)
  To: Yang Weijiang, qemu-devel, pbonzini

On 5/10/2020 9:42 AM, Yang Weijiang wrote:
> CET SHSTK/IBT MSRs can be saved/restored with XSAVES/XRSTORS, but
> currently the related feature words are not supported, so add the
> new entries. XSAVES/RSTORS always use compacted storage format, which
> means the supervisor states' offsets are always 0, ignore them while
> calculating stardard format storage size.
> 
> Signed-off-by: Zhang Yi <yi.z.zhang@linux.intel.com>
> Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
> ---
>   target/i386/cpu.c | 38 ++++++++++++++++++++++++++++++++++++--
>   1 file changed, 36 insertions(+), 2 deletions(-)
> 
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 90ffc5f3b1..3174e05482 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -965,7 +965,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,
> @@ -988,7 +988,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
>               NULL, NULL, "md-clear", NULL,
>               NULL, NULL, NULL, NULL,
>               NULL, NULL, NULL /* pconfig */, NULL,
> -            NULL, NULL, NULL, NULL,
> +            "ibt", NULL, NULL, NULL,
>               NULL, NULL, "spec-ctrl", "stibp",
>               NULL, "arch-capabilities", "core-capability", "ssbd",
>           },
> @@ -1069,6 +1069,26 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
>           },
>           .tcg_features = TCG_XSAVE_FEATURES,
>       },
> +    /* Below are xsaves feature words */
> +    [FEAT_XSAVES_LO] = {
> +        .type = CPUID_FEATURE_WORD,
> +        .cpuid = {
> +            .eax = 0xD,
> +            .needs_ecx = true,
> +            .ecx = 1,
> +            .reg = R_ECX,
> +        },
> +        .migratable_flags = XSTATE_CET_U_MASK,

why exclude XSTATE_CET_S_MASK? Is any reason why it not migratable?

> +    },
> +    [FEAT_XSAVES_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 = {
> @@ -1455,6 +1475,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 /*supervisor mode component, offset = 0 */,
> +            .size = sizeof(XSavesCETU) },
> +    [XSTATE_CET_S_BIT] = {
> +            .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_CET_SHSTK,
> +            .offset = 0 /*supervisor mode component, offset = 0 */,
> +            .size = sizeof(XSavesCETS) },
>   };
>   
>   static uint32_t xsave_area_size(uint64_t mask)
> @@ -1465,6 +1493,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);
>           }
>       }
> @@ -6008,6 +6039,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;
>           }
> 



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

end of thread, other threads:[~2020-07-15  7:52 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-10  1:42 [Qemu-devel][PATCH v5 0/4] Enable CET support for guest Yang Weijiang
2020-05-10  1:42 ` [Qemu-devel][PATCH v5 1/4] x86/cpu: Add CET CPUID/XSAVES flags and data structures Yang Weijiang
2020-07-15  7:10   ` Xiaoyao Li
2020-05-10  1:42 ` [Qemu-devel][PATCH v5 2/4] x86/cpuid: Add XSAVES feature words and CET related state bits Yang Weijiang
2020-07-15  7:22   ` Xiaoyao Li
2020-05-10  1:42 ` [Qemu-devel][PATCH v5 3/4] x86/cpuid: Add support for XSAVES dependent feature enumeration Yang Weijiang
2020-05-10  1:42 ` [Qemu-devel][PATCH v5 4/4] x86/cpu: Add user space access interface for CET MSRs 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.