Re: [PATCH 2/2] i386/cpu: Mask with XCR0/XSS mask for FEAT_XSAVE_XCR0_HI and FEAT_XSAVE_XSS_HI leafs

2024-01-16 Thread Yang, Weijiang

On 1/15/2024 5:13 PM, Li, Xiaoyao wrote:

The value of FEAT_XSAVE_XCR0_HI leaf and FEAT_XSAVE_XSS_HI leaf also
need to be masked by XCR0 and XSS mask respectively, to make it
logically correct.

Fixes: 301e90675c3f ("target/i386: Enable support for XSAVES based features")
Signed-off-by: Xiaoyao Li 
---
  target/i386/cpu.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index b445e2957c4f..a5c08944a483 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -6946,9 +6946,9 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu)
  }
  
  env->features[FEAT_XSAVE_XCR0_LO] = mask & CPUID_XSTATE_XCR0_MASK;

-env->features[FEAT_XSAVE_XCR0_HI] = mask >> 32;
+env->features[FEAT_XSAVE_XCR0_HI] = (mask & CPUID_XSTATE_XCR0_MASK) >> 32;
  env->features[FEAT_XSAVE_XSS_LO] = mask & CPUID_XSTATE_XSS_MASK;
-env->features[FEAT_XSAVE_XSS_HI] = mask >> 32;
+env->features[FEAT_XSAVE_XSS_HI] = (mask & CPUID_XSTATE_XSS_MASK) >> 32;
  }


Thanks for fixing this!
Reviewed-by: Yang Weijiang 

  
  /* Steps involved on loading and filtering CPUID data





Re: [PATCH 1/2] i386/cpu: Clear FEAT_XSAVE_XSS_LO/HI leafs when CPUID_EXT_XSAVE is not available

2024-01-16 Thread Yang, Weijiang

On 1/15/2024 5:13 PM, Li, Xiaoyao wrote:

Leaf FEAT_XSAVE_XSS_LO and FEAT_XSAVE_XSS_HI also need to be cleared
when CPUID_EXT_XSAVE is not set.

Fixes: 301e90675c3f ("target/i386: Enable support for XSAVES based features")
Signed-off-by: Xiaoyao Li 
---
  target/i386/cpu.c | 2 ++
  1 file changed, 2 insertions(+)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 2524881ce245..b445e2957c4f 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -6926,6 +6926,8 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu)
  if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) {
  env->features[FEAT_XSAVE_XCR0_LO] = 0;
  env->features[FEAT_XSAVE_XCR0_HI] = 0;
+env->features[FEAT_XSAVE_XSS_LO] = 0;
+env->features[FEAT_XSAVE_XSS_HI] = 0;
  return;
  }


Thanks for fixing this!
Reviewed-by: Yang Weijiang 

  





Re: [PATCH 4/4] target/i386: add live migration support for FRED

2023-09-21 Thread Yang, Weijiang

On 9/1/2023 1:30 PM, Li, Xin3 wrote:

FRED CPU states are managed in 10 FRED MSRs, in addtion to a few existing
CPU registers and MSRs, e.g., the CR4.FRED bit.

Add the 10 new FRED MSRs to x86 CPUArchState for live migration support.

Tested-by: Shan Kang 
Signed-off-by: Xin Li 
---
  target/i386/cpu.h | 24 +++
  target/i386/kvm/kvm.c | 54 +++
  target/i386/machine.c | 10 
  3 files changed, 88 insertions(+)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 924819a64c..a36a1a58c4 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -529,6 +529,20 @@ typedef enum X86Seg {
  #define MSR_IA32_XFD0x01c4
  #define MSR_IA32_XFD_ERR0x01c5
  
+#define MSR_IA32_PL0_SSP0x06a4   /* Stack level 0 shadow stack pointer in ring 0 */

+
+/* FRED MSRs */
+#define MSR_IA32_FRED_RSP0  0x01cc   /* Stack level 0 
regular stack pointer */
+#define MSR_IA32_FRED_RSP1  0x01cd   /* Stack level 1 
regular stack pointer */
+#define MSR_IA32_FRED_RSP2  0x01ce   /* Stack level 2 
regular stack pointer */
+#define MSR_IA32_FRED_RSP3  0x01cf   /* Stack level 3 
regular stack pointer */
+#define MSR_IA32_FRED_STKLVLS   0x01d0   /* FRED exception 
stack levels */
+#define MSR_IA32_FRED_SSP0  MSR_IA32_PL0_SSP /* Stack level 0 
shadow stack pointer in ring 0 */
+#define MSR_IA32_FRED_SSP1  0x01d1   /* Stack level 1 
shadow stack pointer in ring 0 */
+#define MSR_IA32_FRED_SSP2  0x01d2   /* Stack level 2 
shadow stack pointer in ring 0 */
+#define MSR_IA32_FRED_SSP3  0x01d3   /* Stack level 3 
shadow stack pointer in ring 0 */
+#define MSR_IA32_FRED_CONFIG0x01d4   /* FRED Entrypoint 
and interrupt stack level */
+
  #define MSR_IA32_BNDCFGS0x0d90
  #define MSR_IA32_XSS0x0da0
  #define MSR_IA32_UMWAIT_CONTROL 0xe1
@@ -1680,6 +1694,16 @@ typedef struct CPUArchState {
  target_ulong cstar;
  target_ulong fmask;
  target_ulong kernelgsbase;
+target_ulong fred_rsp0;
+target_ulong fred_rsp1;
+target_ulong fred_rsp2;
+target_ulong fred_rsp3;
+target_ulong fred_stklvls;
+target_ulong fred_ssp0;
+target_ulong fred_ssp1;
+target_ulong fred_ssp2;
+target_ulong fred_ssp3;
+target_ulong fred_config;
  #endif
  
  uint64_t tsc_adjust;

diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 639a242ad8..4b241c82d8 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -3401,6 +3401,18 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
  kvm_msr_entry_add(cpu, MSR_KERNELGSBASE, env->kernelgsbase);
  kvm_msr_entry_add(cpu, MSR_FMASK, env->fmask);
  kvm_msr_entry_add(cpu, MSR_LSTAR, env->lstar);
+if (env->features[FEAT_7_1_EAX] & CPUID_7_1_EAX_FRED) {
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP0, env->fred_rsp0);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP1, env->fred_rsp1);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP2, env->fred_rsp2);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP3, env->fred_rsp3);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_STKLVLS, env->fred_stklvls);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP0, env->fred_ssp0);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP1, env->fred_ssp1);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP2, env->fred_ssp2);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP3, env->fred_ssp3);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_CONFIG, env->fred_config);
+}
  }
  #endif
  
@@ -3901,6 +3913,18 @@ static int kvm_get_msrs(X86CPU *cpu)

  kvm_msr_entry_add(cpu, MSR_KERNELGSBASE, 0);
  kvm_msr_entry_add(cpu, MSR_FMASK, 0);
  kvm_msr_entry_add(cpu, MSR_LSTAR, 0);
+if (env->features[FEAT_7_1_EAX] & CPUID_7_1_EAX_FRED) {
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP0, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP1, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP2, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_RSP3, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_STKLVLS, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP0, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP1, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP2, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_SSP3, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_FRED_CONFIG, 0);
+}
  }
  #endif
  kvm_msr_entry_add(cpu, MSR_KVM_SYSTEM_TIME, 0);
@@ -4123,6 +4147,36 @@ static int kvm_get_msrs(X86CPU *cpu)
  case MSR_LSTAR:
  env->lstar = msrs[i].data;
  break;
+case MSR_IA32_FRED_RSP0:
+env->fred_rsp0 = 

Re: [PATCH] target/i386: enumerate bit 56 of MSR_IA32_VMX_BASIC

2023-09-21 Thread Yang, Weijiang

On 9/20/2023 11:41 PM, Paolo Bonzini wrote:

On parts that enumerate IA32_VMX_BASIC MSR bit as 1, any exception vector
can be delivered with or without an error code if the other consistency
checks are satisfied.

Signed-off-by: Paolo Bonzini 
---
  target/i386/cpu.c | 1 +
  target/i386/cpu.h | 1 +
  2 files changed, 2 insertions(+)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 6e52c7be1e1..8f334dbbcc2 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1347,6 +1347,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
  .feat_names = {
  [54] = "vmx-ins-outs",
  [55] = "vmx-true-ctls",
+[56] = "vmx-any-errcode",
  },
  .msr = {
  .index = MSR_IA32_VMX_BASIC,
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index eab610e5cd5..2e09c588f0b 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1039,6 +1039,7 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
  #define MSR_VMX_BASIC_DUAL_MONITOR   (1ULL << 49)
  #define MSR_VMX_BASIC_INS_OUTS   (1ULL << 54)
  #define MSR_VMX_BASIC_TRUE_CTLS  (1ULL << 55)
+#define MSR_VMX_BASIC_ANY_ERRCODE(1ULL << 56)
  
  #define MSR_VMX_MISC_PREEMPTION_TIMER_SHIFT_MASK 0x1Full

  #define MSR_VMX_MISC_STORE_LMA   (1ULL << 5)


Thanks Paolo!
I forgot to post refreshed CET QEMU series which includes this bit enabling.

Reviewed-by:  Yang Weijiang 



[PATCH v2 0/4] Enable CET userspace support

2023-07-20 Thread Yang Weijiang
CET virtualization requires VMM userspace setup for CET feature
bits enumeration, this series enables all related settings.

Guest CET user and kernel mode SHSTK/IBT are both supported.

Changes in v2:
1. Added supervisor CET states support.
2. Consolidated all CET states in a struct of vmstate.

v1 link:
https://lore.kernel.org/all/20230421041227.90915-1-weijiang.y...@intel.com/


Yang Weijiang (4):
  target/i386: Enable XSAVES support for CET states
  target/i386: Add CET MSRs access interface
  target/i386: Add CET states to vmstate
  target/i386: Advertise CET related flags in feature words

 target/i386/cpu.c | 54 +--
 target/i386/cpu.h | 41 ++
 target/i386/kvm/kvm.c | 59 +++
 target/i386/machine.c | 28 
 4 files changed, 169 insertions(+), 13 deletions(-)


base-commit: a342ce9dfeed8088c426e5d51d4a7e47f3764b84
-- 
2.27.0




[PATCH v2 4/4] target/i386: Advertise CET related flags in feature words

2023-07-20 Thread Yang Weijiang
Add SHSTK and IBT flags in feature words with entry/exit
control flags.

CET SHSTK and IBT feature are enumerated via CPUID(EAX=7,ECX=0)
ECX[bit 7] and EDX[bit 20]. CET states load/restore at vmentry/
vmexit are controlled by VMX_ENTRY_CTLS[bit 20] and VMX_EXIT_CTLS[bit 28].
Enable these flags so that KVM can enumerate the features properly.

CET feature is only available on platforms with IA32_VMX_BASIC[bit 56]
set, otherwise, CET features are disabled in KVM.

Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index ea11b589e3..79a90e35bf 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -835,7 +835,7 @@ 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,
@@ -858,7 +858,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
 "avx512-vp2intersect", NULL, "md-clear", NULL,
 NULL, NULL, "serialize", NULL,
 "tsx-ldtrk", NULL, NULL /* pconfig */, "arch-lbr",
-NULL, NULL, "amx-bf16", "avx512-fp16",
+"ibt", NULL, "amx-bf16", "avx512-fp16",
 "amx-tile", "amx-int8", "spec-ctrl", "stibp",
 NULL, "arch-capabilities", "core-capability", "ssbd",
 },
@@ -1120,7 +1120,7 @@ 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, "vmx-exit-load-pkrs", NULL, NULL,
+"vmx-exit-save-cet-ctl", "vmx-exit-load-pkrs", NULL, NULL,
 },
 .msr = {
 .index = MSR_IA32_VMX_TRUE_EXIT_CTLS,
@@ -1135,7 +1135,7 @@ 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, "vmx-entry-load-pkrs", NULL,
+"vmx-entry-load-cet-ctl", NULL, "vmx-entry-load-pkrs", NULL,
 NULL, NULL, NULL, NULL,
 NULL, NULL, NULL, NULL,
 },
@@ -1192,6 +1192,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
 .feat_names = {
 [54] = "vmx-ins-outs",
 [55] = "vmx-true-ctls",
+[56] = "vmx-hw-no-errcode",
 },
 .msr = {
 .index = MSR_IA32_VMX_BASIC,
-- 
2.27.0




[PATCH v2 1/4] target/i386: Enable XSAVES support for CET states

2023-07-20 Thread Yang Weijiang
Add CET_U/S bits in xstate area and report support in xstate
feature mask.
MSR_XSS[bit 11] corresponds to CET user mode states.
MSR_XSS[bit 12] corresponds to CET supervisor mode states.

CET Shadow Stack(SHSTK) and Indirect Branch Tracking(IBT) features
are enumerated via CPUID.(EAX=07H,ECX=0H):ECX[7] and EDX[20]
respectively, two featues share the same state bits in XSS,so
if either of the features is enabled, set CET_U and CET_S bits
together.

Opportunistically fix the array format issue.

Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 45 -
 target/i386/cpu.h | 23 +++
 2 files changed, 59 insertions(+), 9 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index f083ff4335..ea11b589e3 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -944,8 +944,8 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
 .feat_names = {
 NULL, NULL, NULL, NULL,
 NULL, NULL, NULL, NULL,
-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,
@@ -1421,7 +1421,8 @@ static const X86RegisterInfo32 
x86_reg_info_32[CPU_NB_REGS32] = {
 #undef REGISTER
 
 /* CPUID feature bits available in XSS */
-#define CPUID_XSTATE_XSS_MASK(XSTATE_ARCH_LBR_MASK)
+#define CPUID_XSTATE_XSS_MASK(XSTATE_ARCH_LBR_MASK | XSTATE_CET_U_MASK | \
+  XSTATE_CET_S_MASK)
 
 ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = {
 [XSTATE_FP_BIT] = {
@@ -1439,7 +1440,7 @@ ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = {
 .size = sizeof(XSaveAVX) },
 [XSTATE_BNDREGS_BIT] =
   { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX,
-.size = sizeof(XSaveBNDREG)  },
+.size = sizeof(XSaveBNDREG) },
 [XSTATE_BNDCSR_BIT] =
   { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX,
 .size = sizeof(XSaveBNDCSR)  },
@@ -1459,14 +1460,24 @@ ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] 
= {
 .feature = FEAT_7_0_EDX, .bits = CPUID_7_0_EDX_ARCH_LBR,
 .offset = 0 /*supervisor mode component, offset = 0 */,
 .size = sizeof(XSavesArchLBR) },
+[XSTATE_CET_U_BIT] = {
+.feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_CET_SHSTK,
+/*
+ * The features enabled in XSS MSR always use compacted format
+ * to store the data, in this case .offset == 0.
+ */
+.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) },
 [XSTATE_XTILE_CFG_BIT] = {
 .feature = FEAT_7_0_EDX, .bits = CPUID_7_0_EDX_AMX_TILE,
-.size = sizeof(XSaveXTILECFG),
-},
+.size = sizeof(XSaveXTILECFG) },
 [XSTATE_XTILE_DATA_BIT] = {
 .feature = FEAT_7_0_EDX, .bits = CPUID_7_0_EDX_AMX_TILE,
-.size = sizeof(XSaveXTILEDATA)
-},
+.size = sizeof(XSaveXTILEDATA) }
 };
 
 uint32_t xsave_area_size(uint64_t mask, bool compacted)
@@ -6259,9 +6270,25 @@ 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 depend on XSAVES support, and two
+ * features can be enabled independently, so if either of the two
+ * features is enabled, we set the XSAVES support bits to make the
+ * enabled feature(s) 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);
+}
+}
 }
 
-/* Only request permission for first vcpu */
+/* Only request permission from fisrt vcpu. */
 if (kvm_enabled() && !request_perm) {
 kvm_request_xsave_components(cpu, mask);
 request_perm = true;
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index d243e290d3..06855e0926 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -554,6 +554,8 @@ typedef enum X86Seg {
 #define XSTATE_ZMM_Hi256_BIT6
 #define XSTATE_Hi16_ZMM_BIT 7
 #define XSTATE_PKRU_BIT 9
+#define XSTATE_CET_U_BIT11
+#define XSTATE_CET_S_BIT12
 #define XSTATE_ARCH_LBR_BIT 15
 #define XSTATE_XTILE_CFG_BIT17
 #define XSTATE_XTILE_DATA_BIT   18
@@ -567,6 +569,8 @@ t

[PATCH v2 2/4] target/i386: Add CET MSRs access interface

2023-07-20 Thread Yang Weijiang
CET MSRs include:
MSR_IA32_U_CET - user mode CET control bits.
MSR_IA32_S_CET - supervisor mode CET control bits.
MSR_IA32_PL{0,1,2,3}_SSP - linear addresses of SSPs for user/kernel modes.
MSR_IA32_SSP_TBL_ADDR - linear address of interrupt SSP table
MSR_KVM_GUEST_SSP - current shadow stack pointer

Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.h | 18 +
 target/i386/kvm/kvm.c | 59 +++
 2 files changed, 77 insertions(+)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 06855e0926..ef1f3d6138 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -545,6 +545,15 @@ typedef enum X86Seg {
 #define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x0490
 #define MSR_IA32_VMX_VMFUNC 0x0491
 
+#define MSR_IA32_U_CET  0x06a0
+#define MSR_IA32_S_CET  0x06a2
+#define MSR_IA32_PL0_SSP0x06a4
+#define MSR_IA32_PL1_SSP0x06a5
+#define MSR_IA32_PL2_SSP0x06a6
+#define MSR_IA32_PL3_SSP0x06a7
+#define MSR_IA32_SSP_TBL_ADDR   0x06a8
+#define MSR_KVM_GUEST_SSP   0x4b564d09
+
 #define XSTATE_FP_BIT   0
 #define XSTATE_SSE_BIT  1
 #define XSTATE_YMM_BIT  2
@@ -1766,6 +1775,15 @@ typedef struct CPUArchState {
 
 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_table_addr;
+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/kvm.c b/target/i386/kvm/kvm.c
index de531842f6..ab3a755b97 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -3591,6 +3591,24 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
   env->msr_ia32_sgxlepubkeyhash[3]);
 }
 
+if ((env->features[FEAT_XSAVE_XSS_LO] & XSTATE_CET_U_MASK) &&
+(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_U_CET, env->u_cet);
+kvm_msr_entry_add(cpu, MSR_IA32_S_CET, env->s_cet);
+kvm_msr_entry_add(cpu, MSR_KVM_GUEST_SSP, env->guest_ssp);
+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_PL3_SSP, env->pl3_ssp);
+kvm_msr_entry_add(cpu, MSR_IA32_SSP_TBL_ADDR,
+  env->ssp_table_addr);
+} else if (env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_CET_IBT) {
+kvm_msr_entry_add(cpu, MSR_IA32_U_CET, env->u_cet);
+kvm_msr_entry_add(cpu, MSR_IA32_S_CET, env->s_cet);
+}
+}
+
 if (env->features[FEAT_XSAVE] & CPUID_D_1_EAX_XFD) {
 kvm_msr_entry_add(cpu, MSR_IA32_XFD,
   env->msr_xfd);
@@ -4024,6 +4042,23 @@ static int kvm_get_msrs(X86CPU *cpu)
 kvm_msr_entry_add(cpu, MSR_IA32_SGXLEPUBKEYHASH3, 0);
 }
 
+if ((env->features[FEAT_XSAVE_XSS_LO] & XSTATE_CET_U_MASK) &&
+(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_U_CET, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_S_CET, 0);
+kvm_msr_entry_add(cpu, MSR_KVM_GUEST_SSP, 0);
+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_PL3_SSP, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_SSP_TBL_ADDR, 0);
+ } else if (env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_CET_IBT) {
+kvm_msr_entry_add(cpu, MSR_IA32_U_CET, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_S_CET, 0);
+}
+}
+
 if (env->features[FEAT_XSAVE] & CPUID_D_1_EAX_XFD) {
 kvm_msr_entry_add(cpu, MSR_IA32_XFD, 0);
 kvm_msr_entry_add(cpu, MSR_IA32_XFD_ERR, 0);
@@ -4346,6 +4381,30 @@ static int kvm_get_msrs(X86CPU *cpu)
 env->msr_ia32_sgxlepubkeyhash[index - MSR_IA32_SGXLEPUBKEYHASH0] =
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_KVM_G

[PATCH v2 3/4] target/i386: Add CET states to vmstate

2023-07-20 Thread Yang Weijiang
Add CET states in vmstate if the feature is enabled.

Signed-off-by: Yang Weijiang 
---
 target/i386/machine.c | 28 
 1 file changed, 28 insertions(+)

diff --git a/target/i386/machine.c b/target/i386/machine.c
index c7ac8084b2..6d42f6dc7e 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -1586,6 +1586,33 @@ static const VMStateDescription vmstate_arch_lbr = {
 }
 };
 
+static bool cet_needed(void *opaque)
+{
+X86CPU *cpu = opaque;
+CPUX86State *env = >env;
+
+return !!((env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_CET_SHSTK) ||
+  (env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_CET_IBT));
+}
+
+static const VMStateDescription vmstate_cet = {
+.name = "cpu/cet",
+.version_id = 1,
+.minimum_version_id = 1,
+.needed = cet_needed,
+.fields = (VMStateField[]) {
+VMSTATE_UINT64(env.u_cet, X86CPU),
+VMSTATE_UINT64(env.s_cet, X86CPU),
+VMSTATE_UINT64(env.guest_ssp, X86CPU),
+VMSTATE_UINT64(env.pl0_ssp, X86CPU),
+VMSTATE_UINT64(env.pl1_ssp, X86CPU),
+VMSTATE_UINT64(env.pl2_ssp, X86CPU),
+VMSTATE_UINT64(env.pl3_ssp, X86CPU),
+VMSTATE_UINT64(env.ssp_table_addr, X86CPU),
+VMSTATE_END_OF_LIST()
+}
+};
+
 static bool triple_fault_needed(void *opaque)
 {
 X86CPU *cpu = opaque;
@@ -1745,6 +1772,7 @@ const VMStateDescription vmstate_x86_cpu = {
 _msr_tsx_ctrl,
 _msr_intel_sgx,
 _pdptrs,
+_cet,
 _msr_xfd,
 #ifdef TARGET_X86_64
 _amx_xtile,
-- 
2.27.0




Re: [PATCH v2 3/3] i386/cpuid: Move leaf 7 to correct group

2023-06-27 Thread Yang, Weijiang



On 6/13/2023 9:19 PM, Xiaoyao Li wrote:

CPUID leaf 7 was grouped together with SGX leaf 0x12 by commit
b9edbadefb9e ("i386: Propagate SGX CPUID sub-leafs to KVM") by mistake.

SGX leaf 0x12 has its specific logic to check if subleaf (starting from 2)
is valid or not by checking the bit 0:3 of corresponding EAX is 1 or
not.

Leaf 7 follows the logic that EAX of subleaf 0 enumerates the maximum
valid subleaf.

Fixes: b9edbadefb9e ("i386: Propagate SGX CPUID sub-leafs to KVM")
Signed-off-by: Xiaoyao Li 
---
  target/i386/kvm/kvm.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index d7e235ce35a6..86aab9ca4ba2 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -1993,7 +1993,6 @@ int kvm_arch_init_vcpu(CPUState *cs)
  c = _data.entries[cpuid_i++];
  }
  break;
-case 0x7:
  case 0x12:
  for (j = 0; ; j++) {
  c->function = i;
@@ -2013,6 +2012,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
  c = _data.entries[cpuid_i++];
  }
  break;
+case 0x7:
  case 0x14:
  case 0x1d:
  case 0x1e: {


Reviewed-by:Yang Weijiang 




Re: [PATCH v2 2/3] i386/cpuid: Remove subleaf constraint on CPUID leaf 1F

2023-06-27 Thread Yang, Weijiang

On 6/13/2023 9:19 PM, Xiaoyao Li wrote:


No such constraint that subleaf index needs to be less than 64.

Signed-off-by: Xiaoyao Li 
---
  target/i386/kvm/kvm.c | 4 
  1 file changed, 4 deletions(-)

diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index afa97799d89a..d7e235ce35a6 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -1968,10 +1968,6 @@ int kvm_arch_init_vcpu(CPUState *cs)
  break;
  }
  
-if (i == 0x1f && j == 64) {

-break;
-}
-
  c->function = i;
  c->flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
  c->index = j;

Reviewed-by:Yang Weijiang 



Re: [PATCH v2 1/3] i386/cpuid: Decrease cpuid_i when skipping CPUID leaf 1F

2023-06-27 Thread Yang, Weijiang



On 6/13/2023 9:19 PM, Xiaoyao Li wrote:

Decrease array index cpuid_i when CPUID leaf 1F is skipped, otherwise it
will get an all zero'ed CPUID entry with leaf 0 and subleaf 0. It
conflicts with correct leaf 0.


Maybe change the commit log like this:

Exiting code misses a decrement of cpuid_i when skip left 0x1F, so 
there's a blank CPUID


entry(with all fields stuffed 0s) left in the CPUID array.  Fix the 
issue to avoid the blank slot.


Reviewed-by:Yang Weijiang 



Signed-off-by: Xiaoyao Li 
---
  target/i386/kvm/kvm.c | 1 +
  1 file changed, 1 insertion(+)

diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index de531842f6b1..afa97799d89a 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -1956,6 +1956,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
  }
  case 0x1f:
  if (env->nr_dies < 2) {
+cpuid_i--;
  break;
  }
  /* fallthrough */




[PATCH 4/4] target/i386: Advertise CET flags in feature words

2023-04-21 Thread Yang Weijiang
Add SHSTK and IBT flags in feature words alone with entry/exit
control flags.

CET SHSTK and IBT feature are enumerated via CPUID(EAX=7,ECX=0)
ECX[bit 7] and EDX[bit 20]. CET states load/restore at vmentry/
vmexit are controlled by VMX_ENTRY_CTLS[bit 20] and VMX_EXIT_CTLS[bit 28].
Enable these flags so that KVM can support the features properly.

Signed-off-by: Yang Weijiang 
---
 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 be86df8c1d..f11c5ce86c 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -834,7 +834,7 @@ 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,
@@ -857,7 +857,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
 "avx512-vp2intersect", NULL, "md-clear", NULL,
 NULL, NULL, "serialize", NULL,
 "tsx-ldtrk", NULL, NULL /* pconfig */, "arch-lbr",
-NULL, NULL, "amx-bf16", "avx512-fp16",
+"ibt", NULL, "amx-bf16", "avx512-fp16",
 "amx-tile", "amx-int8", "spec-ctrl", "stibp",
 NULL, "arch-capabilities", "core-capability", "ssbd",
 },
@@ -1119,7 +1119,7 @@ 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, "vmx-exit-load-pkrs", NULL, NULL,
+"vmx-exit-save-cet-ctl", "vmx-exit-load-pkrs", NULL, NULL,
 },
 .msr = {
 .index = MSR_IA32_VMX_TRUE_EXIT_CTLS,
@@ -1134,7 +1134,7 @@ 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, "vmx-entry-load-pkrs", NULL,
+"vmx-entry-load-cet-ctl", NULL, "vmx-entry-load-pkrs", NULL,
 NULL, NULL, NULL, NULL,
 NULL, NULL, NULL, NULL,
 },
-- 
2.27.0




[PATCH 3/4] target/i386: Enable CET states migration

2023-04-21 Thread Yang Weijiang
Add supported CET states in vmstate for VM migration.

Other MSRs, i.e., MSR_IA32_PL{0,1,2}_SSP and MSR_IA32_INTR_SSP_TBL
are for non-supported supervisor mode shadow stack, are ignored now.

Signed-off-by: Yang Weijiang 
---
 target/i386/machine.c | 81 +++
 1 file changed, 81 insertions(+)

diff --git a/target/i386/machine.c b/target/i386/machine.c
index c7ac8084b2..904a7e9574 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -1018,6 +1018,83 @@ static const VMStateDescription vmstate_umwait = {
 }
 };
 
+static bool u_cet_needed(void *opaque)
+{
+X86CPU *cpu = opaque;
+CPUX86State *env = >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 = >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 pl3_ssp_needed(void *opaque)
+{
+X86CPU *cpu = opaque;
+CPUX86State *env = >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 guest_ssp_needed(void *opaque)
+{
+X86CPU *cpu = opaque;
+CPUX86State *env = >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()
+}
+};
+
 static bool pkru_needed(void *opaque)
 {
 X86CPU *cpu = opaque;
@@ -1745,6 +1822,10 @@ const VMStateDescription vmstate_x86_cpu = {
 _msr_tsx_ctrl,
 _msr_intel_sgx,
 _pdptrs,
+_u_cet,
+_s_cet,
+_pl3_ssp,
+_guest_ssp,
 _msr_xfd,
 #ifdef TARGET_X86_64
 _amx_xtile,
-- 
2.27.0




[PATCH 2/4] target/i386: Add CET MSRs access interfaces

2023-04-21 Thread Yang Weijiang
Add access interfaces for supported CET MSRs.
These CET MSRs include:
MSR_IA32_U_CET - store user mode CET control bits.
MSR_IA32_S_CET - store supervisor mode CET control bits.
MSR_IA32_PL3_SSP - strore user mode shadow stack pointer.
MSR_KVM_GUEST_SSP - store current shadow stack pointer.

Other MSRs, i.e., MSR_IA32_PL{0,1,2}_SSP and MSR_IA32_INTR_SSP_TBL
are for non-supported supervisor mode shadow stack, are ignored now.

Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.h | 10 ++
 target/i386/kvm/kvm.c | 44 +++
 2 files changed, 54 insertions(+)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 6526a03206..b78ce8e5c4 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -545,6 +545,11 @@ typedef enum X86Seg {
 #define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x0490
 #define MSR_IA32_VMX_VMFUNC 0x0491
 
+#define MSR_IA32_U_CET  0x06a0
+#define MSR_IA32_S_CET  0x06a2
+#define MSR_IA32_PL3_SSP0x06a7
+#define MSR_KVM_GUEST_SSP   0x4b564d09
+
 #define XSTATE_FP_BIT   0
 #define XSTATE_SSE_BIT  1
 #define XSTATE_YMM_BIT  2
@@ -1756,6 +1761,11 @@ typedef struct CPUArchState {
 
 uintptr_t retaddr;
 
+uint64_t u_cet;
+uint64_t s_cet;
+uint64_t pl3_ssp;
+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/kvm.c b/target/i386/kvm/kvm.c
index de531842f6..13fae898ce 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -3646,6 +3646,22 @@ 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_7_0_ECX] & CPUID_7_0_ECX_CET_SHSTK) &&
+(env->features[FEAT_XSAVE_XSS_LO] & XSTATE_CET_U_MASK)) {
+kvm_msr_entry_add(cpu, MSR_KVM_GUEST_SSP, env->guest_ssp);
+}
+
+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);
+}
+
 return kvm_buf_set_msrs(cpu);
 }
 
@@ -4024,6 +4040,22 @@ static int kvm_get_msrs(X86CPU *cpu)
 kvm_msr_entry_add(cpu, MSR_IA32_SGXLEPUBKEYHASH3, 0);
 }
 
+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_7_0_ECX] & CPUID_7_0_ECX_CET_SHSTK) &&
+(env->features[FEAT_XSAVE_XSS_LO] & XSTATE_CET_U_MASK)) {
+kvm_msr_entry_add(cpu, MSR_KVM_GUEST_SSP, 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_XSAVE] & CPUID_D_1_EAX_XFD) {
 kvm_msr_entry_add(cpu, MSR_IA32_XFD, 0);
 kvm_msr_entry_add(cpu, MSR_IA32_XFD_ERR, 0);
@@ -4346,6 +4378,18 @@ static int kvm_get_msrs(X86CPU *cpu)
 env->msr_ia32_sgxlepubkeyhash[index - MSR_IA32_SGXLEPUBKEYHASH0] =
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_PL3_SSP:
+env->pl3_ssp = msrs[i].data;
+break;
+case MSR_KVM_GUEST_SSP:
+env->guest_ssp = msrs[i].data;
+break;
 case MSR_IA32_XFD:
 env->msr_xfd = msrs[i].data;
 break;
-- 
2.27.0




[PATCH 0/4] Enable VMM userspace support for CET virtualization

2023-04-21 Thread Yang Weijiang
These are VMM userspace enabling patches for CET virtualization.
Currently CET user mode SHSTK/IBT and kernel mode IBT are supported.
supervisor SHSTK are not supported now, so related MSRs support
are not included in this series.

Yang Weijiang (4):
  target/i386: Enable XSAVES support for user mode CET states
  target/i386: Add CET MSRs access interfaces
  target/i386: Enable CET states migration
  target/i386: Advertise CET flags in feature words

 target/i386/cpu.c | 47 ++---
 target/i386/cpu.h | 23 
 target/i386/kvm/kvm.c | 44 +++
 target/i386/machine.c | 81 +++
 4 files changed, 183 insertions(+), 12 deletions(-)

base-commit: c283ff89d11ff123efc9af49128ef58511f73012
-- 
2.27.0




[PATCH 1/4] target/i386: Enable XSAVES support for user mode CET states

2023-04-21 Thread Yang Weijiang
Add CET_U bit support in XSS MSR and report data size in CPUID.
XSAVES/XRSTORS are used to boost CET states save/restore process,
XSS[bit 11] corresponds to user mode CET states.
CET Shadow Stack(SHSTK) and Indirect Branch Tracking(IBT) features
are enumerated via CPUID.(EAX=07H,ECX=0H):ECX[7] and EDX[20]
respectively, two featues share the same bit for user mode states.

Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 39 +++
 target/i386/cpu.h | 13 +
 2 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index cab1e2a957..be86df8c1d 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -943,7 +943,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
 .feat_names = {
 NULL, NULL, NULL, NULL,
 NULL, NULL, NULL, NULL,
-NULL, NULL, NULL, NULL,
+NULL, NULL, NULL, "cet-u",
 NULL, NULL, NULL, NULL,
 NULL, NULL, NULL, NULL,
 NULL, NULL, NULL, NULL,
@@ -1420,7 +1420,7 @@ static const X86RegisterInfo32 
x86_reg_info_32[CPU_NB_REGS32] = {
 #undef REGISTER
 
 /* CPUID feature bits available in XSS */
-#define CPUID_XSTATE_XSS_MASK(XSTATE_ARCH_LBR_MASK)
+#define CPUID_XSTATE_XSS_MASK(XSTATE_ARCH_LBR_MASK | XSTATE_CET_U_MASK)
 
 ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = {
 [XSTATE_FP_BIT] = {
@@ -1438,7 +1438,7 @@ ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = {
 .size = sizeof(XSaveAVX) },
 [XSTATE_BNDREGS_BIT] =
   { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX,
-.size = sizeof(XSaveBNDREG)  },
+.size = sizeof(XSaveBNDREG) },
 [XSTATE_BNDCSR_BIT] =
   { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX,
 .size = sizeof(XSaveBNDCSR)  },
@@ -1458,14 +1458,20 @@ ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] 
= {
 .feature = FEAT_7_0_EDX, .bits = CPUID_7_0_EDX_ARCH_LBR,
 .offset = 0 /*supervisor mode component, offset = 0 */,
 .size = sizeof(XSavesArchLBR) },
+[XSTATE_CET_U_BIT] = {
+.feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_CET_SHSTK,
+/*
+ * The features enabled in XSS MSR always use compacted format
+ * to store the data, in this case .offset == 0.
+ */
+.offset = 0,
+.size = sizeof(XSavesCETU) },
 [XSTATE_XTILE_CFG_BIT] = {
 .feature = FEAT_7_0_EDX, .bits = CPUID_7_0_EDX_AMX_TILE,
-.size = sizeof(XSaveXTILECFG),
-},
+.size = sizeof(XSaveXTILECFG) },
 [XSTATE_XTILE_DATA_BIT] = {
 .feature = FEAT_7_0_EDX, .bits = CPUID_7_0_EDX_AMX_TILE,
-.size = sizeof(XSaveXTILEDATA)
-},
+.size = sizeof(XSaveXTILEDATA) }
 };
 
 uint32_t xsave_area_size(uint64_t mask, bool compacted)
@@ -6258,9 +6264,26 @@ 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) {
+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);
+}
+}
 }
 
-/* Only request permission for first vcpu */
+/* Only request permission from fisrt vcpu. */
 if (kvm_enabled() && !request_perm) {
 kvm_request_xsave_components(cpu, mask);
 request_perm = true;
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index d243e290d3..6526a03206 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -554,6 +554,7 @@ typedef enum X86Seg {
 #define XSTATE_ZMM_Hi256_BIT6
 #define XSTATE_Hi16_ZMM_BIT 7
 #define XSTATE_PKRU_BIT 9
+#define XSTATE_CET_U_BIT11
 #define XSTATE_ARCH_LBR_BIT 15
 #define XSTATE_XTILE_CFG_BIT17
 #define XSTATE_XTILE_DATA_BIT   18
@@ -567,6 +568,7 @@ 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_ARCH_LBR_MASK(1ULL << XSTATE_ARCH_LBR_BIT)
 #define XSTATE_XTILE_CFG_MASK 

Re: [RESEND PATCH v2] target/i386: Switch back XFRM value

2023-03-27 Thread Yang, Weijiang



On 3/27/2023 3:33 PM, Christian Ehrhardt wrote:

On Thu, Oct 27, 2022 at 2:36 AM Yang, Weijiang  wrote:


On 10/26/2022 7:57 PM, Zhong, Yang wrote:

The previous patch wrongly replaced FEAT_XSAVE_XCR0_{LO|HI} with
FEAT_XSAVE_XSS_{LO|HI} in CPUID(EAX=12,ECX=1):{ECX,EDX}, which made
SGX enclave only supported SSE and x87 feature(xfrm=0x3).

Fixes: 301e90675c3f ("target/i386: Enable support for XSAVES based features")

Signed-off-by: Yang Zhong 
---
   target/i386/cpu.c | 4 ++--
   1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index ad623d91e4..19aaed877b 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -5584,8 +5584,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, 
uint32_t count,
   } else {
   *eax &= env->features[FEAT_SGX_12_1_EAX];
   *ebx &= 0; /* ebx reserve */
-*ecx &= env->features[FEAT_XSAVE_XSS_LO];
-*edx &= env->features[FEAT_XSAVE_XSS_HI];
+*ecx &= env->features[FEAT_XSAVE_XCR0_LO];
+*edx &= env->features[FEAT_XSAVE_XCR0_HI];

Oops, that's my fault to replace with wrong definitions, thanks for the fix!

Reviewed-by:  Yang Weijiang 

Hi,
I do not have any background on this but stumbled over this and wondered,
is there any particular reason why this wasn't applied yet?

It seemed to fix a former mistake, was acked and then ... silence


Chris, thanks for the catch!

I double checked this patch isn't in the latest 8.0.0-rc1 tree.


Hi, Paolo,

Could you help merge this fixup patch? Thanks!




   /* FP and SSE are always allowed regardless of XSAVE/XCR0. */
   *ecx |= XSTATE_FP_MASK | XSTATE_SSE_MASK;






Re: [RESEND PATCH v2] target/i386: Switch back XFRM value

2022-10-26 Thread Yang, Weijiang



On 10/26/2022 7:57 PM, Zhong, Yang wrote:

The previous patch wrongly replaced FEAT_XSAVE_XCR0_{LO|HI} with
FEAT_XSAVE_XSS_{LO|HI} in CPUID(EAX=12,ECX=1):{ECX,EDX}, which made
SGX enclave only supported SSE and x87 feature(xfrm=0x3).

Fixes: 301e90675c3f ("target/i386: Enable support for XSAVES based features")

Signed-off-by: Yang Zhong 
---
  target/i386/cpu.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index ad623d91e4..19aaed877b 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -5584,8 +5584,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, 
uint32_t count,
  } else {
  *eax &= env->features[FEAT_SGX_12_1_EAX];
  *ebx &= 0; /* ebx reserve */
-*ecx &= env->features[FEAT_XSAVE_XSS_LO];
-*edx &= env->features[FEAT_XSAVE_XSS_HI];
+*ecx &= env->features[FEAT_XSAVE_XCR0_LO];
+*edx &= env->features[FEAT_XSAVE_XCR0_HI];


Oops, that's my fault to replace with wrong definitions, thanks for the fix!

Reviewed-by:  Yang Weijiang 

  
  /* FP and SSE are always allowed regardless of XSAVE/XCR0. */

  *ecx |= XSTATE_FP_MASK | XSTATE_SSE_MASK;




[PATCH] target/i386: Remove LBREn bit check when access Arch LBR MSRs

2022-05-17 Thread Yang Weijiang
Live migration can happen when Arch LBR LBREn bit is cleared,
e.g., when migration happens after guest entered SMM mode.
In this case, we still need to migrate Arch LBR MSRs.

Signed-off-by: Yang Weijiang 
---
 target/i386/kvm/kvm.c | 21 +
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index a9ee8eebd7..e2d675115b 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -3373,15 +3373,14 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
 int i, ret;
 
 /*
- * Only migrate Arch LBR states when: 1) Arch LBR is enabled
- * for migrated vcpu. 2) the host Arch LBR depth equals that
- * of source guest's, this is to avoid mismatch of guest/host
- * config for the msr hence avoid unexpected misbehavior.
+ * Only migrate Arch LBR states when the host Arch LBR depth
+ * equals that of source guest's, this is to avoid mismatch
+ * of guest/host config for the msr hence avoid unexpected
+ * misbehavior.
  */
 ret = kvm_get_one_msr(cpu, MSR_ARCH_LBR_DEPTH, );
 
-if (ret == 1 && (env->msr_lbr_ctl & 0x1) && !!depth &&
-depth == env->msr_lbr_depth) {
+if (ret == 1 && !!depth && depth == env->msr_lbr_depth) {
 kvm_msr_entry_add(cpu, MSR_ARCH_LBR_CTL, env->msr_lbr_ctl);
 kvm_msr_entry_add(cpu, MSR_ARCH_LBR_DEPTH, env->msr_lbr_depth);
 
@@ -3801,13 +3800,11 @@ static int kvm_get_msrs(X86CPU *cpu)
 
 if (kvm_enabled() && cpu->enable_pmu &&
 (env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR)) {
-uint64_t ctl, depth;
-int i, ret2;
+uint64_t depth;
+int i, ret;
 
-ret = kvm_get_one_msr(cpu, MSR_ARCH_LBR_CTL, );
-ret2 = kvm_get_one_msr(cpu, MSR_ARCH_LBR_DEPTH, );
-if (ret == 1 && ret2 == 1 && (ctl & 0x1) &&
-depth == ARCH_LBR_NR_ENTRIES) {
+ret = kvm_get_one_msr(cpu, MSR_ARCH_LBR_DEPTH, );
+if (ret == 1 && depth == ARCH_LBR_NR_ENTRIES) {
 kvm_msr_entry_add(cpu, MSR_ARCH_LBR_CTL, 0);
 kvm_msr_entry_add(cpu, MSR_ARCH_LBR_DEPTH, 0);
 

base-commit: 8eccdb9eb84615291faef1257d5779ebfef7a0d0
-- 
2.27.0




[PATCH 5/8] target/i386: Add XSAVES support for Arch LBR

2022-02-16 Thread Yang Weijiang
Define Arch LBR bit in XSS and save/restore structure
for XSAVE area size calculation.

Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c |  6 +-
 target/i386/cpu.h | 23 +++
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 496e906233..e505c926b2 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1414,7 +1414,7 @@ static const X86RegisterInfo32 
x86_reg_info_32[CPU_NB_REGS32] = {
 #undef REGISTER
 
 /* CPUID feature bits available in XSS */
-#define CPUID_XSTATE_XSS_MASK(0)
+#define CPUID_XSTATE_XSS_MASK(XSTATE_ARCH_LBR_MASK)
 
 ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = {
 [XSTATE_FP_BIT] = {
@@ -1448,6 +1448,10 @@ ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = 
{
 [XSTATE_PKRU_BIT] =
   { .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_PKU,
 .size = sizeof(XSavePKRU) },
+[XSTATE_ARCH_LBR_BIT] = {
+.feature = FEAT_7_0_EDX, .bits = CPUID_7_0_EDX_ARCH_LBR,
+.offset = 0 /*supervisor mode component, offset = 0 */,
+.size = sizeof(XSavesArchLBR) },
 [XSTATE_XTILE_CFG_BIT] = {
 .feature = FEAT_7_0_EDX, .bits = CPUID_7_0_EDX_AMX_TILE,
 .size = sizeof(XSaveXTILECFG),
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 1d17196a0b..07b198539b 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -541,6 +541,7 @@ typedef enum X86Seg {
 #define XSTATE_ZMM_Hi256_BIT6
 #define XSTATE_Hi16_ZMM_BIT 7
 #define XSTATE_PKRU_BIT 9
+#define XSTATE_ARCH_LBR_BIT 15
 #define XSTATE_XTILE_CFG_BIT17
 #define XSTATE_XTILE_DATA_BIT   18
 
@@ -553,6 +554,7 @@ 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_ARCH_LBR_MASK(1ULL << XSTATE_ARCH_LBR_BIT)
 #define XSTATE_XTILE_CFG_MASK   (1ULL << XSTATE_XTILE_CFG_BIT)
 #define XSTATE_XTILE_DATA_MASK  (1ULL << XSTATE_XTILE_DATA_BIT)
 #define XFEATURE_XTILE_MASK (XSTATE_XTILE_CFG_MASK \
@@ -867,6 +869,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)
+/* Architectural LBRs */
+#define CPUID_7_0_EDX_ARCH_LBR  (1U << 19)
 /* AVX512_FP16 instruction */
 #define CPUID_7_0_EDX_AVX512_FP16   (1U << 23)
 /* AMX tile (two-dimensional register) */
@@ -1386,6 +1390,24 @@ typedef struct XSaveXTILEDATA {
 uint8_t xtiledata[8][1024];
 } XSaveXTILEDATA;
 
+typedef struct {
+   uint64_t from;
+   uint64_t to;
+   uint64_t info;
+} LBR_ENTRY;
+
+#define ARCH_LBR_NR_ENTRIES32
+
+/* Ext. save area 19: Supervisor mode Arch LBR state */
+typedef struct XSavesArchLBR {
+uint64_t lbr_ctl;
+uint64_t lbr_depth;
+uint64_t ler_from;
+uint64_t ler_to;
+uint64_t ler_info;
+LBR_ENTRY lbr_records[ARCH_LBR_NR_ENTRIES];
+} XSavesArchLBR;
+
 QEMU_BUILD_BUG_ON(sizeof(XSaveAVX) != 0x100);
 QEMU_BUILD_BUG_ON(sizeof(XSaveBNDREG) != 0x40);
 QEMU_BUILD_BUG_ON(sizeof(XSaveBNDCSR) != 0x40);
@@ -1395,6 +1417,7 @@ QEMU_BUILD_BUG_ON(sizeof(XSaveHi16_ZMM) != 0x400);
 QEMU_BUILD_BUG_ON(sizeof(XSavePKRU) != 0x8);
 QEMU_BUILD_BUG_ON(sizeof(XSaveXTILECFG) != 0x40);
 QEMU_BUILD_BUG_ON(sizeof(XSaveXTILEDATA) != 0x2000);
+QEMU_BUILD_BUG_ON(sizeof(XSavesArchLBR) != 0x328);
 
 typedef struct ExtSaveArea {
 uint32_t feature, bits;
-- 
2.27.0




[PATCH 0/8] Enable Architectural LBR for guest

2022-02-16 Thread Yang Weijiang
Architectural LBR (Arch LBR) is the enhancement for previous
non-Architectural LBR (Legacy LBR). This feature is introduced
in Intel Architecture Instruction Set Extensions and Future
Features Programming Reference[0]. The advantages of Arch LBR
can be referred to in native patch series[1].

Since Arch LBR relies on XSAVES/XRSTORS to boost memory save/
restore, QEMU needs to enable the support for XSS first. Similar
as Legacy LBR, QEMU uses lbr-fmt=0x3f parameter to advertise
Arch LBR feature to guest.

Note, the depth MSR has following side-effects: 1)On write to the
MSR, it'll reset all Arch LBR recording MSRs to 0s. 2) XRSTORS
resets all record MSRs to 0s if the saved depth mismatches
MSR_ARCH_LBR_DEPTH. As the first step, the Arch LBR virtulization
solution only supports guest depth == host depth to simplify the
implementation.

During live migration, before put Arch LBR msrs, it'll check the
depth setting of destination host, the LBR records are written to
destination only if both source and destination host depth MSR
settings match.

This patch series should be built with AMX QEMU patches in order
to set proper xsave area size.

[0]https://software.intel.com/sites/default/files/managed/c5/15/architecture-instruction-set-extensions-programming-reference.pdf
[1]https://lore.kernel.org/lkml/1593780569-62993-1-git-send-email-kan.li...@linux.intel.com/

QEMU base-commit: ad38520bde

patch 1~2: The support patches for legacy LBR.
patch 3:   Add a helper function to clean up code and it'll be 
   used by Arch LBR patch too.
patch 4~5: Enable XSAVES support for Arch LBR.
patch 6~7: Enable Arch LBR live migration support.
patch 8:   Advertise Arch LBR feature.

Yang Weijiang (8):
  qdev-properties: Add a new macro with bitmask check for uint64_t
property
  target/i386: Add lbr-fmt vPMU option to support guest LBR
  target/i386: Add kvm_get_one_msr helper
  target/i386: Enable support for XSAVES based features
  target/i386: Add XSAVES support for Arch LBR
  target/i386: Add MSR access interface for Arch LBR
  target/i386: Enable Arch LBR migration states in vmstate
  target/i386: Support Arch LBR in CPUID enumeration

 hw/core/qdev-properties.c|  19 
 include/hw/qdev-properties.h |  12 +++
 target/i386/cpu.c| 169 +--
 target/i386/cpu.h|  56 +++-
 target/i386/kvm/kvm.c| 115 +++-
 target/i386/machine.c|  38 
 6 files changed, 361 insertions(+), 48 deletions(-)

-- 
2.27.0




[PATCH 4/8] target/i386: Enable support for XSAVES based features

2022-02-16 Thread Yang Weijiang
There're some new features, including Arch LBR, depending
on XSAVES/XRSTORS support, the new instructions will
save/restore data based on feature bits enabled in XCR0 | XSS.
This patch adds the basic support for related CPUID enumeration
and meanwhile changes the name from FEAT_XSAVE_COMP_{LO|HI} to
FEAT_XSAVE_XCR0_{LO|HI} to differentiate clearly the feature
bits in XCR0 and those in XSS.

Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 104 +++---
 target/i386/cpu.h |  13 +-
 2 files changed, 91 insertions(+), 26 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index a037bba387..496e906233 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -940,6 +940,34 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
 },
 .tcg_features = TCG_XSAVE_FEATURES,
 },
+[FEAT_XSAVE_XSS_LO] = {
+.type = CPUID_FEATURE_WORD,
+.feat_names = {
+NULL, NULL, NULL, NULL,
+NULL, NULL, NULL, NULL,
+NULL, NULL, NULL, NULL,
+NULL, 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,
+.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 = {
@@ -955,7 +983,7 @@ 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,
@@ -968,7 +996,7 @@ 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,
@@ -1385,6 +1413,9 @@ static const X86RegisterInfo32 
x86_reg_info_32[CPU_NB_REGS32] = {
 };
 #undef REGISTER
 
+/* CPUID feature bits available in XSS */
+#define CPUID_XSTATE_XSS_MASK(0)
+
 ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = {
 [XSTATE_FP_BIT] = {
 /* x87 FP state component is always enabled if XSAVE is supported */
@@ -1427,15 +1458,18 @@ ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] 
= {
 },
 };
 
-static uint32_t xsave_area_size(uint64_t mask)
+static uint32_t xsave_area_size(uint64_t mask, bool compacted)
 {
+uint64_t ret = x86_ext_save_areas[0].size;
+const ExtSaveArea *esa;
+uint32_t offset = 0;
 int i;
-uint64_t ret = 0;
 
-for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
-const ExtSaveArea *esa = _ext_save_areas[i];
+for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
+esa = _ext_save_areas[i];
 if ((mask >> i) & 1) {
-ret = MAX(ret, esa->offset + esa->size);
+offset = compacted ? ret : esa->offset;
+ret = MAX(ret, offset + esa->size);
 }
 }
 return ret;
@@ -1446,10 +1480,10 @@ 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_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];
 }
 
 /* Return name of 32-bit register, from a R_* constant */
@@ -1461,6 +1495,12 @@ static const char *get_register_name_32(unsigned int reg)
 return x86_reg_info_32[reg].name;
 }
 
+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];
+}
+
 /*
  * Returns the set of feature flags that are supported and migratable by
  * QEMU, for a given FeatureWord.
@@ -4628,8 +4668,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

[PATCH 8/8] target/i386: Support Arch LBR in CPUID enumeration

2022-02-16 Thread Yang Weijiang
If CPUID.(EAX=07H, ECX=0):EDX[19] is set to 1, the processor
supports Architectural LBRs. In this case, CPUID leaf 01CH
indicates details of the Architectural LBRs capabilities.
XSAVE support for Architectural LBRs is enumerated in
CPUID.(EAX=0DH, ECX=0FH).

Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 21 -
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index e505c926b2..1092618683 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -858,7 +858,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
 "fsrm", NULL, NULL, NULL,
 "avx512-vp2intersect", NULL, "md-clear", NULL,
 NULL, NULL, "serialize", NULL,
-"tsx-ldtrk", NULL, NULL /* pconfig */, NULL,
+"tsx-ldtrk", NULL, NULL /* pconfig */, "arch-lbr",
 NULL, NULL, "amx-bf16", "avx512-fp16",
 "amx-tile", "amx-int8", "spec-ctrl", "stibp",
 NULL, "arch-capabilities", "core-capability", "ssbd",
@@ -5494,6 +5494,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, 
uint32_t count,
 assert(!(*eax & ~0x1f));
 *ebx &= 0x; /* The count doesn't need to be reliable. */
 break;
+case 0x1C:
+*eax = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x1C, 0, R_EAX);
+*ebx = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x1C, 0, R_EBX);
+*ecx = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x1C, 0, R_ECX);
+*edx = 0;
+break;
 case 0x1F:
 /* V2 Extended Topology Enumeration Leaf */
 if (env->nr_dies < 2) {
@@ -5556,6 +5562,19 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, 
uint32_t count,
 *ebx = xsave_area_size(xstate, true);
 *ecx = env->features[FEAT_XSAVE_XSS_LO];
 *edx = env->features[FEAT_XSAVE_XSS_HI];
+if (kvm_enabled() && cpu->enable_pmu &&
+(env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR) &&
+(*eax & CPUID_XSAVE_XSAVES)) {
+*ecx |= XSTATE_ARCH_LBR_MASK;
+} else {
+*ecx &= ~XSTATE_ARCH_LBR_MASK;
+}
+} else if (count == 0xf && kvm_enabled() && cpu->enable_pmu &&
+   (env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR)) {
+*eax = kvm_arch_get_supported_cpuid(cs->kvm_state, 0xD, 0xf, 
R_EAX);
+*ebx = kvm_arch_get_supported_cpuid(cs->kvm_state, 0xD, 0xf, 
R_EBX);
+*ecx = kvm_arch_get_supported_cpuid(cs->kvm_state, 0xD, 0xf, 
R_ECX);
+*edx = kvm_arch_get_supported_cpuid(cs->kvm_state, 0xD, 0xf, 
R_EDX);
 } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {
 const ExtSaveArea *esa = _ext_save_areas[count];
 
-- 
2.27.0




[PATCH 7/8] target/i386: Enable Arch LBR migration states in vmstate

2022-02-16 Thread Yang Weijiang
The Arch LBR record MSRs and control MSRs will be migrated
to destination guest if the vcpus were running with Arch
LBR active.

Signed-off-by: Yang Weijiang 
---
 target/i386/machine.c | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/target/i386/machine.c b/target/i386/machine.c
index 1f9d0c46f1..08db7d3629 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -136,6 +136,22 @@ static const VMStateDescription vmstate_mtrr_var = {
 #define VMSTATE_MTRR_VARS(_field, _state, _n, _v)\
 VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar)
 
+static const VMStateDescription vmstate_lbr_records_var = {
+.name = "lbr_records_var",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT64(from, LBR_ENTRY),
+VMSTATE_UINT64(to, LBR_ENTRY),
+VMSTATE_UINT64(info, LBR_ENTRY),
+VMSTATE_END_OF_LIST()
+}
+};
+
+#define VMSTATE_LBR_VARS(_field, _state, _n, _v)\
+VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_lbr_records_var, \
+ LBR_ENTRY)
+
 typedef struct x86_FPReg_tmp {
 FPReg *parent;
 uint64_t tmp_mant;
@@ -1523,6 +1539,27 @@ static const VMStateDescription vmstate_amx_xtile = {
 }
 };
 
+static bool arch_lbr_needed(void *opaque)
+{
+X86CPU *cpu = opaque;
+CPUX86State *env = >env;
+
+return !!(env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR);
+}
+
+static const VMStateDescription vmstate_arch_lbr = {
+.name = "cpu/arch_lbr",
+.version_id = 1,
+.minimum_version_id = 1,
+.needed = arch_lbr_needed,
+.fields = (VMStateField[]) {
+VMSTATE_UINT64(env.msr_lbr_ctl, X86CPU),
+VMSTATE_UINT64(env.msr_lbr_depth, X86CPU),
+VMSTATE_LBR_VARS(env.lbr_records, X86CPU, ARCH_LBR_NR_ENTRIES, 1),
+VMSTATE_END_OF_LIST()
+}
+};
+
 const VMStateDescription vmstate_x86_cpu = {
 .name = "cpu",
 .version_id = 12,
@@ -1664,6 +1701,7 @@ const VMStateDescription vmstate_x86_cpu = {
 _pdptrs,
 _msr_xfd,
 _amx_xtile,
+_arch_lbr,
 NULL
 }
 };
-- 
2.27.0




[PATCH 3/8] target/i386: Add kvm_get_one_msr helper

2022-02-16 Thread Yang Weijiang
When try to get one msr from KVM, I found there's no such kind of
existing interface while kvm_put_one_msr() is there. So here comes
the patch. It'll remove redundant preparation code before finally
call KVM_GET_MSRS IOCTL.

No functional change intended.

Signed-off-by: Yang Weijiang 
---
 target/i386/kvm/kvm.c | 48 ---
 1 file changed, 27 insertions(+), 21 deletions(-)

diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 8dbda2420d..764d110e0f 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -136,6 +136,7 @@ static struct kvm_msr_list *kvm_feature_msrs;
 
 #define BUS_LOCK_SLICE_TIME 10ULL /* ns */
 static RateLimit bus_lock_ratelimit_ctrl;
+static int kvm_get_one_msr(X86CPU *cpu, int index, uint64_t *value);
 
 int kvm_has_pit_state2(void)
 {
@@ -206,28 +207,21 @@ static int kvm_get_tsc(CPUState *cs)
 {
 X86CPU *cpu = X86_CPU(cs);
 CPUX86State *env = >env;
-struct {
-struct kvm_msrs info;
-struct kvm_msr_entry entries[1];
-} msr_data = {};
+uint64_t value;
 int ret;
 
 if (env->tsc_valid) {
 return 0;
 }
 
-memset(_data, 0, sizeof(msr_data));
-msr_data.info.nmsrs = 1;
-msr_data.entries[0].index = MSR_IA32_TSC;
 env->tsc_valid = !runstate_is_running();
 
-ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, _data);
+ret = kvm_get_one_msr(cpu, MSR_IA32_TSC, );
 if (ret < 0) {
 return ret;
 }
 
-assert(ret == 1);
-env->tsc = msr_data.entries[0].data;
+env->tsc = value;
 return 0;
 }
 
@@ -1485,21 +1479,14 @@ static int hyperv_init_vcpu(X86CPU *cpu)
  * the kernel doesn't support setting vp_index; assert that its value
  * is in sync
  */
-struct {
-struct kvm_msrs info;
-struct kvm_msr_entry entries[1];
-} msr_data = {
-.info.nmsrs = 1,
-.entries[0].index = HV_X64_MSR_VP_INDEX,
-};
-
-ret = kvm_vcpu_ioctl(cs, KVM_GET_MSRS, _data);
+uint64_t value;
+
+ret = kvm_get_one_msr(cpu, HV_X64_MSR_VP_INDEX, );
 if (ret < 0) {
 return ret;
 }
-assert(ret == 1);
 
-if (msr_data.entries[0].data != hyperv_vp_index(CPU(cpu))) {
+if (value != hyperv_vp_index(CPU(cpu))) {
 error_report("kernel's vp_index != QEMU's vp_index");
 return -ENXIO;
 }
@@ -2752,6 +2739,25 @@ static int kvm_put_one_msr(X86CPU *cpu, int index, 
uint64_t value)
 return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf);
 }
 
+static int kvm_get_one_msr(X86CPU *cpu, int index, uint64_t *value)
+{
+int ret;
+struct {
+struct kvm_msrs info;
+struct kvm_msr_entry entries[1];
+} msr_data = {
+.info.nmsrs = 1,
+.entries[0].index = index,
+};
+
+ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, _data);
+if (ret < 0) {
+return ret;
+}
+assert(ret == 1);
+*value = msr_data.entries[0].data;
+return ret;
+}
 void kvm_put_apicbase(X86CPU *cpu, uint64_t value)
 {
 int ret;
-- 
2.27.0




[PATCH 1/8] qdev-properties: Add a new macro with bitmask check for uint64_t property

2022-02-16 Thread Yang Weijiang
The DEFINE_PROP_UINT64_CHECKMASK maro applies certain mask check agaist
user-supplied property value, reject the value if it violates the bitmask.

Co-developed-by: Like Xu 
Signed-off-by: Like Xu 
Signed-off-by: Yang Weijiang 
---
 hw/core/qdev-properties.c| 19 +++
 include/hw/qdev-properties.h | 12 
 2 files changed, 31 insertions(+)

diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index c34aac6ebc..27566e5ef7 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -428,6 +428,25 @@ const PropertyInfo qdev_prop_int64 = {
 .set_default_value = qdev_propinfo_set_default_value_int,
 };
 
+static void set_uint64_checkmask(Object *obj, Visitor *v, const char *name,
+  void *opaque, Error **errp)
+{
+Property *prop = opaque;
+uint64_t *ptr = object_field_prop_ptr(obj, prop);
+
+visit_type_uint64(v, name, ptr, errp);
+if (*ptr & ~prop->bitmask) {
+error_setg(errp, "Property value for '%s' violates bitmask '0x%lx'",
+   name, prop->bitmask);
+}
+}
+
+const PropertyInfo qdev_prop_uint64_checkmask = {
+.name  = "uint64",
+.get   = get_uint64,
+.set   = set_uint64_checkmask,
+};
+
 /* --- string --- */
 
 static void release_string(Object *obj, const char *name, void *opaque)
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index f7925f67d0..e1df08876c 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -17,6 +17,7 @@ struct Property {
 const PropertyInfo *info;
 ptrdiff_toffset;
 uint8_t  bitnr;
+uint64_t bitmask;
 bool set_default;
 union {
 int64_t i;
@@ -54,6 +55,7 @@ extern const PropertyInfo qdev_prop_uint16;
 extern const PropertyInfo qdev_prop_uint32;
 extern const PropertyInfo qdev_prop_int32;
 extern const PropertyInfo qdev_prop_uint64;
+extern const PropertyInfo qdev_prop_uint64_checkmask;
 extern const PropertyInfo qdev_prop_int64;
 extern const PropertyInfo qdev_prop_size;
 extern const PropertyInfo qdev_prop_string;
@@ -103,6 +105,16 @@ extern const PropertyInfo qdev_prop_link;
 .set_default = true, \
 .defval.u= (bool)_defval)
 
+/**
+ * The DEFINE_PROP_UINT64_CHECKMASK macro checks a user-supplied value
+ * against corresponding bitmask, rejects the value if it violates.
+ * The default value is set in instance_init().
+ */
+#define DEFINE_PROP_UINT64_CHECKMASK(_name, _state, _field, _bitmask)   \
+DEFINE_PROP(_name, _state, _field, qdev_prop_uint64_checkmask, uint64_t, \
+.bitmask= (_bitmask), \
+.set_default = false)
+
 #define PROP_ARRAY_LEN_PREFIX "len-"
 
 /**
-- 
2.27.0




[PATCH 2/8] target/i386: Add lbr-fmt vPMU option to support guest LBR

2022-02-16 Thread Yang Weijiang
The Last Branch Recording (LBR) is a performance monitor unit (PMU)
feature on Intel processors which records a running trace of the most
recent branches taken by the processor in the LBR stack. This option
indicates the LBR format to enable for guest perf.

The LBR feature is enabled if below conditions are met:
1) KVM is enabled and the PMU is enabled.
2) msr-based-feature IA32_PERF_CAPABILITIES is supporterd on KVM.
3) Supported returned value for lbr_fmt from above msr is non-zero.
4) Guest vcpu model does support FEAT_1_ECX.CPUID_EXT_PDCM.
5) User-provided lbr-fmt value doesn't violate its bitmask (0x3f).
6) Target guest LBR format matches that of host.

Co-developed-by: Like Xu 
Signed-off-by: Like Xu 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 40 
 target/i386/cpu.h | 10 ++
 2 files changed, 50 insertions(+)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 9543762e7e..a037bba387 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -6370,6 +6370,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error 
**errp)
 CPUX86State *env = >env;
 Error *local_err = NULL;
 static bool ht_warned;
+uint64_t requested_lbr_fmt;
 
 if (cpu->apic_id == UNASSIGNED_APIC_ID) {
 error_setg(errp, "apic-id property was not initialized properly");
@@ -6387,6 +6388,42 @@ static void x86_cpu_realizefn(DeviceState *dev, Error 
**errp)
 goto out;
 }
 
+/*
+ * Override env->features[FEAT_PERF_CAPABILITIES].LBR_FMT
+ * with user-provided setting.
+ */
+if (cpu->lbr_fmt != ~PERF_CAP_LBR_FMT) {
+if ((cpu->lbr_fmt & PERF_CAP_LBR_FMT) != cpu->lbr_fmt) {
+error_setg(errp, "invalid lbr-fmt");
+return;
+}
+env->features[FEAT_PERF_CAPABILITIES] &= ~PERF_CAP_LBR_FMT;
+env->features[FEAT_PERF_CAPABILITIES] |= cpu->lbr_fmt;
+}
+
+/*
+ * vPMU LBR is supported when 1) KVM is enabled 2) Option pmu=on and
+ * 3)vPMU LBR format matches that of host setting.
+ */
+requested_lbr_fmt =
+env->features[FEAT_PERF_CAPABILITIES] & PERF_CAP_LBR_FMT;
+if (requested_lbr_fmt && kvm_enabled()) {
+uint64_t host_perf_cap =
+x86_cpu_get_supported_feature_word(FEAT_PERF_CAPABILITIES, false);
+uint64_t host_lbr_fmt = host_perf_cap & PERF_CAP_LBR_FMT;
+
+if (!cpu->enable_pmu) {
+error_setg(errp, "vPMU: LBR is unsupported without pmu=on");
+return;
+}
+if (requested_lbr_fmt != host_lbr_fmt) {
+error_setg(errp, "vPMU: the lbr-fmt value (0x%lx) mismatches "
+"the host supported value (0x%lx).",
+requested_lbr_fmt, host_lbr_fmt);
+return;
+}
+}
+
 x86_cpu_filter_features(cpu, cpu->check_cpuid || cpu->enforce_cpuid);
 
 if (cpu->enforce_cpuid && x86_cpu_have_filtered_features(cpu)) {
@@ -6739,6 +6776,8 @@ static void x86_cpu_initfn(Object *obj)
 object_property_add_alias(obj, "sse4_2", obj, "sse4.2");
 
 object_property_add_alias(obj, "hv-apicv", obj, "hv-avic");
+cpu->lbr_fmt = ~PERF_CAP_LBR_FMT;
+object_property_add_alias(obj, "lbr_fmt", obj, "lbr-fmt");
 
 if (xcc->model) {
 x86_cpu_load_model(cpu, xcc->model);
@@ -6894,6 +6933,7 @@ static Property x86_cpu_properties[] = {
 #endif
 DEFINE_PROP_INT32("node-id", X86CPU, node_id, CPU_UNSET_NUMA_NODE_ID),
 DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false),
+DEFINE_PROP_UINT64_CHECKMASK("lbr-fmt", X86CPU, lbr_fmt, PERF_CAP_LBR_FMT),
 
 DEFINE_PROP_UINT32("hv-spinlocks", X86CPU, hyperv_spinlock_attempts,
HYPERV_SPINLOCK_NEVER_NOTIFY),
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 509c16323a..852afabe0b 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -383,6 +383,7 @@ typedef enum X86Seg {
 #define ARCH_CAP_TSX_CTRL_MSR  (1<<7)
 
 #define MSR_IA32_PERF_CAPABILITIES  0x345
+#define PERF_CAP_LBR_FMT0x3f
 
 #define MSR_IA32_TSX_CTRL  0x122
 #define MSR_IA32_TSCDEADLINE0x6e0
@@ -1819,6 +1820,15 @@ struct X86CPU {
  */
 bool enable_pmu;
 
+/*
+ * Enable LBR_FMT bits of IA32_PERF_CAPABILITIES MSR.
+ * This can't be initialized with a default because it doesn't have
+ * stable ABI support yet. It is only allowed to pass all LBR_FMT bits
+ * returned by kvm_arch_get_supported_msr_feature()(which depends on both
+ * host CPU and kernel capabilities) to the guest.
+ */
+uint64_t lbr_fmt;
+
 /* LMCE support can be enabled/disabled via cpu option 'lmce=on/off'. It is
  * disabled by default to avoid breaking migration between QEMU with
  * different LMCE configurations.
-- 
2.27.0




[PATCH 6/8] target/i386: Add MSR access interface for Arch LBR

2022-02-16 Thread Yang Weijiang
In the first generation of Arch LBR, the max support
Arch LBR depth is 32, both host and guest use the value
to set depth MSR. This can simplify the implementation
of patch given the side-effect of mismatch of host/guest
depth MSR: XRSTORS will reset all recording MSRs to 0s
if the saved depth mismatches MSR_ARCH_LBR_DEPTH.

In most of the cases Arch LBR is not in active status,
so check the control bit before save/restore the big
chunck of Arch LBR MSRs.

Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.h | 10 +++
 target/i386/kvm/kvm.c | 67 +++
 2 files changed, 77 insertions(+)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 07b198539b..0cadd37c47 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -388,6 +388,11 @@ typedef enum X86Seg {
 #define MSR_IA32_TSX_CTRL  0x122
 #define MSR_IA32_TSCDEADLINE0x6e0
 #define MSR_IA32_PKRS   0x6e1
+#define MSR_ARCH_LBR_CTL0x14ce
+#define MSR_ARCH_LBR_DEPTH  0x14cf
+#define MSR_ARCH_LBR_FROM_0 0x1500
+#define MSR_ARCH_LBR_TO_0   0x1600
+#define MSR_ARCH_LBR_INFO_0 0x1200
 
 #define FEATURE_CONTROL_LOCKED(1<<0)
 #define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX  (1ULL << 1)
@@ -1659,6 +1664,11 @@ typedef struct CPUX86State {
 uint64_t msr_xfd;
 uint64_t msr_xfd_err;
 
+/* Per-VCPU Arch LBR MSRs */
+uint64_t msr_lbr_ctl;
+uint64_t msr_lbr_depth;
+LBR_ENTRY lbr_records[ARCH_LBR_NR_ENTRIES];
+
 /* exception/interrupt handling */
 int error_code;
 int exception_is_int;
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 764d110e0f..974ff3c0a5 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -3273,6 +3273,38 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
   env->msr_xfd_err);
 }
 
+if (kvm_enabled() && cpu->enable_pmu &&
+(env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR)) {
+uint64_t depth;
+int i, ret;
+
+/*
+ * Only migrate Arch LBR states when: 1) Arch LBR is enabled
+ * for migrated vcpu. 2) the host Arch LBR depth equals that
+ * of source guest's, this is to avoid mismatch of guest/host
+ * config for the msr hence avoid unexpected misbehavior.
+ */
+ret = kvm_get_one_msr(cpu, MSR_ARCH_LBR_DEPTH, );
+
+if (ret == 1 && (env->msr_lbr_ctl & 0x1) && !!depth &&
+depth == env->msr_lbr_depth) {
+kvm_msr_entry_add(cpu, MSR_ARCH_LBR_CTL, env->msr_lbr_ctl);
+kvm_msr_entry_add(cpu, MSR_ARCH_LBR_DEPTH, env->msr_lbr_depth);
+
+for (i = 0; i < ARCH_LBR_NR_ENTRIES; i++) {
+if (!env->lbr_records[i].from) {
+continue;
+}
+kvm_msr_entry_add(cpu, MSR_ARCH_LBR_FROM_0 + i,
+  env->lbr_records[i].from);
+kvm_msr_entry_add(cpu, MSR_ARCH_LBR_TO_0 + i,
+  env->lbr_records[i].to);
+kvm_msr_entry_add(cpu, MSR_ARCH_LBR_INFO_0 + i,
+  env->lbr_records[i].info);
+}
+}
+}
+
 /* Note: MSR_IA32_FEATURE_CONTROL is written separately, see
  *   kvm_put_msr_feature_control. */
 }
@@ -3670,6 +3702,26 @@ static int kvm_get_msrs(X86CPU *cpu)
 kvm_msr_entry_add(cpu, MSR_IA32_XFD_ERR, 0);
 }
 
+if (kvm_enabled() && cpu->enable_pmu &&
+(env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR)) {
+uint64_t ctl, depth;
+int i, ret2;
+
+ret = kvm_get_one_msr(cpu, MSR_ARCH_LBR_CTL, );
+ret2 = kvm_get_one_msr(cpu, MSR_ARCH_LBR_DEPTH, );
+if (ret == 1 && ret2 == 1 && (ctl & 0x1) &&
+depth == ARCH_LBR_NR_ENTRIES) {
+kvm_msr_entry_add(cpu, MSR_ARCH_LBR_CTL, 0);
+kvm_msr_entry_add(cpu, MSR_ARCH_LBR_DEPTH, 0);
+
+for (i = 0; i < ARCH_LBR_NR_ENTRIES; i++) {
+kvm_msr_entry_add(cpu, MSR_ARCH_LBR_FROM_0 + i, 0);
+kvm_msr_entry_add(cpu, MSR_ARCH_LBR_TO_0 + i, 0);
+kvm_msr_entry_add(cpu, MSR_ARCH_LBR_INFO_0 + i, 0);
+}
+}
+}
+
 ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, cpu->kvm_msr_buf);
 if (ret < 0) {
 return ret;
@@ -3972,6 +4024,21 @@ static int kvm_get_msrs(X86CPU *cpu)
 case MSR_IA32_XFD_ERR:
 env->msr_xfd_err = msrs[i].data;
 break;
+case MSR_ARCH_LBR_CTL:
+env->msr_lbr_ctl = msrs[i].data;
+b

Re: [PATCH v2] target/i386: Add kvm_get_one_msr helper

2022-02-11 Thread Yang, Weijiang

Ping...

Does this v2 meet the requirement?

On 1/30/2022 7:07 AM, Yang Weijiang wrote:

When try to get one msr from KVM, I found there's no such kind of
existing interface while kvm_put_one_msr() is there. So here comes
the patch. It'll remove redundant preparation code before finally
call KVM_GET_MSRS IOCTL.

No functional change intended.

v2:
  Per Paolo's suggestion, move the helper before uses to eliminate
  a forward declaration.

base-commit: 48302d4eb628ff0bea4d7e92cbf6b726410eb4c3

Signed-off-by: Yang Weijiang 
---
  target/i386/kvm/kvm.c | 48 ---
  1 file changed, 27 insertions(+), 21 deletions(-)

diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 2c8feb4a6f..627535395a 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -201,32 +201,45 @@ bool kvm_hv_vpindex_settable(void)
  return hv_vpindex_settable;
  }
  
-static int kvm_get_tsc(CPUState *cs)

+static int kvm_get_one_msr(X86CPU *cpu, int index, uint64_t *value)
  {
-X86CPU *cpu = X86_CPU(cs);
-CPUX86State *env = >env;
+int ret;
  struct {
  struct kvm_msrs info;
  struct kvm_msr_entry entries[1];
-} msr_data = {};
+} msr_data = {
+.info.nmsrs = 1,
+.entries[0].index = index,
+};
+
+ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, _data);
+if (ret < 0) {
+return ret;
+}
+assert(ret == 1);
+*value = msr_data.entries[0].data;
+return ret;
+}
+
+static int kvm_get_tsc(CPUState *cs)
+{
+X86CPU *cpu = X86_CPU(cs);
+CPUX86State *env = >env;
+uint64_t value;
  int ret;
  
  if (env->tsc_valid) {

  return 0;
  }
  
-memset(_data, 0, sizeof(msr_data));

-msr_data.info.nmsrs = 1;
-msr_data.entries[0].index = MSR_IA32_TSC;
  env->tsc_valid = !runstate_is_running();
  
-ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, _data);

+ret = kvm_get_one_msr(cpu, MSR_IA32_TSC, );
  if (ret < 0) {
  return ret;
  }
  
-assert(ret == 1);

-env->tsc = msr_data.entries[0].data;
+env->tsc = value;
  return 0;
  }
  
@@ -1478,21 +1491,14 @@ static int hyperv_init_vcpu(X86CPU *cpu)

   * the kernel doesn't support setting vp_index; assert that its value
   * is in sync
   */
-struct {
-struct kvm_msrs info;
-struct kvm_msr_entry entries[1];
-} msr_data = {
-.info.nmsrs = 1,
-.entries[0].index = HV_X64_MSR_VP_INDEX,
-};
-
-ret = kvm_vcpu_ioctl(cs, KVM_GET_MSRS, _data);
+uint64_t value;
+
+ret = kvm_get_one_msr(cpu, HV_X64_MSR_VP_INDEX, );
  if (ret < 0) {
  return ret;
  }
-assert(ret == 1);
  
-if (msr_data.entries[0].data != hyperv_vp_index(CPU(cpu))) {

+if (value != hyperv_vp_index(CPU(cpu))) {
  error_report("kernel's vp_index != QEMU's vp_index");
  return -ENXIO;
  }




Re: [PATCH v5 0/2] Enable legacy LBR support for guest

2022-02-09 Thread Yang, Weijiang



On 2/9/2022 5:14 PM, Like Xu wrote:

Hi Weijiang,

On 23/1/2022 12:11 am, Yang Weijiang wrote:

KVM legacy LBR patches have been merged in kernel 5.12, this patchset
is to expose the feature to guest from the perf capability MSR. Qemu can
add LBR format in cpu option to achieve it, e.g., -cpu host,lbr-fmt=0x5,


Some older Intel CPUs may have lbr-fmt=LBR_FORMAT_32 (which is 0), would
you help verify that KVM is supported on these platforms ? If so, how 
do we enable

guest LBR form the QEMU side, w/ -cpu host,lbr-fmt=0x0 ?


Hi, Like, do you know which cpu model or platform so that I can have a 
test on?





the format should match host value in IA32_PERF_CAPABILITIES.

Note, KVM legacy LBR solution accelerates guest perf performace by 
LBR MSR

passthrough so it requires guest cpu model matches that of host's, i.e.,


Would you help add live migration support across host/guest CPU models 
when
hosts at both ends have the same number of LBR entries and the same 
lbr-fmt ?
Yes, I'm working on this part for Arch LBR, then enable it for legacy 
LBR as well.


Thanks,
Like Xu


only -cpu host is supported.

Change in v5:
1. This patchset is rebased on tip : 6621441db5
2. No functional change since v4.




[PATCH v2] target/i386: Add kvm_get_one_msr helper

2022-01-30 Thread Yang Weijiang
When try to get one msr from KVM, I found there's no such kind of
existing interface while kvm_put_one_msr() is there. So here comes
the patch. It'll remove redundant preparation code before finally
call KVM_GET_MSRS IOCTL.

No functional change intended.

v2:
 Per Paolo's suggestion, move the helper before uses to eliminate
 a forward declaration.

base-commit: 48302d4eb628ff0bea4d7e92cbf6b726410eb4c3

Signed-off-by: Yang Weijiang 
---
 target/i386/kvm/kvm.c | 48 ---
 1 file changed, 27 insertions(+), 21 deletions(-)

diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 2c8feb4a6f..627535395a 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -201,32 +201,45 @@ bool kvm_hv_vpindex_settable(void)
 return hv_vpindex_settable;
 }
 
-static int kvm_get_tsc(CPUState *cs)
+static int kvm_get_one_msr(X86CPU *cpu, int index, uint64_t *value)
 {
-X86CPU *cpu = X86_CPU(cs);
-CPUX86State *env = >env;
+int ret;
 struct {
 struct kvm_msrs info;
 struct kvm_msr_entry entries[1];
-} msr_data = {};
+} msr_data = {
+.info.nmsrs = 1,
+.entries[0].index = index,
+};
+
+ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, _data);
+if (ret < 0) {
+return ret;
+}
+assert(ret == 1);
+*value = msr_data.entries[0].data;
+return ret;
+}
+
+static int kvm_get_tsc(CPUState *cs)
+{
+X86CPU *cpu = X86_CPU(cs);
+CPUX86State *env = >env;
+uint64_t value;
 int ret;
 
 if (env->tsc_valid) {
 return 0;
 }
 
-memset(_data, 0, sizeof(msr_data));
-msr_data.info.nmsrs = 1;
-msr_data.entries[0].index = MSR_IA32_TSC;
 env->tsc_valid = !runstate_is_running();
 
-ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, _data);
+ret = kvm_get_one_msr(cpu, MSR_IA32_TSC, );
 if (ret < 0) {
 return ret;
 }
 
-assert(ret == 1);
-env->tsc = msr_data.entries[0].data;
+env->tsc = value;
 return 0;
 }
 
@@ -1478,21 +1491,14 @@ static int hyperv_init_vcpu(X86CPU *cpu)
  * the kernel doesn't support setting vp_index; assert that its value
  * is in sync
  */
-struct {
-struct kvm_msrs info;
-struct kvm_msr_entry entries[1];
-} msr_data = {
-.info.nmsrs = 1,
-.entries[0].index = HV_X64_MSR_VP_INDEX,
-};
-
-ret = kvm_vcpu_ioctl(cs, KVM_GET_MSRS, _data);
+uint64_t value;
+
+ret = kvm_get_one_msr(cpu, HV_X64_MSR_VP_INDEX, );
 if (ret < 0) {
 return ret;
 }
-assert(ret == 1);
 
-if (msr_data.entries[0].data != hyperv_vp_index(CPU(cpu))) {
+if (value != hyperv_vp_index(CPU(cpu))) {
 error_report("kernel's vp_index != QEMU's vp_index");
 return -ENXIO;
 }
-- 
2.27.0




Re: [PATCH] target/i386: Add kvm_get_one_msr helper

2022-01-28 Thread Yang, Weijiang



On 1/28/2022 6:55 PM, Paolo Bonzini wrote:

On 1/27/22 16:58, Yang Weijiang wrote:

@@ -135,6 +135,7 @@ static struct kvm_msr_list *kvm_feature_msrs;
    #define BUS_LOCK_SLICE_TIME 10ULL /* ns */
  static RateLimit bus_lock_ratelimit_ctrl;
+static int kvm_get_one_msr(X86CPU *cpu, int index, uint64_t *value);
    int kvm_has_pit_state2(void)
  {


...

@@ -2734,6 +2721,25 @@ static int kvm_put_one_msr(X86CPU *cpu, int 
index, uint64_t value)

  return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf);
  }
  +static int kvm_get_one_msr(X86CPU *cpu, int index, uint64_t *value)
+{
+    int ret;
+    struct {
+    struct kvm_msrs info;
+    struct kvm_msr_entry entries[1];
+    } msr_data = {
+    .info.nmsrs = 1,
+    .entries[0].index = index,
+    };
+
+    ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, _data);
+    if (ret < 0) {
+    return ret;
+    }
+    assert(ret == 1);
+    *value = msr_data.entries[0].data;
+    return ret;
+}
  void kvm_put_apicbase(X86CPU *cpu, uint64_t value)
  {
  int ret;


The patch is a good idea, but you can put the function before the 
uses.  This way there will be no need for a forward declaration, either.


Thanks Paolo!

Is v2 version required for this?



Thanks,

Paolo




[PATCH] target/i386: Add kvm_get_one_msr helper

2022-01-27 Thread Yang Weijiang
When try to get one msr from KVM, I found there's no such kind of
existing interface while kvm_put_one_msr() is there. So here comes
the patch. It'll remove redundant preparation code before finally
call KVM_GET_MSRS IOCTL.

No functional change intended.

Signed-off-by: Yang Weijiang 
---
 target/i386/kvm/kvm.c | 48 ---
 1 file changed, 27 insertions(+), 21 deletions(-)

diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 2c8feb4a6f..c897dbaf60 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -135,6 +135,7 @@ static struct kvm_msr_list *kvm_feature_msrs;
 
 #define BUS_LOCK_SLICE_TIME 10ULL /* ns */
 static RateLimit bus_lock_ratelimit_ctrl;
+static int kvm_get_one_msr(X86CPU *cpu, int index, uint64_t *value);
 
 int kvm_has_pit_state2(void)
 {
@@ -205,28 +206,21 @@ static int kvm_get_tsc(CPUState *cs)
 {
 X86CPU *cpu = X86_CPU(cs);
 CPUX86State *env = >env;
-struct {
-struct kvm_msrs info;
-struct kvm_msr_entry entries[1];
-} msr_data = {};
+uint64_t value;
 int ret;
 
 if (env->tsc_valid) {
 return 0;
 }
 
-memset(_data, 0, sizeof(msr_data));
-msr_data.info.nmsrs = 1;
-msr_data.entries[0].index = MSR_IA32_TSC;
 env->tsc_valid = !runstate_is_running();
 
-ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, _data);
+ret = kvm_get_one_msr(cpu, MSR_IA32_TSC, );
 if (ret < 0) {
 return ret;
 }
 
-assert(ret == 1);
-env->tsc = msr_data.entries[0].data;
+env->tsc = value;
 return 0;
 }
 
@@ -1478,21 +1472,14 @@ static int hyperv_init_vcpu(X86CPU *cpu)
  * the kernel doesn't support setting vp_index; assert that its value
  * is in sync
  */
-struct {
-struct kvm_msrs info;
-struct kvm_msr_entry entries[1];
-} msr_data = {
-.info.nmsrs = 1,
-.entries[0].index = HV_X64_MSR_VP_INDEX,
-};
-
-ret = kvm_vcpu_ioctl(cs, KVM_GET_MSRS, _data);
+uint64_t value;
+
+ret = kvm_get_one_msr(cpu, HV_X64_MSR_VP_INDEX, );
 if (ret < 0) {
 return ret;
 }
-assert(ret == 1);
 
-if (msr_data.entries[0].data != hyperv_vp_index(CPU(cpu))) {
+if (value != hyperv_vp_index(CPU(cpu))) {
 error_report("kernel's vp_index != QEMU's vp_index");
 return -ENXIO;
 }
@@ -2734,6 +2721,25 @@ static int kvm_put_one_msr(X86CPU *cpu, int index, 
uint64_t value)
 return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf);
 }
 
+static int kvm_get_one_msr(X86CPU *cpu, int index, uint64_t *value)
+{
+int ret;
+struct {
+struct kvm_msrs info;
+struct kvm_msr_entry entries[1];
+} msr_data = {
+.info.nmsrs = 1,
+.entries[0].index = index,
+};
+
+ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, _data);
+if (ret < 0) {
+return ret;
+}
+assert(ret == 1);
+*value = msr_data.entries[0].data;
+return ret;
+}
 void kvm_put_apicbase(X86CPU *cpu, uint64_t value)
 {
 int ret;
-- 
2.27.0




[PATCH v5 1/2] qdev-properties: Add a new macro with bitmask check for uint64_t property

2022-01-22 Thread Yang Weijiang
The DEFINE_PROP_UINT64_CHECKMASK maro applies certain mask check agaist
user-supplied property value, reject the value if it violates the bitmask.

Co-developed-by: Like Xu 
Signed-off-by: Like Xu 
Signed-off-by: Yang Weijiang 
---
 hw/core/qdev-properties.c| 19 +++
 include/hw/qdev-properties.h | 12 
 2 files changed, 31 insertions(+)

diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index c34aac6ebc..27566e5ef7 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -428,6 +428,25 @@ const PropertyInfo qdev_prop_int64 = {
 .set_default_value = qdev_propinfo_set_default_value_int,
 };
 
+static void set_uint64_checkmask(Object *obj, Visitor *v, const char *name,
+  void *opaque, Error **errp)
+{
+Property *prop = opaque;
+uint64_t *ptr = object_field_prop_ptr(obj, prop);
+
+visit_type_uint64(v, name, ptr, errp);
+if (*ptr & ~prop->bitmask) {
+error_setg(errp, "Property value for '%s' violates bitmask '0x%lx'",
+   name, prop->bitmask);
+}
+}
+
+const PropertyInfo qdev_prop_uint64_checkmask = {
+.name  = "uint64",
+.get   = get_uint64,
+.set   = set_uint64_checkmask,
+};
+
 /* --- string --- */
 
 static void release_string(Object *obj, const char *name, void *opaque)
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index f7925f67d0..e1df08876c 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -17,6 +17,7 @@ struct Property {
 const PropertyInfo *info;
 ptrdiff_toffset;
 uint8_t  bitnr;
+uint64_t bitmask;
 bool set_default;
 union {
 int64_t i;
@@ -54,6 +55,7 @@ extern const PropertyInfo qdev_prop_uint16;
 extern const PropertyInfo qdev_prop_uint32;
 extern const PropertyInfo qdev_prop_int32;
 extern const PropertyInfo qdev_prop_uint64;
+extern const PropertyInfo qdev_prop_uint64_checkmask;
 extern const PropertyInfo qdev_prop_int64;
 extern const PropertyInfo qdev_prop_size;
 extern const PropertyInfo qdev_prop_string;
@@ -103,6 +105,16 @@ extern const PropertyInfo qdev_prop_link;
 .set_default = true, \
 .defval.u= (bool)_defval)
 
+/**
+ * The DEFINE_PROP_UINT64_CHECKMASK macro checks a user-supplied value
+ * against corresponding bitmask, rejects the value if it violates.
+ * The default value is set in instance_init().
+ */
+#define DEFINE_PROP_UINT64_CHECKMASK(_name, _state, _field, _bitmask)   \
+DEFINE_PROP(_name, _state, _field, qdev_prop_uint64_checkmask, uint64_t, \
+.bitmask= (_bitmask), \
+.set_default = false)
+
 #define PROP_ARRAY_LEN_PREFIX "len-"
 
 /**
-- 
2.27.0




[PATCH v5 0/2] Enable legacy LBR support for guest

2022-01-22 Thread Yang Weijiang
KVM legacy LBR patches have been merged in kernel 5.12, this patchset
is to expose the feature to guest from the perf capability MSR. Qemu can
add LBR format in cpu option to achieve it, e.g., -cpu host,lbr-fmt=0x5,
the format should match host value in IA32_PERF_CAPABILITIES.

Note, KVM legacy LBR solution accelerates guest perf performace by LBR MSR
passthrough so it requires guest cpu model matches that of host's, i.e.,
only -cpu host is supported.

Change in v5:
1. This patchset is rebased on tip : 6621441db5
2. No functional change since v4.


Yang Weijiang (2):
  qdev-properties: Add a new macro with bitmask check for uint64_t
property
  target/i386: Add lbr-fmt vPMU option to support guest LBR

 hw/core/qdev-properties.c| 19 +
 include/hw/qdev-properties.h | 12 +++
 target/i386/cpu.c| 40 
 target/i386/cpu.h| 10 +
 4 files changed, 81 insertions(+)

-- 
2.27.0




[PATCH v5 2/2] target/i386: Add lbr-fmt vPMU option to support guest LBR

2022-01-22 Thread Yang Weijiang
The Last Branch Recording (LBR) is a performance monitor unit (PMU)
feature on Intel processors which records a running trace of the most
recent branches taken by the processor in the LBR stack. This option
indicates the LBR format to enable for guest perf.

The LBR feature is enabled if below conditions are met:
1) KVM is enabled and the PMU is enabled.
2) msr-based-feature IA32_PERF_CAPABILITIES is supporterd on KVM.
3) Supported returned value for lbr_fmt from above msr is non-zero.
4) Guest vcpu model does support FEAT_1_ECX.CPUID_EXT_PDCM.
5) User-provided lbr-fmt value doesn't violate its bitmask (0x3f).
6) Target guest LBR format matches that of host.

Co-developed-by: Like Xu 
Signed-off-by: Like Xu 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 40 
 target/i386/cpu.h | 10 ++
 2 files changed, 50 insertions(+)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index aa9e636800..55eb519214 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -6280,6 +6280,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error 
**errp)
 CPUX86State *env = >env;
 Error *local_err = NULL;
 static bool ht_warned;
+uint64_t requested_lbr_fmt;
 
 if (cpu->apic_id == UNASSIGNED_APIC_ID) {
 error_setg(errp, "apic-id property was not initialized properly");
@@ -6297,6 +6298,42 @@ static void x86_cpu_realizefn(DeviceState *dev, Error 
**errp)
 goto out;
 }
 
+/*
+ * Override env->features[FEAT_PERF_CAPABILITIES].LBR_FMT
+ * with user-provided setting.
+ */
+if (cpu->lbr_fmt != ~PERF_CAP_LBR_FMT) {
+if ((cpu->lbr_fmt & PERF_CAP_LBR_FMT) != cpu->lbr_fmt) {
+error_setg(errp, "invalid lbr-fmt");
+return;
+}
+env->features[FEAT_PERF_CAPABILITIES] &= ~PERF_CAP_LBR_FMT;
+env->features[FEAT_PERF_CAPABILITIES] |= cpu->lbr_fmt;
+}
+
+/*
+ * vPMU LBR is supported when 1) KVM is enabled 2) Option pmu=on and
+ * 3)vPMU LBR format matches that of host setting.
+ */
+requested_lbr_fmt =
+env->features[FEAT_PERF_CAPABILITIES] & PERF_CAP_LBR_FMT;
+if (requested_lbr_fmt && kvm_enabled()) {
+uint64_t host_perf_cap =
+x86_cpu_get_supported_feature_word(FEAT_PERF_CAPABILITIES, false);
+uint64_t host_lbr_fmt = host_perf_cap & PERF_CAP_LBR_FMT;
+
+if (!cpu->enable_pmu) {
+error_setg(errp, "vPMU: LBR is unsupported without pmu=on");
+return;
+}
+if (requested_lbr_fmt != host_lbr_fmt) {
+error_setg(errp, "vPMU: the lbr-fmt value (0x%lx) mismatches "
+"the host supported value (0x%lx).",
+requested_lbr_fmt, host_lbr_fmt);
+return;
+}
+}
+
 x86_cpu_filter_features(cpu, cpu->check_cpuid || cpu->enforce_cpuid);
 
 if (cpu->enforce_cpuid && x86_cpu_have_filtered_features(cpu)) {
@@ -6649,6 +6686,8 @@ static void x86_cpu_initfn(Object *obj)
 object_property_add_alias(obj, "sse4_2", obj, "sse4.2");
 
 object_property_add_alias(obj, "hv-apicv", obj, "hv-avic");
+cpu->lbr_fmt = ~PERF_CAP_LBR_FMT;
+object_property_add_alias(obj, "lbr_fmt", obj, "lbr-fmt");
 
 if (xcc->model) {
 x86_cpu_load_model(cpu, xcc->model);
@@ -6804,6 +6843,7 @@ static Property x86_cpu_properties[] = {
 #endif
 DEFINE_PROP_INT32("node-id", X86CPU, node_id, CPU_UNSET_NUMA_NODE_ID),
 DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false),
+DEFINE_PROP_UINT64_CHECKMASK("lbr-fmt", X86CPU, lbr_fmt, PERF_CAP_LBR_FMT),
 
 DEFINE_PROP_UINT32("hv-spinlocks", X86CPU, hyperv_spinlock_attempts,
HYPERV_SPINLOCK_NEVER_NOTIFY),
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 9911d7c871..ee8974abc9 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -383,6 +383,7 @@ typedef enum X86Seg {
 #define ARCH_CAP_TSX_CTRL_MSR  (1<<7)
 
 #define MSR_IA32_PERF_CAPABILITIES  0x345
+#define PERF_CAP_LBR_FMT0x3f
 
 #define MSR_IA32_TSX_CTRL  0x122
 #define MSR_IA32_TSCDEADLINE0x6e0
@@ -1775,6 +1776,15 @@ struct X86CPU {
  */
 bool enable_pmu;
 
+/*
+ * Enable LBR_FMT bits of IA32_PERF_CAPABILITIES MSR.
+ * This can't be initialized with a default because it doesn't have
+ * stable ABI support yet. It is only allowed to pass all LBR_FMT bits
+ * returned by kvm_arch_get_supported_msr_feature()(which depends on both
+ * host CPU and kernel capabilities) to the guest.
+ */
+uint64_t lbr_fmt;
+
 /* LMCE support can be enabled/disabled via cpu option 'lmce=on/off'. It is
  * disabled by default to avoid breaking migration between QEMU with
  * different LMCE configurations.
-- 
2.27.0




Re: [PATCH v4 1/2] qdev-properties: Add a new macro with bitmask check for uint64_t property

2021-08-26 Thread Yang Weijiang
On Sun, Jun 20, 2021 at 10:42:36AM +0800, Yang, Weijiang wrote:

Hi, Paolo and Eduardo,

Legacy Arch LBR patches have been merged in 5.12 kernel tree, these patches
are corresponding change from QEMU side, without these patches,legacy Arch LBR
cannot work, could you review them at your convenience?

Thanks a lot!

> The DEFINE_PROP_UINT64_CHECKMASK maro applies certain mask check agaist
> user-supplied property value, reject the value if it violates the bitmask.
> 
> Co-developed-by: Like Xu 
> Signed-off-by: Like Xu 
> Signed-off-by: Yang Weijiang 
> ---
>  hw/core/qdev-properties.c| 19 +++
>  include/hw/qdev-properties.h | 12 
>  2 files changed, 31 insertions(+)
> 
> diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
> index 50f40949f5..343a200784 100644
> --- a/hw/core/qdev-properties.c
> +++ b/hw/core/qdev-properties.c
> @@ -428,6 +428,25 @@ const PropertyInfo qdev_prop_int64 = {
>  .set_default_value = qdev_propinfo_set_default_value_int,
>  };
>  
> +static void set_uint64_checkmask(Object *obj, Visitor *v, const char *name,
> +  void *opaque, Error **errp)
> +{
> +Property *prop = opaque;
> +uint64_t *ptr = object_field_prop_ptr(obj, prop);
> +
> +visit_type_uint64(v, name, ptr, errp);
> +if (*ptr & ~prop->bitmask) {
> +error_setg(errp, "Property value for '%s' violates bitmask '0x%lx'",
> +   name, prop->bitmask);
> +}
> +}
> +
> +const PropertyInfo qdev_prop_uint64_checkmask = {
> +.name  = "uint64",
> +.get   = get_uint64,
> +.set   = set_uint64_checkmask,
> +};
> +
>  /* --- string --- */
>  
>  static void release_string(Object *obj, const char *name, void *opaque)
> diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
> index 0ef97d60ce..075882e8c1 100644
> --- a/include/hw/qdev-properties.h
> +++ b/include/hw/qdev-properties.h
> @@ -17,6 +17,7 @@ struct Property {
>  const PropertyInfo *info;
>  ptrdiff_toffset;
>  uint8_t  bitnr;
> +uint64_t bitmask;
>  bool set_default;
>  union {
>  int64_t i;
> @@ -53,6 +54,7 @@ extern const PropertyInfo qdev_prop_uint16;
>  extern const PropertyInfo qdev_prop_uint32;
>  extern const PropertyInfo qdev_prop_int32;
>  extern const PropertyInfo qdev_prop_uint64;
> +extern const PropertyInfo qdev_prop_uint64_checkmask;
>  extern const PropertyInfo qdev_prop_int64;
>  extern const PropertyInfo qdev_prop_size;
>  extern const PropertyInfo qdev_prop_string;
> @@ -102,6 +104,16 @@ extern const PropertyInfo qdev_prop_link;
>  .set_default = true, \
>  .defval.u= (bool)_defval)
>  
> +/**
> + * The DEFINE_PROP_UINT64_CHECKMASK macro checks a user-supplied value
> + * against corresponding bitmask, rejects the value if it violates.
> + * The default value is set in instance_init().
> + */
> +#define DEFINE_PROP_UINT64_CHECKMASK(_name, _state, _field, _bitmask)   \
> +DEFINE_PROP(_name, _state, _field, qdev_prop_uint64_checkmask, uint64_t, 
> \
> +.bitmask= (_bitmask), \
> +.set_default = false)
> +
>  #define PROP_ARRAY_LEN_PREFIX "len-"
>  
>  /**
> -- 
> 2.21.1



Re: [PATCH v4 1/2] qdev-properties: Add a new macro with bitmask check for uint64_t property

2021-07-19 Thread Yang Weijiang
Hello, maintainers,

Could you review this patch series kindly since the legacy LBR patches
have been merged in 5.12 kernel tree?

Thanks!

On Sun, Jun 20, 2021 at 10:42:36AM +0800, Yang, Weijiang wrote:
> The DEFINE_PROP_UINT64_CHECKMASK maro applies certain mask check agaist
> user-supplied property value, reject the value if it violates the bitmask.
> 
> Co-developed-by: Like Xu 
> Signed-off-by: Like Xu 
> Signed-off-by: Yang Weijiang 
> ---
>  hw/core/qdev-properties.c| 19 +++
>  include/hw/qdev-properties.h | 12 
>  2 files changed, 31 insertions(+)
> 
> diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
> index 50f40949f5..343a200784 100644
> --- a/hw/core/qdev-properties.c
> +++ b/hw/core/qdev-properties.c
> @@ -428,6 +428,25 @@ const PropertyInfo qdev_prop_int64 = {
>  .set_default_value = qdev_propinfo_set_default_value_int,
>  };
>  
> +static void set_uint64_checkmask(Object *obj, Visitor *v, const char *name,
> +  void *opaque, Error **errp)
> +{
> +Property *prop = opaque;
> +uint64_t *ptr = object_field_prop_ptr(obj, prop);
> +
> +visit_type_uint64(v, name, ptr, errp);
> +if (*ptr & ~prop->bitmask) {
> +error_setg(errp, "Property value for '%s' violates bitmask '0x%lx'",
> +   name, prop->bitmask);
> +}
> +}
> +
> +const PropertyInfo qdev_prop_uint64_checkmask = {
> +.name  = "uint64",
> +.get   = get_uint64,
> +.set   = set_uint64_checkmask,
> +};
> +
>  /* --- string --- */
>  
>  static void release_string(Object *obj, const char *name, void *opaque)
> diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
> index 0ef97d60ce..075882e8c1 100644
> --- a/include/hw/qdev-properties.h
> +++ b/include/hw/qdev-properties.h
> @@ -17,6 +17,7 @@ struct Property {
>  const PropertyInfo *info;
>  ptrdiff_toffset;
>  uint8_t  bitnr;
> +uint64_t bitmask;
>  bool set_default;
>  union {
>  int64_t i;
> @@ -53,6 +54,7 @@ extern const PropertyInfo qdev_prop_uint16;
>  extern const PropertyInfo qdev_prop_uint32;
>  extern const PropertyInfo qdev_prop_int32;
>  extern const PropertyInfo qdev_prop_uint64;
> +extern const PropertyInfo qdev_prop_uint64_checkmask;
>  extern const PropertyInfo qdev_prop_int64;
>  extern const PropertyInfo qdev_prop_size;
>  extern const PropertyInfo qdev_prop_string;
> @@ -102,6 +104,16 @@ extern const PropertyInfo qdev_prop_link;
>  .set_default = true, \
>  .defval.u= (bool)_defval)
>  
> +/**
> + * The DEFINE_PROP_UINT64_CHECKMASK macro checks a user-supplied value
> + * against corresponding bitmask, rejects the value if it violates.
> + * The default value is set in instance_init().
> + */
> +#define DEFINE_PROP_UINT64_CHECKMASK(_name, _state, _field, _bitmask)   \
> +DEFINE_PROP(_name, _state, _field, qdev_prop_uint64_checkmask, uint64_t, 
> \
> +.bitmask= (_bitmask), \
> +.set_default = false)
> +
>  #define PROP_ARRAY_LEN_PREFIX "len-"
>  
>  /**
> -- 
> 2.21.1



[PATCH v4 2/2] target/i386: Add lbr-fmt vPMU option to support guest LBR

2021-06-19 Thread Yang Weijiang
The Last Branch Recording (LBR) is a performance monitor unit (PMU)
feature on Intel processors which records a running trace of the most
recent branches taken by the processor in the LBR stack. This option
indicates the LBR format to enable for guest perf.

The LBR feature is enabled if below conditions are met:
1) KVM is enabled and the PMU is enabled.
2) msr-based-feature IA32_PERF_CAPABILITIES is supporterd on KVM.
3) Supported returned value for lbr_fmt from above msr is non-zero.
4) Guest vcpu model does support FEAT_1_ECX.CPUID_EXT_PDCM.
5) User-provided lbr-fmt value doesn't violate its bitmask (0x3f).
6) Target guest LBR format matches that of host.

Co-developed-by: Like Xu 
Signed-off-by: Like Xu 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 41 +
 target/i386/cpu.h | 10 ++
 2 files changed, 51 insertions(+)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index ad99cad0e7..c80b8b7fe2 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -6701,6 +6701,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error 
**errp)
 CPUX86State *env = >env;
 Error *local_err = NULL;
 static bool ht_warned;
+uint64_t requested_lbr_fmt;
 
 if (xcc->host_cpuid_required) {
 if (!accel_uses_host_cpuid()) {
@@ -6748,6 +6749,42 @@ static void x86_cpu_realizefn(DeviceState *dev, Error 
**errp)
 goto out;
 }
 
+/*
+ * Override env->features[FEAT_PERF_CAPABILITIES].LBR_FMT
+ * with user-provided setting.
+ */
+if (cpu->lbr_fmt != ~PERF_CAP_LBR_FMT) {
+if ((cpu->lbr_fmt & PERF_CAP_LBR_FMT) != cpu->lbr_fmt) {
+error_setg(errp, "invalid lbr-fmt");
+return;
+}
+env->features[FEAT_PERF_CAPABILITIES] &= ~PERF_CAP_LBR_FMT;
+env->features[FEAT_PERF_CAPABILITIES] |= cpu->lbr_fmt;
+}
+
+/*
+ * vPMU LBR is supported when 1) KVM is enabled 2) Option pmu=on and
+ * 3)vPMU LBR format matches that of host setting.
+ */
+requested_lbr_fmt =
+env->features[FEAT_PERF_CAPABILITIES] & PERF_CAP_LBR_FMT;
+if (requested_lbr_fmt && kvm_enabled()) {
+uint64_t host_perf_cap =
+x86_cpu_get_supported_feature_word(FEAT_PERF_CAPABILITIES, false);
+uint64_t host_lbr_fmt = host_perf_cap & PERF_CAP_LBR_FMT;
+
+if (!cpu->enable_pmu) {
+error_setg(errp, "vPMU: LBR is unsupported without pmu=on");
+return;
+}
+if (requested_lbr_fmt != host_lbr_fmt) {
+error_setg(errp, "vPMU: the lbr-fmt value (0x%lx) mismatches "
+"the host supported value (0x%lx).",
+requested_lbr_fmt, host_lbr_fmt);
+return;
+}
+}
+
 x86_cpu_filter_features(cpu, cpu->check_cpuid || cpu->enforce_cpuid);
 
 if (cpu->enforce_cpuid && x86_cpu_have_filtered_features(cpu)) {
@@ -7150,6 +7187,9 @@ static void x86_cpu_initfn(Object *obj)
 object_property_add_alias(obj, "sse4_1", obj, "sse4.1");
 object_property_add_alias(obj, "sse4_2", obj, "sse4.2");
 
+cpu->lbr_fmt = ~PERF_CAP_LBR_FMT;
+object_property_add_alias(obj, "lbr_fmt", obj, "lbr-fmt");
+
 if (xcc->model) {
 x86_cpu_load_model(cpu, xcc->model);
 }
@@ -7300,6 +7340,7 @@ static Property x86_cpu_properties[] = {
 #endif
 DEFINE_PROP_INT32("node-id", X86CPU, node_id, CPU_UNSET_NUMA_NODE_ID),
 DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false),
+DEFINE_PROP_UINT64_CHECKMASK("lbr-fmt", X86CPU, lbr_fmt, PERF_CAP_LBR_FMT),
 
 DEFINE_PROP_UINT32("hv-spinlocks", X86CPU, hyperv_spinlock_attempts,
HYPERV_SPINLOCK_NEVER_NOTIFY),
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 1bc300ce85..50e6d66791 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -354,6 +354,7 @@ typedef enum X86Seg {
 #define ARCH_CAP_TSX_CTRL_MSR  (1<<7)
 
 #define MSR_IA32_PERF_CAPABILITIES  0x345
+#define PERF_CAP_LBR_FMT0x3f
 
 #define MSR_IA32_TSX_CTRL  0x122
 #define MSR_IA32_TSCDEADLINE0x6e0
@@ -1726,6 +1727,15 @@ struct X86CPU {
  */
 bool enable_pmu;
 
+/*
+ * Enable LBR_FMT bits of IA32_PERF_CAPABILITIES MSR.
+ * This can't be initialized with a default because it doesn't have
+ * stable ABI support yet. It is only allowed to pass all LBR_FMT bits
+ * returned by kvm_arch_get_supported_msr_feature()(which depends on both
+ * host CPU and kernel capabilities) to the guest.
+ */
+uint64_t lbr_fmt;
+
 /* LMCE support can be enabled/disabled via cpu option 'lmce=on/off'. It is
  * disabled by default to avoid breaking migration between QEMU with
  * different LMCE configurations.
-- 
2.21.1




[PATCH v4 1/2] qdev-properties: Add a new macro with bitmask check for uint64_t property

2021-06-19 Thread Yang Weijiang
The DEFINE_PROP_UINT64_CHECKMASK maro applies certain mask check agaist
user-supplied property value, reject the value if it violates the bitmask.

Co-developed-by: Like Xu 
Signed-off-by: Like Xu 
Signed-off-by: Yang Weijiang 
---
 hw/core/qdev-properties.c| 19 +++
 include/hw/qdev-properties.h | 12 
 2 files changed, 31 insertions(+)

diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 50f40949f5..343a200784 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -428,6 +428,25 @@ const PropertyInfo qdev_prop_int64 = {
 .set_default_value = qdev_propinfo_set_default_value_int,
 };
 
+static void set_uint64_checkmask(Object *obj, Visitor *v, const char *name,
+  void *opaque, Error **errp)
+{
+Property *prop = opaque;
+uint64_t *ptr = object_field_prop_ptr(obj, prop);
+
+visit_type_uint64(v, name, ptr, errp);
+if (*ptr & ~prop->bitmask) {
+error_setg(errp, "Property value for '%s' violates bitmask '0x%lx'",
+   name, prop->bitmask);
+}
+}
+
+const PropertyInfo qdev_prop_uint64_checkmask = {
+.name  = "uint64",
+.get   = get_uint64,
+.set   = set_uint64_checkmask,
+};
+
 /* --- string --- */
 
 static void release_string(Object *obj, const char *name, void *opaque)
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 0ef97d60ce..075882e8c1 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -17,6 +17,7 @@ struct Property {
 const PropertyInfo *info;
 ptrdiff_toffset;
 uint8_t  bitnr;
+uint64_t bitmask;
 bool set_default;
 union {
 int64_t i;
@@ -53,6 +54,7 @@ extern const PropertyInfo qdev_prop_uint16;
 extern const PropertyInfo qdev_prop_uint32;
 extern const PropertyInfo qdev_prop_int32;
 extern const PropertyInfo qdev_prop_uint64;
+extern const PropertyInfo qdev_prop_uint64_checkmask;
 extern const PropertyInfo qdev_prop_int64;
 extern const PropertyInfo qdev_prop_size;
 extern const PropertyInfo qdev_prop_string;
@@ -102,6 +104,16 @@ extern const PropertyInfo qdev_prop_link;
 .set_default = true, \
 .defval.u= (bool)_defval)
 
+/**
+ * The DEFINE_PROP_UINT64_CHECKMASK macro checks a user-supplied value
+ * against corresponding bitmask, rejects the value if it violates.
+ * The default value is set in instance_init().
+ */
+#define DEFINE_PROP_UINT64_CHECKMASK(_name, _state, _field, _bitmask)   \
+DEFINE_PROP(_name, _state, _field, qdev_prop_uint64_checkmask, uint64_t, \
+.bitmask= (_bitmask), \
+.set_default = false)
+
 #define PROP_ARRAY_LEN_PREFIX "len-"
 
 /**
-- 
2.21.1




[PATCH v8 5/6] target/i386: Add CET state support for guest migration

2021-05-19 Thread Yang Weijiang
Save the MSRs being used on source machine and restore them
on destination machine.

Signed-off-by: Yang Weijiang 
---
 target/i386/machine.c | 161 ++
 1 file changed, 161 insertions(+)

diff --git a/target/i386/machine.c b/target/i386/machine.c
index 137604ddb8..4d63340931 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -1000,6 +1000,159 @@ static const VMStateDescription vmstate_umwait = {
 }
 };
 
+static bool u_cet_needed(void *opaque)
+{
+X86CPU *cpu = opaque;
+CPUX86State *env = >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 = >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 = >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 = >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 = >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 = >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 = >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 = >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()
+}
+};
+
 static bool pkru_needed(void *opaque)
 {
 X86CPU *cpu = opaque;
@@ -1531,6 +1684,14 @@ VMStateDescription vmstate_x86_cpu = {
 _nested_state,
 #endif
 _msr_tsx_ctrl,
+_u_cet,
+_s_cet,
+_pl0_ssp,
+_pl1_ssp,
+_pl2_ssp,
+_pl3_ssp,
+_ssp_tbl,
+_guest_ssp,
 NULL
 }
 };
-- 
2.26.2




[PATCH v8 4/6] target/i386: Add user-space MSR access interface for CET

2021-05-19 Thread 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 
---
 target/i386/cpu.h | 18 +++
 target/i386/kvm/kvm.c | 72 +++
 2 files changed, 90 insertions(+)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 593a2d6823..a5bb049d4e 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -483,6 +483,15 @@ typedef enum X86Seg {
 #define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x0490
 #define MSR_IA32_VMX_VMFUNC 0x0491
 
+#define MSR_IA32_U_CET  0x06a0
+#define MSR_IA32_S_CET  0x06a2
+#define MSR_IA32_PL0_SSP0x06a4
+#define MSR_IA32_PL1_SSP0x06a5
+#define MSR_IA32_PL2_SSP0x06a6
+#define MSR_IA32_PL3_SSP0x06a7
+#define MSR_IA32_SSP_TBL0x06a8
+#define MSR_KVM_GUEST_SSP   0x4b564d08
+
 #define XSTATE_FP_BIT   0
 #define XSTATE_SSE_BIT  1
 #define XSTATE_YMM_BIT  2
@@ -1601,6 +1610,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/kvm.c b/target/i386/kvm/kvm.c
index 7fe9f52710..c36ff7ffec 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -3047,6 +3047,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);
 }
 
@@ -3369,6 +3393,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;
@@ -3658,6 +3706,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

[PATCH v8 6/6] target/i386: Advise CET bits in CPU/MSR feature words

2021-05-19 Thread 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 
---
 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 bae827c8d5..b432b681d8 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -958,7 +958,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,
@@ -981,7 +981,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, "avx512-fp16",
+"ibt", NULL, NULL, "avx512-fp16",
 NULL, NULL, "spec-ctrl", "stibp",
 NULL, "arch-capabilities", "core-capability", "ssbd",
 },
@@ -1243,7 +1243,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, "vmx-exit-load-pkrs", NULL, NULL,
+"vmx-exit-save-cet-ctl", "vmx-exit-load-pkrs", NULL, NULL,
 },
 .msr = {
 .index = MSR_IA32_VMX_TRUE_EXIT_CTLS,
@@ -1258,7 +1258,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, "vmx-entry-load-pkrs", NULL,
+"vmx-entry-load-cet-ctl", NULL, "vmx-entry-load-pkrs", NULL,
 NULL, NULL, NULL, NULL,
 NULL, NULL, NULL, NULL,
 },
-- 
2.26.2




[PATCH v8 1/6] target/i386: Change XSAVE related feature-word names

2021-05-19 Thread Yang Weijiang
Rename XSAVE related feature-words for introducing XSAVES related
feature-words.

Signed-off-by: Yang Weijiang 
---
 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 ad99cad0e7..5c76186883 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1077,7 +1077,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,
@@ -1090,7 +1090,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,
@@ -1519,8 +1519,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];
 }
 
 /* Return name of 32-bit register, from a R_* constant */
@@ -4811,8 +4811,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) {
@@ -5860,8 +5860,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
@@ -6431,8 +6431,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;
 }
 
@@ -6444,8 +6444,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 570f916878..84cb6adcaa 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -526,8 +526,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




[PATCH v8 3/6] target/i386: Enable XSAVES support for CET states

2021-05-19 Thread 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 
---
 target/i386/cpu.c | 42 +-
 target/i386/cpu.h | 21 +
 2 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index d74d68e319..bae827c8d5 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1064,6 +1064,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,
@@ -1472,7 +1482,7 @@ typedef struct ExtSaveArea {
 } ExtSaveArea;
 
 /* CPUID feature bits available in XSS */
-#define CPUID_XSTATE_XSS_MASK0
+#define CPUID_XSTATE_XSS_MASK(XSTATE_CET_U_MASK)
 
 static const ExtSaveArea x86_ext_save_areas[] = {
 [XSTATE_FP_BIT] = {
@@ -1517,6 +1527,19 @@ 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,
+/*
+ * The features enabled in XSS MSR always use compacted format
+ * to store the data, in this case .offset == 0. And CET bits
+ * fall into this category.
+ */
+.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, bool compacted)
@@ -6486,6 +6509,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 42f835d455..593a2d6823 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -492,6 +492,8 @@ typedef enum X86Seg {
 #define XSTATE_ZMM_Hi256_BIT6
 #define XSTATE_Hi16_ZMM_BIT 7
 #define XSTATE_PKRU_BIT 9
+#define XSTATE_CET_U_BIT11
+#define XSTATE_CET_S_BIT12
 
 #define XSTATE_FP_MASK  (1ULL << XSTATE_FP_BIT)
 #define XSTATE_SSE_MASK (1ULL << XSTATE_SSE_BIT)
@@ -502,6 +504,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 | \
@@ -761,6 +765,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 */
@@ -800,6 +806,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_7_0_EDX_SERIALIZE

[PATCH v8 2/6] target/i386: Enable XSS feature CPUID enumeration

2021-05-19 Thread Yang Weijiang
Currently, CPUID.(EAX=0DH,ECX=01H) doesn't enumerate features in XSS
properly, so enable the support. XCR0 bits indicate user-mode XSAVE
components, and XSS bits indicate supervisor-mode XSAVE components.

Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 68 +++
 target/i386/cpu.h |  9 +++
 2 files changed, 66 insertions(+), 11 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 5c76186883..d74d68e319 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1062,6 +1062,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 = {
@@ -1453,6 +1471,9 @@ typedef struct ExtSaveArea {
 uint32_t offset, size;
 } ExtSaveArea;
 
+/* CPUID feature bits available in XSS */
+#define CPUID_XSTATE_XSS_MASK0
+
 static const ExtSaveArea x86_ext_save_areas[] = {
 [XSTATE_FP_BIT] = {
 /* x87 FP state component is always enabled if XSAVE is supported */
@@ -1498,15 +1519,18 @@ static const ExtSaveArea x86_ext_save_areas[] = {
 .size = sizeof(XSavePKRU) },
 };
 
-static uint32_t xsave_area_size(uint64_t mask)
+static uint32_t xsave_area_size(uint64_t mask, bool compacted)
 {
+uint64_t ret = x86_ext_save_areas[0].size;
+const ExtSaveArea *esa;
+uint32_t offset = 0;
 int i;
-uint64_t ret = 0;
 
-for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
-const ExtSaveArea *esa = _ext_save_areas[i];
+for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
+esa = _ext_save_areas[i];
 if ((mask >> i) & 1) {
-ret = MAX(ret, esa->offset + esa->size);
+offset = compacted ? ret : esa->offset;
+ret = MAX(ret, offset + esa->size);
 }
 }
 return ret;
@@ -1517,7 +1541,7 @@ 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];
@@ -1532,6 +1556,12 @@ static const char *get_register_name_32(unsigned int reg)
 return x86_reg_info_32[reg].name;
 }
 
+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];
+}
+
 /*
  * Returns the set of feature flags that are supported and migratable by
  * QEMU, for a given FeatureWord.
@@ -5859,7 +5889,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), false);
 *eax = env->features[FEAT_XSAVE_XCR0_LO];
 *edx = env->features[FEAT_XSAVE_XCR0_HI];
 /*
@@ -5868,14 +5898,25 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, 
uint32_t count,
  * even through guest update xcr0, this will crash some legacy 
guest
  * (e.g., CentOS 6), So set ebx == ecx to workaroud it.
  */
-*ebx = kvm_enabled() ? *ecx : xsave_area_size(env->xcr0);
+*ebx = kvm_enabled() ? *ecx : xsave_area_size(env->xcr0, false);
 } else if (count == 1) {
+uint64_t xstate = x86_cpu_xsave_xcr0_components(cpu) |
+  x86_cpu_xsave_xss_components(cpu);
+
 *eax = env->features[FEAT_XSAVE];
+*ebx = xsave_area_size(xstate, true);
+*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 = _ext_save_areas[count];
+const ExtSaveArea *esa = _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;
+*

[PATCH v8 0/6] Enable CET support for guest

2021-05-19 Thread 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 v8:
- Extended xsave_area_size() to accommodate compacted format size calculation.
- Added CPUID(0xD,1).EBX assigment per maintain's feedback.
- Changed XSS field check and added more comments to make things clearer.
- Other ajustment per maintainer's review feedback.
- Rebased to 6.0.0.

v7 patch:
https://lore.kernel.org/kvm/20210226022058.24562-1-weijiang.y...@intel.com

CET KVM patches:
https://git.kernel.org/pub/scm/virt/kvm/kvm.git/log/?h=intel

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


Yang Weijiang (6):
  target/i386: Change XSAVE related feature-word names
  target/i386: Enable XSS feature CPUID enumeration
  target/i386: Enable XSAVES support for CET states
  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 | 138 +---
 target/i386/cpu.h |  52 +-
 target/i386/kvm/kvm.c |  72 +++
 target/i386/machine.c | 161 ++
 4 files changed, 395 insertions(+), 28 deletions(-)

-- 
2.26.2




Re: [PATCH v7 2/6] target/i386: Enable XSS feature enumeration for CPUID

2021-05-07 Thread Yang Weijiang
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 
> > ---
> >  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 = _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 = _ext_save_areas[count];
> > +const ExtSaveArea *esa = _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 = _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;
> >  }

[...]
  

[PATCH v7 4/6] target/i386: Add user-space MSR access interface for CET

2021-02-25 Thread 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 
---
 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 0x0490
 #define MSR_IA32_VMX_VMFUNC 0x0491
 
+#define MSR_IA32_U_CET  0x06a0
+#define MSR_IA32_S_CET  0x06a2
+#define MSR_IA32_PL0_SSP0x06a4
+#define MSR_IA32_PL1_SSP0x06a5
+#define MSR_IA32_PL2_SSP0x06a6
+#define MSR_IA32_PL3_SSP0x06a7
+#define MSR_IA32_SSP_TBL0x06a8
+#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:
+  

[PATCH v7 5/6] target/i386: Add CET state support for guest migration

2021-02-25 Thread Yang Weijiang
Save the MSRs being used on source machine and restore them
on destination machine.

Signed-off-by: Yang Weijiang 
---
 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 = >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 = >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 = >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 = >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 = >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 = >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 = >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 = >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 = {
 _nested_state,
 #endif
 _msr_tsx_ctrl,
+_u_cet,
+_s_cet,
+_pl0_ssp,
+_pl1_ssp,
+_pl2_ssp,
+_pl3_ssp,
+_ssp_tbl,
+_guest_ssp,
 NULL
 }
 };
-- 
2.26.2




[PATCH v7 2/6] target/i386: Enable XSS feature enumeration for CPUID

2021-02-25 Thread 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 
---
 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 = _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 = _ext_save_areas[count];
+const ExtSaveArea *esa = _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 = _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_M

[PATCH v7 6/6] target/i386: Advise CET bits in CPU/MSR feature words

2021-02-25 Thread 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 
---
 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




[PATCH v7 1/6] target/i386: Change XSAVE related feature-word names

2021-02-25 Thread Yang Weijiang
Rename XSAVE related feature-words for introducing XSAVES related
feature-words.

Signed-off-by: Yang Weijiang 
---
 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




[PATCH v7 0/6] Enable CET support for guest

2021-02-25 Thread 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.y...@intel.com

CET kernel patches:
https://lkml.kernel.org/r/20210217222730.15819-1-yu-cheng...@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




[PATCH v7 3/6] target/i386: Enable CET components support for XSAVES

2021-02-25 Thread 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 
---
 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_BIT6
 #define XSTATE_Hi16_ZMM_BIT 7
 #define XSTATE_PKRU_BIT 9
+#define XSTATE_CET_U_BIT11
+#define XSTATE_CET_S_BIT12
 
 #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_MASK0
+#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 

Re: [Qemu-devel][PATCH] x86/cpu: Use max host physical address if -cpu max option is applied

2021-01-24 Thread Yang Weijiang
On Sun, Jan 24, 2021 at 02:08:29PM -0700, Nathan Chancellor wrote:
> On Wed, Jan 13, 2021 at 05:04:30PM +0800, Yang Weijiang wrote:
> > QEMU option -cpu max(max_features) means "Enables all features supported by
> > the accelerator in the current host", this looks true for all the features
> > except guest max physical address width, so add this patch to enable it.
> > 
> > Signed-off-by: Yang Weijiang 
> > ---
> >  target/i386/cpu.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> > index 35459a38bb..b5943406f7 100644
> > --- a/target/i386/cpu.c
> > +++ b/target/i386/cpu.c
> > @@ -6673,7 +6673,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error 
> > **errp)
> >  warned = true;
> >  }
> >  
> > -if (cpu->host_phys_bits) {
> > +if (cpu->host_phys_bits || cpu->max_features) {
> >  /* The user asked for us to use the host physical bits */
> >  cpu->phys_bits = host_phys_bits;
> >  if (cpu->host_phys_bits_limit &&
> > -- 
> > 2.17.2
> > 
> > 
> 
> Hi,
> 
> This patch as commit 5a140b255d ("x86/cpu: Use max host physical address
> if -cpu max option is applied") prevents me from using '-cpu host' while
> booting an i386_defconfig kernel.
> 
> $ qemu-system-i386 \
> -append console=ttyS0 \
> -cpu host \
> -display none \
> -enable-kvm \
> -initrd rootfs.cpio \
> -kernel bzImage \
> -serial mon:stdio
> qemu-system-i386: phys-bits should be between 32 and 36  (but is 48)
> 
> Am I expected to pass "-cpu host,host-phys-bits=false" now or did this
> do something unexpected?
>
Hi, Nathan,
Could you try Paolo's latest patch?

[PULL 03/31] x86/cpu: Use max host physical address if -cpu max option is 
applied

diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 35459a38bb..72a79e6019 
100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -4319,6 +4319,7 @@ static void max_x86_cpu_initfn(Object *obj)
 if (lmce_supported()) {
 object_property_set_bool(OBJECT(cpu), "lmce", true, _abort);
 }
+object_property_set_bool(OBJECT(cpu), "host-phys-bits", true,
+ _abort);
 } else {
 object_property_set_str(OBJECT(cpu), "vendor", CPUID_VENDOR_AMD,
 _abort);
> Cheers,
> Nathan



Re: [Qemu-devel][PATCH] x86/cpu: Use max host physical address if -cpu max option is applied

2021-01-13 Thread Yang Weijiang
On Wed, Jan 13, 2021 at 11:06:09AM +0100, Paolo Bonzini wrote:
> On 13/01/21 10:04, Yang Weijiang wrote:
> > QEMU option -cpu max(max_features) means "Enables all features supported by
> > the accelerator in the current host", this looks true for all the features
> > except guest max physical address width, so add this patch to enable it.
> > 
> > Signed-off-by: Yang Weijiang 
> > ---
> >   target/i386/cpu.c | 2 +-
> >   1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> > index 35459a38bb..b5943406f7 100644
> > --- a/target/i386/cpu.c
> > +++ b/target/i386/cpu.c
> > @@ -6673,7 +6673,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error 
> > **errp)
> >   warned = true;
> >   }
> > -if (cpu->host_phys_bits) {
> > +if (cpu->host_phys_bits || cpu->max_features) {
> >   /* The user asked for us to use the host physical bits */
> >   cpu->phys_bits = host_phys_bits;
> >   if (cpu->host_phys_bits_limit &&
> > 
> 
> Can you check if this works?
> 
Hi, Paolo,
Yes, below change works for kvm-unit-test/access. Would you add the
patch? 

Thanks!

> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 35459a38bb..72a79e6019 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -4319,6 +4319,7 @@ static void max_x86_cpu_initfn(Object *obj)
>  if (lmce_supported()) {
>  object_property_set_bool(OBJECT(cpu), "lmce", true,
> _abort);
>  }
> +object_property_set_bool(OBJECT(cpu), "host-phys-bits", true,
> _abort);
>  } else {
>  object_property_set_str(OBJECT(cpu), "vendor", CPUID_VENDOR_AMD,
>  _abort);
> 
> 
> It should allow people to use -cpu max,host-phys-bits=false.
> 
> Thanks,
> 
> Paolo



[Qemu-devel][PATCH] x86/cpu: Use max host physical address if -cpu max option is applied

2021-01-13 Thread Yang Weijiang
QEMU option -cpu max(max_features) means "Enables all features supported by
the accelerator in the current host", this looks true for all the features
except guest max physical address width, so add this patch to enable it.

Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 35459a38bb..b5943406f7 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -6673,7 +6673,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error 
**errp)
 warned = true;
 }
 
-if (cpu->host_phys_bits) {
+if (cpu->host_phys_bits || cpu->max_features) {
 /* The user asked for us to use the host physical bits */
 cpu->phys_bits = host_phys_bits;
 if (cpu->host_phys_bits_limit &&
-- 
2.17.2




Re: [Qemu-devel][PATCH v6 1/6] x86/cpu: Rename XSAVE related feature words.

2020-10-14 Thread Yang Weijiang
On Tue, Oct 13, 2020 at 05:08:54PM -0700, Sean Christopherson wrote:
> On Tue, Oct 13, 2020 at 01:19:30PM +0800, Yang Weijiang wrote:
> > With more components in XSS being developed on Intel platform,
> > it's necessary to clean up existing XSAVE related feature words to
> > make the name clearer. It's to prepare for adding CET related support
> > in following patches.
> > 
> > Signed-off-by: Yang Weijiang 
> > ---
> >  target/i386/cpu.c| 60 
> >  target/i386/cpu.h|  6 ++--
> >  target/i386/fpu_helper.c |  2 +-
> >  target/i386/translate.c  |  2 +-
> >  4 files changed, 35 insertions(+), 35 deletions(-)
> > 
> > diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> > index 588f32e136..e2891740f1 100644
> > --- a/target/i386/cpu.c
> > +++ b/target/i386/cpu.c
> > @@ -1050,7 +1050,7 @@ static FeatureWordInfo 
> > feature_word_info[FEATURE_WORDS] = {
> >  .tcg_features = 0,
> >  .unmigratable_flags = 0,
> >  },
> > -[FEAT_XSAVE] = {
> > +[FEAT_XSAVE_INSTRUCTION] = {
> 
> The COMP->XCRO change is great, but I don't think XSAVE->XSAVE_INSTRUCTION
> makes sense.  There is no guarantee the word will only be used for
> instructions; it already blurs the line, e.g. XSAVEC also changes the behavior
> of XRSTOR, and XSAVES also means the XSS MSR is available.
> 
> FWIW, I also don't find FEAT_XSAVE to be confusing.
>
Thanks for the feedback! I also found it's hard to rename it with a
precise one, just wanted to make all XSAVE related feature words more
specific. I'll revert it in next version.

> >  .type = CPUID_FEATURE_WORD,
> >  .feat_names = {
> >  "xsaveopt", "xsavec", "xgetbv1", "xsaves",
> > @@ -1084,7 +1084,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,



[Qemu-devel][PATCH v6 6/6] x86/cpu: Advise CET bits in CPU/MSR feature words

2020-10-12 Thread 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 
---
 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 5496fd68d4..904bf1d4b6 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] = {
 "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",
 },
@@ -1250,7 +1250,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,
@@ -1265,7 +1265,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




[Qemu-devel][PATCH v6 5/6] x86/cpu: Add CET state support for guest migration

2020-10-12 Thread Yang Weijiang
Save the MSRs being used on source machine and restore them
on destination machine.

Signed-off-by: Yang Weijiang 
---
 target/i386/machine.c | 161 ++
 1 file changed, 161 insertions(+)

diff --git a/target/i386/machine.c b/target/i386/machine.c
index b1acf7d0ef..fe4692eaa8 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 = >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 = >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 = >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 = >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 = >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 = >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 = >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 = >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)
 {
@@ -1476,6 +1629,14 @@ VMStateDescription vmstate_x86_cpu = {
 _nested_state,
 #endif
 _msr_tsx_ctrl,
+_u_cet,
+_s_cet,
+_pl0_ssp,
+_pl1_ssp,
+_pl2_ssp,
+_pl3_ssp,
+_ssp_tbl,
+_guest_ssp,
 NULL
 }
 };
-- 
2.26.2




[Qemu-devel][PATCH v6 1/6] x86/cpu: Rename XSAVE related feature words.

2020-10-12 Thread Yang Weijiang
With more components in XSS being developed on Intel platform,
it's necessary to clean up existing XSAVE related feature words to
make the name clearer. It's to prepare for adding CET related support
in following patches.

Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c| 60 
 target/i386/cpu.h|  6 ++--
 target/i386/fpu_helper.c |  2 +-
 target/i386/translate.c  |  2 +-
 4 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 588f32e136..e2891740f1 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1050,7 +1050,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = 
{
 .tcg_features = 0,
 .unmigratable_flags = 0,
 },
-[FEAT_XSAVE] = {
+[FEAT_XSAVE_INSTRUCTION] = {
 .type = CPUID_FEATURE_WORD,
 .feat_names = {
 "xsaveopt", "xsavec", "xgetbv1", "xsaves",
@@ -1084,7 +1084,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,
@@ -1097,7 +1097,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,
@@ -1369,7 +1369,7 @@ static FeatureDep feature_dependencies[] = {
 .to = { FEAT_VMX_SECONDARY_CTLS,~0ull },
 },
 {
-.from = { FEAT_XSAVE,   CPUID_XSAVE_XSAVES },
+.from = { FEAT_XSAVE_INSTRUCTION,   CPUID_XSAVE_XSAVES },
 .to = { FEAT_VMX_SECONDARY_CTLS,VMX_SECONDARY_EXEC_XSAVES },
 },
 {
@@ -1502,8 +1502,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)
@@ -2390,7 +2390,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
 CPUID_EXT2_SYSCALL,
 .features[FEAT_8000_0001_ECX] =
 CPUID_EXT3_LAHF_LM,
-.features[FEAT_XSAVE] =
+.features[FEAT_XSAVE_INSTRUCTION] =
 CPUID_XSAVE_XSAVEOPT,
 .features[FEAT_6_EAX] =
 CPUID_6_EAX_ARAT,
@@ -2479,7 +2479,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
 CPUID_EXT2_SYSCALL,
 .features[FEAT_8000_0001_ECX] =
 CPUID_EXT3_LAHF_LM,
-.features[FEAT_XSAVE] =
+.features[FEAT_XSAVE_INSTRUCTION] =
 CPUID_XSAVE_XSAVEOPT,
 .features[FEAT_6_EAX] =
 CPUID_6_EAX_ARAT,
@@ -2574,7 +2574,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
 CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
 CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
 CPUID_7_0_EBX_RTM,
-.features[FEAT_XSAVE] =
+.features[FEAT_XSAVE_INSTRUCTION] =
 CPUID_XSAVE_XSAVEOPT,
 .features[FEAT_6_EAX] =
 CPUID_6_EAX_ARAT,
@@ -2704,7 +2704,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
 CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
 CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
 CPUID_7_0_EBX_SMAP,
-.features[FEAT_XSAVE] =
+.features[FEAT_XSAVE_INSTRUCTION] =
 CPUID_XSAVE_XSAVEOPT,
 .features[FEAT_6_EAX] =
 CPUID_6_EAX_ARAT,
@@ -2834,7 +2834,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
  * and the only one defined in Skylake (processor tracing)
  * probably will block migration anyway.
  */
-.features[FEAT_XSAVE] =
+.features[FEAT_XSAVE_INSTRUCTION] =
 CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC |
 CPUID_XSAVE_XGETBV1,
 .features[FEAT_6_EAX] =
@@ -2954,7 +2954,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
  * and the only one defined in Skylake (processor tracing)
  * probably will block migration anyway.
  */
-.features[FEAT_XSAVE] =
+.features[FEAT_XSAVE_INSTRUCTION] =
 CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC |
 CPUID_XSAVE_XGETBV1,
 .features[FEAT_6_EAX] =
@@ -3089,7 +3089,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
 * and the only one defined in Skylake (processor 

[Qemu-devel][PATCH v6 3/6] x86/cpu: Enable CET components support for XSAVE

2020-10-12 Thread 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 XSAVE.
They correspond to CET states in user and supervisor mode respectively.

Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 18 ++
 target/i386/cpu.h | 23 ++-
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 38eab02b3d..5496fd68d4 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1071,6 +1071,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,
@@ -1497,6 +1507,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)
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 10bf4d8b51..d4563fa0e8 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -493,6 +493,8 @@ typedef enum X86Seg {
 #define XSTATE_ZMM_Hi256_BIT6
 #define XSTATE_Hi16_ZMM_BIT 7
 #define XSTATE_PKRU_BIT 9
+#define XSTATE_CET_U_BIT11
+#define XSTATE_CET_S_BIT12
 
 #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_MASK0
+#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




[Qemu-devel][PATCH v6 2/6] x86/cpuid: Enable XSS feature enumeration for CPUID

2020-10-12 Thread 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 
---
 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 e2891740f1..38eab02b3d 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1069,6 +1069,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 = {
@@ -1489,6 +1507,9 @@ static uint32_t xsave_area_size(uint64_t mask)
 for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
 const ExtSaveArea *esa = _ext_save_areas[i];
 if ((mask >> i) & 1) {
+if (i >= 2 && !esa->offset) {
+continue;
+}
 ret = MAX(ret, esa->offset + esa->size);
 }
 }
@@ -1500,12 +1521,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) {
@@ -5735,7 +5762,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];
 /*
@@ -5747,11 +5774,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_INSTRUCTION];
+*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 = _ext_save_areas[count];
+const ExtSaveArea *esa = _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;
@@ -6073,6 +6106,9 @@ static void x86_cpu_reset(DeviceState *dev)
 }
 for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
 const ExtSaveArea *esa = _ext_save_areas[i];
+if (!esa->offset) {
+continue;
+}
 if (env->features[esa->feature] & esa->bits) {
 xcr0 |= 1ull << i;
 }
@@ -6307,8 +6343,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 b86eb8dba0..10bf4d8b51 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_M

[Qemu-devel][PATCH v6 4/6] x86/cpu: Add user-space MSR access interface for CET

2020-10-12 Thread Yang Weijiang
CET states are divided into user-mode and supervisor-mode states,
MSR_KVM_GUEST_SSP stores 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 the access according to current CET supported bits in CPUID
and XSS.

Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.h | 18 
 target/i386/kvm.c | 73 +++
 2 files changed, 91 insertions(+)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index d4563fa0e8..9c0568672e 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 0x0490
 #define MSR_IA32_VMX_VMFUNC 0x0491
 
+#define MSR_IA32_U_CET  0x6a0
+#define MSR_IA32_S_CET  0x6a2
+#define MSR_IA32_PL0_SSP0x6a4
+#define MSR_IA32_PL1_SSP0x6a5
+#define MSR_IA32_PL2_SSP0x6a6
+#define MSR_IA32_PL3_SSP0x6a7
+#define MSR_IA32_SSP_TBL0x6a8
+#define MSR_KVM_GUEST_SSP   0x4b564d06
+
 #define XSTATE_FP_BIT   0
 #define XSTATE_SSE_BIT  1
 #define XSTATE_YMM_BIT  2
@@ -1583,6 +1592,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 6f18d940a5..3315d5dd4f 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -3001,6 +3001,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_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);
+}
+
+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_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);
 }
 
@@ -3317,6 +3342,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);
+}
+
+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_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;
@@ -3600,6 +3649,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;

[Qemu-devel][PATCH v6 0/6] Enable CET support for guest

2020-10-12 Thread 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 for guest CET enabling. It enclosed patches for
XSS feature report and CET CPUID enumeration, XSAVE support and MSR
access interface etc.

Related patch series:
CET KVM patches v14:
https://github.com/sean-jc/linux/releases/tag/kvm-cet-v14-rc1

Intel 64 and IA-32 Architectures Software Developer's Manual:
https://software.intel.com/en-us/download/intel-64-and-ia-32-
architectures-sdm-combined-volumes-1-2a-2b-2c-2d-3a-3b-3c-3d-and-4

CET Shadow Stack patches v14:
https://lkml.kernel.org/r/20201012153850.26996-1-yu-cheng...@intel.com/

[3] Indirect Branch Tracking patches v14.
https://lkml.kernel.org/r/20201012154530.28382-1-yu-cheng...@intel.com/

v6:
  - Cleaned up XSAVE related naming for adding XSS features.
  - Refactored patches based on new QEMU code base.
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 (6):
  x86/cpu: Rename XSAVE related feature words.
  x86/cpuid: Enable XSS feature enumeration for CPUID
  x86/cpu: Enable CET components support for XSAVE
  x86/cpu: Add user-space MSR access interface for CET
  x86/cpu: Add CET state support for guest migration
  x86/cpu: Advise CET bits in CPU/MSR feature words

 target/i386/cpu.c| 132 +++-
 target/i386/cpu.h|  57 +-
 target/i386/fpu_helper.c |   2 +-
 target/i386/kvm.c|  73 ++
 target/i386/machine.c| 161 +++
 target/i386/translate.c  |   2 +-
 6 files changed, 384 insertions(+), 43 deletions(-)

-- 
2.26.2




[Qemu-devel][PATCH v5 4/4] x86/cpu: Add user space access interface for CET MSRs

2020-05-09 Thread 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 
---
 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 0x0490
 #define MSR_IA32_VMX_VMFUNC 0x0491
 
+#define MSR_IA32_U_CET  0x6a0
+#define MSR_IA32_S_CET  0x6a2
+#define MSR_IA32_PL0_SSP0x6a4
+#define MSR_IA32_PL1_SSP0x6a5
+#define MSR_IA32_PL2_SSP0x6a6
+#define MSR_IA32_PL3_SSP0x6a7
+#define MSR_IA32_SSP_TBL0x6a8
+#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].dat

[Qemu-devel][PATCH v5 2/4] x86/cpuid: Add XSAVES feature words and CET related state bits

2020-05-09 Thread 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 
Signed-off-by: Yang Weijiang 
---
 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 = _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 = _ext_save_areas[i];
+if (!esa->offset) {
+continue;
+}
 if (env->features[esa->feature] & esa->bits) {
 xcr0 |= 1ull << i;
 }
-- 
2.17.2




[Qemu-devel][PATCH v5 3/4] x86/cpuid: Add support for XSAVES dependent feature enumeration

2020-05-09 Thread 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 
Signed-off-by: Yang Weijiang 
---
 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 = _ext_save_areas[count];
 *eax = esa->size;
 *ebx = esa->offset;
 }
+if ((x86_cpu_xsave_sv_components(cpu) >> count) & 1) {
+const ExtSaveArea *esa_sv = _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




[Qemu-devel][PATCH v5 0/4] Enable CET support for guest

2020-05-09 Thread 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.y...@intel.com

CET kernel patches:
https://lkml.kernel.org/r/20200429220732.31602-1-yu-cheng...@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




[Qemu-devel][PATCH v5 1/4] x86/cpu: Add CET CPUID/XSAVES flags and data structures

2020-05-09 Thread 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 
Signed-off-by: Yang Weijiang 
---
 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_BIT6
 #define XSTATE_Hi16_ZMM_BIT 7
 #define XSTATE_PKRU_BIT 9
+#define XSTATE_RESERVED_BIT 10
+#define XSTATE_CET_U_BIT11
+#define XSTATE_CET_S_BIT12
 
 #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




[Qemu-devel] [RFC PATCH v4 5/5] Add CET MSR save/restore support for migration

2019-03-19 Thread Yang Weijiang
To support features such as live-migration,
CET runtime MSRs need to be saved in source machine and
restored on destination machine, this patch is to save
and restore CET_U, CET_S, PL0_SSP/PL1_SSP/PL2_SSP/PL3_SSP
and SSP_TABL_ADDR MSRs.

Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.h |  16 +
 target/i386/kvm.c |  53 
 target/i386/machine.c | 141 ++
 3 files changed, 210 insertions(+)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 7a181cb95f..e12f33e829 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -460,6 +460,14 @@ typedef enum X86Seg {
 #define MSR_IA32_BNDCFGS0x0d90
 #define MSR_IA32_XSS0x0da0
 
+#define MSR_IA32_U_CET  0x6a0
+#define MSR_IA32_S_CET  0x6a2
+#define MSR_IA32_PL0_SSP0x6a4
+#define MSR_IA32_PL1_SSP0x6a5
+#define MSR_IA32_PL2_SSP0x6a6
+#define MSR_IA32_PL3_SSP0x6a7
+#define MSR_IA32_INTR_SSP_TBL   0x6a8
+
 #define XSTATE_FP_BIT   0
 #define XSTATE_SSE_BIT  1
 #define XSTATE_YMM_BIT  2
@@ -1322,6 +1330,14 @@ 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_tabl_addr;
+
 /* 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 f524e7d929..597cec0aaa 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -63,6 +63,8 @@
 /* A 4096-byte buffer can hold the 8-byte kvm_msrs header, plus
  * 255 kvm_msr_entry structs */
 #define MSR_BUF_SIZE 4096
+#define HAS_CET_CAP(env)  (env->features[FEAT_7_0_ECX] & 0x80 || \
+   env->features[FEAT_7_0_EDX] & 0x10)
 
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
 KVM_CAP_INFO(SET_TSS_ADDR),
@@ -2197,6 +2199,21 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
 }
 }
 
+if (HAS_CET_CAP(env)) {
+/*
+* DO NOT change below register sequence, the first 3 are
+* written to guest fpu xsave area as a whole, the rest 2
+* are written to vmcs guest fields.
+*/
+kvm_msr_entry_add(cpu, MSR_IA32_U_CET, env->u_cet);
+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_PL3_SSP, env->pl3_ssp);
+kvm_msr_entry_add(cpu, MSR_IA32_S_CET, env->s_cet);
+kvm_msr_entry_add(cpu, MSR_IA32_INTR_SSP_TBL, env->ssp_tabl_addr);
+}
+
 ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf);
 if (ret < 0) {
 return ret;
@@ -2516,6 +2533,21 @@ static int kvm_get_msrs(X86CPU *cpu)
 }
 }
 
+if (HAS_CET_CAP(env)) {
+/*
+* DO NOT change below register sequence, the first 3 are
+* read from guest fpu xsave area as a whole, the rest 2
+* are read from vmcs guest fields.
+*/
+kvm_msr_entry_add(cpu, MSR_IA32_U_CET, 0);
+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_PL3_SSP, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_S_CET, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_INTR_SSP_TBL, 0);
+}
+
 ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, cpu->kvm_msr_buf);
 if (ret < 0) {
 return ret;
@@ -2789,6 +2821,27 @@ 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_INTR_SSP_TBL:
+env->ssp_tabl_addr = msrs[i].data;
+break;
 }
 }
 
diff --git a/target/i386/machine.c b/target/i386/machine.c
index 225b5d433b..5f933dedfa 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -810,6 +810,140 @@ static const VMStateDescription vmstate_xss = {
 }
 };
 
+static bool u_cet_n

[Qemu-devel] [RFC PATCH v4 4/5] Report CPUID xsave area support for CET.

2019-03-19 Thread Yang Weijiang
CPUID bit definition as below:
CPUID.(EAX=d, ECX=1):ECX.CET_U(bit 11): user mode state
CPUID.(EAX=d, ECX=1):ECX.CET_S(bit 12): kernel mode state

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 11dbb9bcc4..ac0ceded89 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -4382,13 +4382,22 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, 
uint32_t count,
 *edx = env->features[FEAT_XSAVE_COMP_HI];
 *ebx = xsave_area_size(env->xcr0);
 } else if (count == 1) {
+/* ebx is updated in kvm.*/
 *eax = env->features[FEAT_XSAVE];
+*ecx = env->features[FEAT_XSAVE_SV_LO];
+*edx = env->features[FEAT_XSAVE_SV_HI];
 } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {
 if ((x86_cpu_xsave_components(cpu) >> count) & 1) {
 const ExtSaveArea *esa = _ext_save_areas[count];
 *eax = esa->size;
 *ebx = esa->offset;
 }
+if ((x86_cpu_xsave_sv_components(cpu) >> count) & 1) {
+const ExtSaveArea *esa_sv = _ext_save_areas[count];
+*eax = esa_sv->size;
+*ebx = 0;
+*ecx = 1;
+}
 }
 break;
 }
-- 
2.17.1




[Qemu-devel] [RFC PATCH v4 1/5] Add CET xsaves/xrstors related macros and structures.

2019-03-19 Thread Yang Weijiang
CET protection in user mode and kernel mode relies on
specific MSRs, these MSRs' contents are automatically
saved/restored by xsaves/xrstors instructions.

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.h | 33 -
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 9c52d0cbeb..7a181cb95f 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -469,6 +469,9 @@ typedef enum X86Seg {
 #define XSTATE_ZMM_Hi256_BIT6
 #define XSTATE_Hi16_ZMM_BIT 7
 #define XSTATE_PKRU_BIT 9
+#define XSTATE_RESERVED_BIT 10
+#define XSTATE_CET_U_BIT11
+#define XSTATE_CET_S_BIT12
 
 #define XSTATE_FP_MASK  (1ULL << XSTATE_FP_BIT)
 #define XSTATE_SSE_MASK (1ULL << XSTATE_SSE_BIT)
@@ -479,6 +482,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 | XSTATE_CET_S_MASK)
 
 /* CPUID feature words */
 typedef enum FeatureWord {
@@ -503,6 +519,8 @@ typedef enum FeatureWord {
 FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */
 FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */
 FEAT_ARCH_CAPABILITIES,
+FEAT_XSAVE_SV_LO,   /* CPUID[EAX=0xd,ECX=1].ECX */
+FEAT_XSAVE_SV_HI,   /* CPUID[EAX=0xd,ECX=1].EDX */
 FEATURE_WORDS,
 } FeatureWord;
 
@@ -687,7 +705,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_7_0_ECX_LA57 (1U << 16)
 #define CPUID_7_0_ECX_RDPID(1U << 22)
 #define CPUID_7_0_ECX_CLDEMOTE (1U << 25)  /* CLDEMOTE Instruction */
-
+#define CPUID_7_0_ECX_CET_SHSTK (1U << 7)  /* CET SHSTK feature bit */
 #define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network 
Instructions */
 #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation 
Single Precision */
 #define CPUID_7_0_EDX_PCONFIG (1U << 18)   /* Platform Configuration */
@@ -1021,6 +1039,19 @@ typedef struct XSavePKRU {
 uint32_t padding;
 } XSavePKRU;
 
+/* Ext. save area 11: User mode CET state */
+typedef struct XSaveCETU {
+uint64_t u_cet;
+uint64_t user_ssp;
+} XSaveCETU;
+
+/* Ext. save area 12: Supervisor mode CET state */
+typedef struct XSaveCETS {
+uint64_t kernel_ssp;
+uint64_t pl1_ssp;
+uint64_t pl2_ssp;
+} XSaveCETS;
+
 typedef struct X86XSaveArea {
 X86LegacyXSaveArea legacy;
 X86XSaveHeader header;
-- 
2.17.1




[Qemu-devel] [RFC PATCH v4 3/5] Add hepler functions for CPUID xsave area size calculation.

2019-03-19 Thread Yang Weijiang
These functions are called when return CPUID xsave area
size information.

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index f6c7bdf6fe..11dbb9bcc4 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1290,6 +1290,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_XSAVE_SV_HI]) << 32 |
+   cpu->env.features[FEAT_XSAVE_SV_LO];
+}
+
 const char *get_register_name_32(unsigned int reg)
 {
 if (reg >= CPU_NB_REGS32) {
@@ -4919,8 +4925,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_XSAVE_SV_LO] = mask & CPUID_XSTATE_KERNEL_MASK;
+env->features[FEAT_XSAVE_SV_HI] = mask >> 32;
 }
 
 /* Steps involved on loading and filtering CPUID data
-- 
2.17.1




[Qemu-devel] [RFC PATCH v4 2/5] Add CET SHSTK and IBT CPUID feature-word definitions.

2019-03-19 Thread Yang Weijiang
XSS[bit 11] and XSS[bit 12] correspond to CET
user mode area and supervisor mode area respectively.

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 37 +++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index f81d35e1f9..f6c7bdf6fe 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1018,7 +1018,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = 
{
 .type = CPUID_FEATURE_WORD,
 .feat_names = {
 NULL, "avx512vbmi", "umip", "pku",
-NULL /* ospke */, NULL, "avx512vbmi2", NULL,
+NULL /* ospke */, NULL, "avx512vbmi2", "shstk",
 "gfni", "vaes", "vpclmulqdq", "avx512vnni",
 "avx512bitalg", NULL, "avx512-vpopcntdq", NULL,
 "la57", NULL, NULL, NULL,
@@ -1041,7 +1041,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = 
{
 NULL, NULL, NULL, NULL,
 NULL, NULL, NULL, NULL,
 NULL, NULL, "pconfig", NULL,
-NULL, NULL, NULL, NULL,
+"ibt", NULL, NULL, NULL,
 NULL, NULL, "spec-ctrl", NULL,
 NULL, "arch-capabilities", NULL, "ssbd",
 },
@@ -1162,6 +1162,25 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] 
= {
 }
 },
 },
+/* Below are CET supervisor xsave features */
+[FEAT_XSAVE_SV_LO] = {
+.type = CPUID_FEATURE_WORD,
+.cpuid = {
+.eax = 0xD,
+.needs_ecx = true,
+.ecx = 1,
+.reg = R_ECX,
+},
+},
+[FEAT_XSAVE_SV_HI] = {
+.type = CPUID_FEATURE_WORD,
+.cpuid = {
+.eax = 0xD,
+.needs_ecx = true,
+.ecx = 1,
+.reg = R_EDX
+},
+}
 };
 
 typedef struct X86RegisterInfo32 {
@@ -1233,6 +1252,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(XSaveCETU) },
+[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(XSaveCETS) },
 };
 
 static uint32_t xsave_area_size(uint64_t mask)
@@ -1243,6 +1270,9 @@ static uint32_t xsave_area_size(uint64_t mask)
 for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
 const ExtSaveArea *esa = _ext_save_areas[i];
 if ((mask >> i) & 1) {
+if (i >= 2 && !esa->offset) {
+continue;
+}
 ret = MAX(ret, esa->offset + esa->size);
 }
 }
@@ -4657,6 +4687,9 @@ static void x86_cpu_reset(CPUState *s)
 }
 for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
 const ExtSaveArea *esa = _ext_save_areas[i];
+if (!esa->offset) {
+continue;
+}
 if (env->features[esa->feature] & esa->bits) {
 xcr0 |= 1ull << i;
 }
-- 
2.17.1




[Qemu-devel] [RFC PATCH v4 0/5] This patch-set is to enable Guest

2019-03-19 Thread Yang Weijiang
Control-flow Enforcement Technology (CET) provides protection against
return/jump-oriented programming (ROP) attacks. To make kvm Guest OS own
the capability, this patch-set is required. It enables CET related CPUID
report, xsaves/xrstors and live-migration etc. in Qemu.

Changelog:
 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 (5):
  Add CET xsaves/xrstors related macros and structures.
  Add CET SHSTK and IBT CPUID feature-word definitions.
  Add hepler functions for CPUID xsave area size calculation.
  Report CPUID xsave area support for CET.
  Add CET MSR save/restore support for migration

 target/i386/cpu.c |  56 -
 target/i386/cpu.h |  49 ++-
 target/i386/kvm.c |  53 
 target/i386/machine.c | 141 ++
 4 files changed, 295 insertions(+), 4 deletions(-)

-- 
2.17.1




[Qemu-devel] [PATCH v3 3/5] Add hepler functions for CPUID xsave area size calculation.

2019-02-25 Thread Yang Weijiang
These functions are called when return CPUID xsave area
size information.

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 26 +-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index f6c7bdf6fe..d8c36e0f2f 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1284,12 +1284,34 @@ static inline bool accel_uses_host_cpuid(void)
 return kvm_enabled() || hvf_enabled();
 }
 
+static uint32_t xsave_area_size_compacted(uint64_t mask)
+{
+int i;
+uint64_t ret = 0;
+uint32_t offset;
+
+for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
+const ExtSaveArea *esa = _ext_save_areas[i];
+offset = i >= 2 ? ret : esa->offset;
+if ((mask >> i) & 1) {
+ret = MAX(ret, offset + esa->size);
+}
+}
+return ret;
+}
+
 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];
 }
 
+static inline uint64_t x86_cpu_xsave_sv_components(X86CPU *cpu)
+{
+return ((uint64_t)cpu->env.features[FEAT_XSAVE_SV_HI]) << 32 |
+   cpu->env.features[FEAT_XSAVE_SV_LO];
+}
+
 const char *get_register_name_32(unsigned int reg)
 {
 if (reg >= CPU_NB_REGS32) {
@@ -4919,8 +4941,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_XSAVE_SV_LO] = mask & CPUID_XSTATE_KERNEL_MASK;
+env->features[FEAT_XSAVE_SV_HI] = mask >> 32;
 }
 
 /* Steps involved on loading and filtering CPUID data
-- 
2.17.1




[Qemu-devel] [PATCH v3 5/5] Add CET MSR save/restore support for migration

2019-02-25 Thread Yang Weijiang
To support features such as live-migration,
CET runtime MSRs need to be saved in source machine and
restored on destination machine, this patch is to save
and restore CET_U, CET_S, PL0_SSP, PL3_SSP and SSP_TABL_ADDR
MSRs.

Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.h |  12 +
 target/i386/kvm.c |  33 ++
 target/i386/machine.c | 100 ++
 3 files changed, 145 insertions(+)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index f3f724d8e6..f350684895 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -460,6 +460,12 @@ typedef enum X86Seg {
 #define MSR_IA32_BNDCFGS0x0d90
 #define MSR_IA32_XSS0x0da0
 
+#define MSR_IA32_U_CET  0x6a0
+#define MSR_IA32_S_CET  0x6a2
+#define MSR_IA32_PL0_SSP0x6a4
+#define MSR_IA32_PL3_SSP0x6a7
+#define MSR_IA32_INTR_SSP_TABL  0x6a8
+
 #define XSTATE_FP_BIT   0
 #define XSTATE_SSE_BIT  1
 #define XSTATE_YMM_BIT  2
@@ -1325,6 +1331,12 @@ typedef struct CPUX86State {
 
 uintptr_t retaddr;
 
+uint64_t u_cet;
+uint64_t s_cet;
+uint64_t pl0_ssp;
+uint64_t pl3_ssp;
+uint64_t ssp_tabl_addr;
+
 /* 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 f524e7d929..2ab3c977a4 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -63,6 +63,8 @@
 /* A 4096-byte buffer can hold the 8-byte kvm_msrs header, plus
  * 255 kvm_msr_entry structs */
 #define MSR_BUF_SIZE 4096
+#define HAS_CET_CAP(env)  (env->features[FEAT_7_0_ECX] & 0x80 || \
+   env->features[FEAT_7_0_EDX] & 0x10)
 
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
 KVM_CAP_INFO(SET_TSS_ADDR),
@@ -2197,6 +2199,14 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
 }
 }
 
+if (HAS_CET_CAP(env)) {
+kvm_msr_entry_add(cpu, MSR_IA32_U_CET, env->u_cet);
+kvm_msr_entry_add(cpu, MSR_IA32_S_CET, env->s_cet);
+kvm_msr_entry_add(cpu, MSR_IA32_PL0_SSP, env->pl0_ssp);
+kvm_msr_entry_add(cpu, MSR_IA32_PL3_SSP, env->pl3_ssp);
+kvm_msr_entry_add(cpu, MSR_IA32_INTR_SSP_TABL, env->ssp_tabl_addr);
+}
+
 ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf);
 if (ret < 0) {
 return ret;
@@ -2516,6 +2526,14 @@ static int kvm_get_msrs(X86CPU *cpu)
 }
 }
 
+if (HAS_CET_CAP(env)) {
+kvm_msr_entry_add(cpu, MSR_IA32_U_CET, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_S_CET, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_PL0_SSP, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_PL3_SSP, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_INTR_SSP_TABL, 0);
+}
+
 ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, cpu->kvm_msr_buf);
 if (ret < 0) {
 return ret;
@@ -2789,6 +2807,21 @@ 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_PL3_SSP:
+env->pl3_ssp = msrs[i].data;
+break;
+case MSR_IA32_INTR_SSP_TABL:
+env->ssp_tabl_addr = msrs[i].data;
+break;
 }
 }
 
diff --git a/target/i386/machine.c b/target/i386/machine.c
index 225b5d433b..5f8a12ca30 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -810,6 +810,101 @@ static const VMStateDescription vmstate_xss = {
 }
 };
 
+static bool u_cet_needed(void *opaque)
+{
+X86CPU *cpu = opaque;
+CPUX86State *env = >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 = >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 = >env;
+
+return env->pl0_ssp != 0;
+}
+
+sta

[Qemu-devel] RESEND: [PATCH v3 0/5] This patch-set is to enable Guest

2019-02-25 Thread Yang Weijiang
Control-flow Enforcement Technology (CET) provides protection against
return/jump-oriented programming (ROP) attacks. To make kvm Guest OS own
the capability, this patch-set is required. It enables CET related CPUID
report, xsaves/xrstors and live-migration etc. in Qemu.

Changelog:

 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 (5):
  Add CET xsaves/xrstors related macros and structures.
  Add CET SHSTK and IBT CPUID feature-word definitions.
  Add hepler functions for CPUID xsave area size calculation.
  Report CPUID xsave area support for CET.
  Add CET MSR save/restore support for migration

 target/i386/cpu.c |  73 --
 target/i386/cpu.h |  48 +++-
 target/i386/kvm.c |  27 
 target/i386/machine.c | 100 ++
 4 files changed, 244 insertions(+), 4 deletions(-)

-- 
2.17.1




[Qemu-devel] [PATCH v3 2/5] Add CET SHSTK and IBT CPUID feature-word definitions.

2019-02-25 Thread Yang Weijiang
XSS[bit 11] and XSS[bit 12] correspond to CET
user mode area and supervisor mode area respectively.

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 37 +++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index f81d35e1f9..f6c7bdf6fe 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1018,7 +1018,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = 
{
 .type = CPUID_FEATURE_WORD,
 .feat_names = {
 NULL, "avx512vbmi", "umip", "pku",
-NULL /* ospke */, NULL, "avx512vbmi2", NULL,
+NULL /* ospke */, NULL, "avx512vbmi2", "shstk",
 "gfni", "vaes", "vpclmulqdq", "avx512vnni",
 "avx512bitalg", NULL, "avx512-vpopcntdq", NULL,
 "la57", NULL, NULL, NULL,
@@ -1041,7 +1041,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = 
{
 NULL, NULL, NULL, NULL,
 NULL, NULL, NULL, NULL,
 NULL, NULL, "pconfig", NULL,
-NULL, NULL, NULL, NULL,
+"ibt", NULL, NULL, NULL,
 NULL, NULL, "spec-ctrl", NULL,
 NULL, "arch-capabilities", NULL, "ssbd",
 },
@@ -1162,6 +1162,25 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] 
= {
 }
 },
 },
+/* Below are CET supervisor xsave features */
+[FEAT_XSAVE_SV_LO] = {
+.type = CPUID_FEATURE_WORD,
+.cpuid = {
+.eax = 0xD,
+.needs_ecx = true,
+.ecx = 1,
+.reg = R_ECX,
+},
+},
+[FEAT_XSAVE_SV_HI] = {
+.type = CPUID_FEATURE_WORD,
+.cpuid = {
+.eax = 0xD,
+.needs_ecx = true,
+.ecx = 1,
+.reg = R_EDX
+},
+}
 };
 
 typedef struct X86RegisterInfo32 {
@@ -1233,6 +1252,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(XSaveCETU) },
+[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(XSaveCETS) },
 };
 
 static uint32_t xsave_area_size(uint64_t mask)
@@ -1243,6 +1270,9 @@ static uint32_t xsave_area_size(uint64_t mask)
 for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
 const ExtSaveArea *esa = _ext_save_areas[i];
 if ((mask >> i) & 1) {
+if (i >= 2 && !esa->offset) {
+continue;
+}
 ret = MAX(ret, esa->offset + esa->size);
 }
 }
@@ -4657,6 +4687,9 @@ static void x86_cpu_reset(CPUState *s)
 }
 for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
 const ExtSaveArea *esa = _ext_save_areas[i];
+if (!esa->offset) {
+continue;
+}
 if (env->features[esa->feature] & esa->bits) {
 xcr0 |= 1ull << i;
 }
-- 
2.17.1




[Qemu-devel] [PATCH v3 4/5] Report CPUID xsave area support for CET.

2019-02-25 Thread Yang Weijiang
CPUID bit definition as below:
CPUID.(EAX=d, ECX=1):ECX.CET_U(bit 11): user mode state
CPUID.(EAX=d, ECX=1):ECX.CET_S(bit 12): kernel mode state

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index d8c36e0f2f..15e2d5e009 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -4399,12 +4399,22 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, 
uint32_t count,
 *ebx = xsave_area_size(env->xcr0);
 } else if (count == 1) {
 *eax = env->features[FEAT_XSAVE];
+*ecx = env->features[FEAT_XSAVE_SV_LO];
+*edx = env->features[FEAT_XSAVE_SV_HI];
+*ebx = xsave_area_size_compacted(x86_cpu_xsave_components(cpu) |
+x86_cpu_xsave_sv_components(cpu));
 } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {
 if ((x86_cpu_xsave_components(cpu) >> count) & 1) {
 const ExtSaveArea *esa = _ext_save_areas[count];
 *eax = esa->size;
 *ebx = esa->offset;
 }
+if ((x86_cpu_xsave_sv_components(cpu) >> count) & 1) {
+const ExtSaveArea *esa_sv = _ext_save_areas[count];
+*eax = esa_sv->size;
+*ebx = 0;
+*ecx = 1;
+}
 }
 break;
 }
-- 
2.17.1




[Qemu-devel] [PATCH v3 1/5] Add CET xsaves/xrstors related macros and structures.

2019-02-25 Thread Yang Weijiang
CET protection in user mode and kernel mode relies on
specific MSRs, these MSRs' contents are automatically
saved/restored by xsaves/xrstors instructions.

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.h | 36 +++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 9c52d0cbeb..f3f724d8e6 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -469,6 +469,9 @@ typedef enum X86Seg {
 #define XSTATE_ZMM_Hi256_BIT6
 #define XSTATE_Hi16_ZMM_BIT 7
 #define XSTATE_PKRU_BIT 9
+#define XSTATE_RESERVED_BIT 10
+#define XSTATE_CET_U_BIT11
+#define XSTATE_CET_S_BIT12
 
 #define XSTATE_FP_MASK  (1ULL << XSTATE_FP_BIT)
 #define XSTATE_SSE_MASK (1ULL << XSTATE_SSE_BIT)
@@ -479,6 +482,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 | XSTATE_CET_S_MASK)
 
 /* CPUID feature words */
 typedef enum FeatureWord {
@@ -503,6 +519,8 @@ typedef enum FeatureWord {
 FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */
 FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */
 FEAT_ARCH_CAPABILITIES,
+FEAT_XSAVE_SV_LO,   /* CPUID[EAX=0xd,ECX=1].ECX */
+FEAT_XSAVE_SV_HI,   /* CPUID[EAX=0xd,ECX=1].EDX */
 FEATURE_WORDS,
 } FeatureWord;
 
@@ -687,7 +705,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_7_0_ECX_LA57 (1U << 16)
 #define CPUID_7_0_ECX_RDPID(1U << 22)
 #define CPUID_7_0_ECX_CLDEMOTE (1U << 25)  /* CLDEMOTE Instruction */
-
+#define CPUID_7_0_ECX_CET_SHSTK (1U << 7)  /* CET SHSTK feature bit */
 #define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network 
Instructions */
 #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation 
Single Precision */
 #define CPUID_7_0_EDX_PCONFIG (1U << 18)   /* Platform Configuration */
@@ -1021,6 +1039,19 @@ typedef struct XSavePKRU {
 uint32_t padding;
 } XSavePKRU;
 
+/* Ext. save area 11: User mode CET state */
+typedef struct XSaveCETU {
+uint64_t u_cet;
+uint64_t user_ssp;
+} XSaveCETU;
+
+/* Ext. save area 12: Supervisor mode CET state */
+typedef struct XSaveCETS {
+uint64_t kernel_ssp;
+uint64_t pl1_ssp;
+uint64_t pl2_ssp;
+} XSaveCETS;
+
 typedef struct X86XSaveArea {
 X86LegacyXSaveArea legacy;
 X86XSaveHeader header;
@@ -1039,6 +1070,9 @@ typedef struct X86XSaveArea {
 XSaveHi16_ZMM hi16_zmm_state;
 /* PKRU State: */
 XSavePKRU pkru_state;
+/* CET State: */
+XSaveCETU cet_u;
+XSaveCETS cet_s;
 } X86XSaveArea;
 
 QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, avx_state) != 0x240);
-- 
2.17.1




[Qemu-devel] [PATCH v3 4/5] Report CPUID xsave area support for CET.

2019-02-25 Thread Yang Weijiang
CPUID bit definition as below:
CPUID.(EAX=d, ECX=1):ECX.CET_U(bit 11): user mode state
CPUID.(EAX=d, ECX=1):ECX.CET_S(bit 12): kernel mode state

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index d8c36e0f2f..15e2d5e009 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -4399,12 +4399,22 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, 
uint32_t count,
 *ebx = xsave_area_size(env->xcr0);
 } else if (count == 1) {
 *eax = env->features[FEAT_XSAVE];
+*ecx = env->features[FEAT_XSAVE_SV_LO];
+*edx = env->features[FEAT_XSAVE_SV_HI];
+*ebx = xsave_area_size_compacted(x86_cpu_xsave_components(cpu) |
+x86_cpu_xsave_sv_components(cpu));
 } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {
 if ((x86_cpu_xsave_components(cpu) >> count) & 1) {
 const ExtSaveArea *esa = _ext_save_areas[count];
 *eax = esa->size;
 *ebx = esa->offset;
 }
+if ((x86_cpu_xsave_sv_components(cpu) >> count) & 1) {
+const ExtSaveArea *esa_sv = _ext_save_areas[count];
+*eax = esa_sv->size;
+*ebx = 0;
+*ecx = 1;
+}
 }
 break;
 }
-- 
2.17.1




[Qemu-devel] [PATCH v3 2/5] Add CET SHSTK and IBT CPUID feature-word definitions.

2019-02-25 Thread Yang Weijiang
XSS[bit 11] and XSS[bit 12] correspond to CET
user mode area and supervisor mode area respectively.

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 37 +++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index f81d35e1f9..f6c7bdf6fe 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1018,7 +1018,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = 
{
 .type = CPUID_FEATURE_WORD,
 .feat_names = {
 NULL, "avx512vbmi", "umip", "pku",
-NULL /* ospke */, NULL, "avx512vbmi2", NULL,
+NULL /* ospke */, NULL, "avx512vbmi2", "shstk",
 "gfni", "vaes", "vpclmulqdq", "avx512vnni",
 "avx512bitalg", NULL, "avx512-vpopcntdq", NULL,
 "la57", NULL, NULL, NULL,
@@ -1041,7 +1041,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = 
{
 NULL, NULL, NULL, NULL,
 NULL, NULL, NULL, NULL,
 NULL, NULL, "pconfig", NULL,
-NULL, NULL, NULL, NULL,
+"ibt", NULL, NULL, NULL,
 NULL, NULL, "spec-ctrl", NULL,
 NULL, "arch-capabilities", NULL, "ssbd",
 },
@@ -1162,6 +1162,25 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] 
= {
 }
 },
 },
+/* Below are CET supervisor xsave features */
+[FEAT_XSAVE_SV_LO] = {
+.type = CPUID_FEATURE_WORD,
+.cpuid = {
+.eax = 0xD,
+.needs_ecx = true,
+.ecx = 1,
+.reg = R_ECX,
+},
+},
+[FEAT_XSAVE_SV_HI] = {
+.type = CPUID_FEATURE_WORD,
+.cpuid = {
+.eax = 0xD,
+.needs_ecx = true,
+.ecx = 1,
+.reg = R_EDX
+},
+}
 };
 
 typedef struct X86RegisterInfo32 {
@@ -1233,6 +1252,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(XSaveCETU) },
+[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(XSaveCETS) },
 };
 
 static uint32_t xsave_area_size(uint64_t mask)
@@ -1243,6 +1270,9 @@ static uint32_t xsave_area_size(uint64_t mask)
 for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
 const ExtSaveArea *esa = _ext_save_areas[i];
 if ((mask >> i) & 1) {
+if (i >= 2 && !esa->offset) {
+continue;
+}
 ret = MAX(ret, esa->offset + esa->size);
 }
 }
@@ -4657,6 +4687,9 @@ static void x86_cpu_reset(CPUState *s)
 }
 for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
 const ExtSaveArea *esa = _ext_save_areas[i];
+if (!esa->offset) {
+continue;
+}
 if (env->features[esa->feature] & esa->bits) {
 xcr0 |= 1ull << i;
 }
-- 
2.17.1




[Qemu-devel] [PATCH v3 3/5] Add hepler functions for CPUID xsave area size calculation.

2019-02-25 Thread Yang Weijiang
These functions are called when return CPUID xsave area
size information.

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 26 +-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index f6c7bdf6fe..d8c36e0f2f 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1284,12 +1284,34 @@ static inline bool accel_uses_host_cpuid(void)
 return kvm_enabled() || hvf_enabled();
 }
 
+static uint32_t xsave_area_size_compacted(uint64_t mask)
+{
+int i;
+uint64_t ret = 0;
+uint32_t offset;
+
+for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
+const ExtSaveArea *esa = _ext_save_areas[i];
+offset = i >= 2 ? ret : esa->offset;
+if ((mask >> i) & 1) {
+ret = MAX(ret, offset + esa->size);
+}
+}
+return ret;
+}
+
 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];
 }
 
+static inline uint64_t x86_cpu_xsave_sv_components(X86CPU *cpu)
+{
+return ((uint64_t)cpu->env.features[FEAT_XSAVE_SV_HI]) << 32 |
+   cpu->env.features[FEAT_XSAVE_SV_LO];
+}
+
 const char *get_register_name_32(unsigned int reg)
 {
 if (reg >= CPU_NB_REGS32) {
@@ -4919,8 +4941,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_XSAVE_SV_LO] = mask & CPUID_XSTATE_KERNEL_MASK;
+env->features[FEAT_XSAVE_SV_HI] = mask >> 32;
 }
 
 /* Steps involved on loading and filtering CPUID data
-- 
2.17.1




[Qemu-devel] [PATCH v3 5/5] Add CET MSR save/restore support for migration

2019-02-25 Thread Yang Weijiang
To support features such as live-migration,
CET runtime MSRs need to be saved in source machine and
restored on destination machine, this patch is to save
and restore CET_U, CET_S, PL0_SSP, PL3_SSP and SSP_TABL_ADDR
MSRs.

Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.h |  12 +
 target/i386/kvm.c |  33 ++
 target/i386/machine.c | 100 ++
 3 files changed, 145 insertions(+)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index f3f724d8e6..f350684895 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -460,6 +460,12 @@ typedef enum X86Seg {
 #define MSR_IA32_BNDCFGS0x0d90
 #define MSR_IA32_XSS0x0da0
 
+#define MSR_IA32_U_CET  0x6a0
+#define MSR_IA32_S_CET  0x6a2
+#define MSR_IA32_PL0_SSP0x6a4
+#define MSR_IA32_PL3_SSP0x6a7
+#define MSR_IA32_INTR_SSP_TABL  0x6a8
+
 #define XSTATE_FP_BIT   0
 #define XSTATE_SSE_BIT  1
 #define XSTATE_YMM_BIT  2
@@ -1325,6 +1331,12 @@ typedef struct CPUX86State {
 
 uintptr_t retaddr;
 
+uint64_t u_cet;
+uint64_t s_cet;
+uint64_t pl0_ssp;
+uint64_t pl3_ssp;
+uint64_t ssp_tabl_addr;
+
 /* 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 f524e7d929..2ab3c977a4 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -63,6 +63,8 @@
 /* A 4096-byte buffer can hold the 8-byte kvm_msrs header, plus
  * 255 kvm_msr_entry structs */
 #define MSR_BUF_SIZE 4096
+#define HAS_CET_CAP(env)  (env->features[FEAT_7_0_ECX] & 0x80 || \
+   env->features[FEAT_7_0_EDX] & 0x10)
 
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
 KVM_CAP_INFO(SET_TSS_ADDR),
@@ -2197,6 +2199,14 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
 }
 }
 
+if (HAS_CET_CAP(env)) {
+kvm_msr_entry_add(cpu, MSR_IA32_U_CET, env->u_cet);
+kvm_msr_entry_add(cpu, MSR_IA32_S_CET, env->s_cet);
+kvm_msr_entry_add(cpu, MSR_IA32_PL0_SSP, env->pl0_ssp);
+kvm_msr_entry_add(cpu, MSR_IA32_PL3_SSP, env->pl3_ssp);
+kvm_msr_entry_add(cpu, MSR_IA32_INTR_SSP_TABL, env->ssp_tabl_addr);
+}
+
 ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf);
 if (ret < 0) {
 return ret;
@@ -2516,6 +2526,14 @@ static int kvm_get_msrs(X86CPU *cpu)
 }
 }
 
+if (HAS_CET_CAP(env)) {
+kvm_msr_entry_add(cpu, MSR_IA32_U_CET, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_S_CET, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_PL0_SSP, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_PL3_SSP, 0);
+kvm_msr_entry_add(cpu, MSR_IA32_INTR_SSP_TABL, 0);
+}
+
 ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, cpu->kvm_msr_buf);
 if (ret < 0) {
 return ret;
@@ -2789,6 +2807,21 @@ 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_PL3_SSP:
+env->pl3_ssp = msrs[i].data;
+break;
+case MSR_IA32_INTR_SSP_TABL:
+env->ssp_tabl_addr = msrs[i].data;
+break;
 }
 }
 
diff --git a/target/i386/machine.c b/target/i386/machine.c
index 225b5d433b..5f8a12ca30 100644
--- a/target/i386/machine.c
+++ b/target/i386/machine.c
@@ -810,6 +810,101 @@ static const VMStateDescription vmstate_xss = {
 }
 };
 
+static bool u_cet_needed(void *opaque)
+{
+X86CPU *cpu = opaque;
+CPUX86State *env = >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 = >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 = >env;
+
+return env->pl0_ssp != 0;
+}
+
+sta

[Qemu-devel] [PATCH v3 1/5] Add CET xsaves/xrstors related macros and structures.

2019-02-25 Thread Yang Weijiang
CET protection in user mode and kernel mode relies on
specific MSRs, these MSRs' contents are automatically
saved/restored by xsaves/xrstors instructions.

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.h | 36 +++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 9c52d0cbeb..f3f724d8e6 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -469,6 +469,9 @@ typedef enum X86Seg {
 #define XSTATE_ZMM_Hi256_BIT6
 #define XSTATE_Hi16_ZMM_BIT 7
 #define XSTATE_PKRU_BIT 9
+#define XSTATE_RESERVED_BIT 10
+#define XSTATE_CET_U_BIT11
+#define XSTATE_CET_S_BIT12
 
 #define XSTATE_FP_MASK  (1ULL << XSTATE_FP_BIT)
 #define XSTATE_SSE_MASK (1ULL << XSTATE_SSE_BIT)
@@ -479,6 +482,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 | XSTATE_CET_S_MASK)
 
 /* CPUID feature words */
 typedef enum FeatureWord {
@@ -503,6 +519,8 @@ typedef enum FeatureWord {
 FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */
 FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */
 FEAT_ARCH_CAPABILITIES,
+FEAT_XSAVE_SV_LO,   /* CPUID[EAX=0xd,ECX=1].ECX */
+FEAT_XSAVE_SV_HI,   /* CPUID[EAX=0xd,ECX=1].EDX */
 FEATURE_WORDS,
 } FeatureWord;
 
@@ -687,7 +705,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_7_0_ECX_LA57 (1U << 16)
 #define CPUID_7_0_ECX_RDPID(1U << 22)
 #define CPUID_7_0_ECX_CLDEMOTE (1U << 25)  /* CLDEMOTE Instruction */
-
+#define CPUID_7_0_ECX_CET_SHSTK (1U << 7)  /* CET SHSTK feature bit */
 #define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network 
Instructions */
 #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation 
Single Precision */
 #define CPUID_7_0_EDX_PCONFIG (1U << 18)   /* Platform Configuration */
@@ -1021,6 +1039,19 @@ typedef struct XSavePKRU {
 uint32_t padding;
 } XSavePKRU;
 
+/* Ext. save area 11: User mode CET state */
+typedef struct XSaveCETU {
+uint64_t u_cet;
+uint64_t user_ssp;
+} XSaveCETU;
+
+/* Ext. save area 12: Supervisor mode CET state */
+typedef struct XSaveCETS {
+uint64_t kernel_ssp;
+uint64_t pl1_ssp;
+uint64_t pl2_ssp;
+} XSaveCETS;
+
 typedef struct X86XSaveArea {
 X86LegacyXSaveArea legacy;
 X86XSaveHeader header;
@@ -1039,6 +1070,9 @@ typedef struct X86XSaveArea {
 XSaveHi16_ZMM hi16_zmm_state;
 /* PKRU State: */
 XSavePKRU pkru_state;
+/* CET State: */
+XSaveCETU cet_u;
+XSaveCETS cet_s;
 } X86XSaveArea;
 
 QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, avx_state) != 0x240);
-- 
2.17.1




[Qemu-devel] (no subject)

2019-02-25 Thread Yang Weijiang
Subject: [Qemu-devel][PATCH v3 0/5] This patch-set is to enable Guest
CET support.

Control-flow Enforcement Technology (CET) provides protection against
return/jump-oriented programming (ROP) attacks. To make kvm Guest OS own
the capability, this patch-set is required. It enables CET related CPUID
report, xsaves/xrstors and live-migration etc. in Qemu.

Changelog:

 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 (5):
  Add CET xsaves/xrstors related macros and structures.
  Add CET SHSTK and IBT CPUID feature-word definitions.
  Add hepler functions for CPUID xsave area size calculation.
  Report CPUID xsave area support for CET.
  Add CET MSR save/restore support for migration

 target/i386/cpu.c |  73 --
 target/i386/cpu.h |  48 +++-
 target/i386/kvm.c |  27 
 target/i386/machine.c | 100 ++
 4 files changed, 244 insertions(+), 4 deletions(-)

-- 
2.17.1




[Qemu-devel] [PATCH v2 3/4] Add hepler functions for CPUID xsave area size calculation.

2019-01-23 Thread Yang Weijiang
These functions are called when return CPUID xsave area
size information.

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 26 +-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index f6c7bdf6fe..d8c36e0f2f 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1284,12 +1284,34 @@ static inline bool accel_uses_host_cpuid(void)
 return kvm_enabled() || hvf_enabled();
 }
 
+static uint32_t xsave_area_size_compacted(uint64_t mask)
+{
+int i;
+uint64_t ret = 0;
+uint32_t offset;
+
+for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
+const ExtSaveArea *esa = _ext_save_areas[i];
+offset = i >= 2 ? ret : esa->offset;
+if ((mask >> i) & 1) {
+ret = MAX(ret, offset + esa->size);
+}
+}
+return ret;
+}
+
 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];
 }
 
+static inline uint64_t x86_cpu_xsave_sv_components(X86CPU *cpu)
+{
+return ((uint64_t)cpu->env.features[FEAT_XSAVE_SV_HI]) << 32 |
+   cpu->env.features[FEAT_XSAVE_SV_LO];
+}
+
 const char *get_register_name_32(unsigned int reg)
 {
 if (reg >= CPU_NB_REGS32) {
@@ -4919,8 +4941,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_XSAVE_SV_LO] = mask & CPUID_XSTATE_KERNEL_MASK;
+env->features[FEAT_XSAVE_SV_HI] = mask >> 32;
 }
 
 /* Steps involved on loading and filtering CPUID data
-- 
2.17.1




[Qemu-devel] [PATCH v2 1/4] Add CET xsaves/xrstors related macros and structures.

2019-01-23 Thread Yang Weijiang
CET protection in user mode and kernel mode relies on
specific MSRs, these MSRs' contents are automatically
saved/restored by xsaves/xrstors instructions.

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.h | 36 +++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 9c52d0cbeb..f3f724d8e6 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -469,6 +469,9 @@ typedef enum X86Seg {
 #define XSTATE_ZMM_Hi256_BIT6
 #define XSTATE_Hi16_ZMM_BIT 7
 #define XSTATE_PKRU_BIT 9
+#define XSTATE_RESERVED_BIT 10
+#define XSTATE_CET_U_BIT11
+#define XSTATE_CET_S_BIT12
 
 #define XSTATE_FP_MASK  (1ULL << XSTATE_FP_BIT)
 #define XSTATE_SSE_MASK (1ULL << XSTATE_SSE_BIT)
@@ -479,6 +482,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 | XSTATE_CET_S_MASK)
 
 /* CPUID feature words */
 typedef enum FeatureWord {
@@ -503,6 +519,8 @@ typedef enum FeatureWord {
 FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */
 FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */
 FEAT_ARCH_CAPABILITIES,
+FEAT_XSAVE_SV_LO,   /* CPUID[EAX=0xd,ECX=1].ECX */
+FEAT_XSAVE_SV_HI,   /* CPUID[EAX=0xd,ECX=1].EDX */
 FEATURE_WORDS,
 } FeatureWord;
 
@@ -687,7 +705,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_7_0_ECX_LA57 (1U << 16)
 #define CPUID_7_0_ECX_RDPID(1U << 22)
 #define CPUID_7_0_ECX_CLDEMOTE (1U << 25)  /* CLDEMOTE Instruction */
-
+#define CPUID_7_0_ECX_CET_SHSTK (1U << 7)  /* CET SHSTK feature bit */
 #define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network 
Instructions */
 #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation 
Single Precision */
 #define CPUID_7_0_EDX_PCONFIG (1U << 18)   /* Platform Configuration */
@@ -1021,6 +1039,19 @@ typedef struct XSavePKRU {
 uint32_t padding;
 } XSavePKRU;
 
+/* Ext. save area 11: User mode CET state */
+typedef struct XSaveCETU {
+uint64_t u_cet;
+uint64_t user_ssp;
+} XSaveCETU;
+
+/* Ext. save area 12: Supervisor mode CET state */
+typedef struct XSaveCETS {
+uint64_t kernel_ssp;
+uint64_t pl1_ssp;
+uint64_t pl2_ssp;
+} XSaveCETS;
+
 typedef struct X86XSaveArea {
 X86LegacyXSaveArea legacy;
 X86XSaveHeader header;
@@ -1039,6 +1070,9 @@ typedef struct X86XSaveArea {
 XSaveHi16_ZMM hi16_zmm_state;
 /* PKRU State: */
 XSavePKRU pkru_state;
+/* CET State: */
+XSaveCETU cet_u;
+XSaveCETS cet_s;
 } X86XSaveArea;
 
 QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, avx_state) != 0x240);
-- 
2.17.1




[Qemu-devel] [PATCH v2 0/4] This patch-set is to enable Guest

2019-01-23 Thread Yang Weijiang
Control-flow Enforcement Technology (CET) provides protection against
return/jump-oriented programming (ROP) attacks. To make kvm Guest OS own
the capability, this patch-set is required. It enables CET related CPUID
report and xsaves/xrstors support etc in qemu.

Changelog:
 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):
  Add CET xsaves/xrstors related macros and structures.
  Add CET SHSTK and IBT CPUID feature-word definitions.
  Add hepler functions for CPUID xsave area size calculation.
  Report CPUID xsave area support for CET.

 target/i386/cpu.c | 73 +--
 target/i386/cpu.h | 36 ++-
 2 files changed, 105 insertions(+), 4 deletions(-)

-- 
2.17.1




[Qemu-devel] [PATCH v2 2/4] Add CET SHSTK and IBT CPUID feature-word definitions.

2019-01-23 Thread Yang Weijiang
XSS[bit 11] and XSS[bit 12] correspond to CET
user mode area and supervisor mode area respectively.

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 37 +++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index f81d35e1f9..f6c7bdf6fe 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1018,7 +1018,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = 
{
 .type = CPUID_FEATURE_WORD,
 .feat_names = {
 NULL, "avx512vbmi", "umip", "pku",
-NULL /* ospke */, NULL, "avx512vbmi2", NULL,
+NULL /* ospke */, NULL, "avx512vbmi2", "shstk",
 "gfni", "vaes", "vpclmulqdq", "avx512vnni",
 "avx512bitalg", NULL, "avx512-vpopcntdq", NULL,
 "la57", NULL, NULL, NULL,
@@ -1041,7 +1041,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = 
{
 NULL, NULL, NULL, NULL,
 NULL, NULL, NULL, NULL,
 NULL, NULL, "pconfig", NULL,
-NULL, NULL, NULL, NULL,
+"ibt", NULL, NULL, NULL,
 NULL, NULL, "spec-ctrl", NULL,
 NULL, "arch-capabilities", NULL, "ssbd",
 },
@@ -1162,6 +1162,25 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] 
= {
 }
 },
 },
+/* Below are CET supervisor xsave features */
+[FEAT_XSAVE_SV_LO] = {
+.type = CPUID_FEATURE_WORD,
+.cpuid = {
+.eax = 0xD,
+.needs_ecx = true,
+.ecx = 1,
+.reg = R_ECX,
+},
+},
+[FEAT_XSAVE_SV_HI] = {
+.type = CPUID_FEATURE_WORD,
+.cpuid = {
+.eax = 0xD,
+.needs_ecx = true,
+.ecx = 1,
+.reg = R_EDX
+},
+}
 };
 
 typedef struct X86RegisterInfo32 {
@@ -1233,6 +1252,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(XSaveCETU) },
+[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(XSaveCETS) },
 };
 
 static uint32_t xsave_area_size(uint64_t mask)
@@ -1243,6 +1270,9 @@ static uint32_t xsave_area_size(uint64_t mask)
 for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
 const ExtSaveArea *esa = _ext_save_areas[i];
 if ((mask >> i) & 1) {
+if (i >= 2 && !esa->offset) {
+continue;
+}
 ret = MAX(ret, esa->offset + esa->size);
 }
 }
@@ -4657,6 +4687,9 @@ static void x86_cpu_reset(CPUState *s)
 }
 for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
 const ExtSaveArea *esa = _ext_save_areas[i];
+if (!esa->offset) {
+continue;
+}
 if (env->features[esa->feature] & esa->bits) {
 xcr0 |= 1ull << i;
 }
-- 
2.17.1




[Qemu-devel] [PATCH v2 4/4] Report CPUID xsave area support for CET.

2019-01-23 Thread Yang Weijiang
CPUID bit definition as below:
CPUID.(EAX=d, ECX=1):ECX.CET_U(bit 11): user mode state
CPUID.(EAX=d, ECX=1):ECX.CET_S(bit 12): kernel mode state

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index d8c36e0f2f..15e2d5e009 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -4399,12 +4399,22 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, 
uint32_t count,
 *ebx = xsave_area_size(env->xcr0);
 } else if (count == 1) {
 *eax = env->features[FEAT_XSAVE];
+*ecx = env->features[FEAT_XSAVE_SV_LO];
+*edx = env->features[FEAT_XSAVE_SV_HI];
+*ebx = xsave_area_size_compacted(x86_cpu_xsave_components(cpu) |
+x86_cpu_xsave_sv_components(cpu));
 } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {
 if ((x86_cpu_xsave_components(cpu) >> count) & 1) {
 const ExtSaveArea *esa = _ext_save_areas[count];
 *eax = esa->size;
 *ebx = esa->offset;
 }
+if ((x86_cpu_xsave_sv_components(cpu) >> count) & 1) {
+const ExtSaveArea *esa_sv = _ext_save_areas[count];
+*eax = esa_sv->size;
+*ebx = 0;
+*ecx = 1;
+}
 }
 break;
 }
-- 
2.17.1




Re: [Qemu-devel] [PATCH 2/4] Add CET SHSTK and IBT CPUID feature-word definitions.

2018-12-29 Thread Yang Weijiang
On Fri, Dec 28, 2018 at 03:25:10PM +0100, Paolo Bonzini wrote:
Thanks a lot Paolo for the comments!

I'll fix the issue in next version.

> On 26/12/18 09:25, Yang Weijiang wrote:
> > @@ -1233,6 +1252,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 = offsetof(X86XSaveArea, cet_u),
> 
> These offsets are incorrect, since supervisor states are only stored in
> the compacted format.  In fact, in patch 4, supervisor states should
> return 0 in CPUID(EAX=0Dh,ECX=n).EBX.
> 
> You can use offset == 0 to distinguish supervisor and user states, so
> that supervisor states are skipped in xsave_area_size and x86_cpu_reset.
> 
> Thanks,
> 
> Paolo
> 
> > +.size = sizeof(XSaveCETU) },
> > +[XSTATE_CET_S_BIT] = {
> > +.feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_CET_SHSTK,
> > +.offset = offsetof(X86XSaveArea, cet_s),
> > +.size = sizeof(XSaveCETS) },
> >  };
> >  
> >  static uint32_t xsave_area_size(uint64_t mask)



[Qemu-devel] [PATCH 2/4] Add CET SHSTK and IBT CPUID feature-word definitions.

2018-12-26 Thread Yang Weijiang
XSS[bit 11] and XSS[bit 12] correspond to CET
user mode area and supervisor mode area respectively.

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 31 +--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index f81d35e1f9..3630c688d6 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1018,7 +1018,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = 
{
 .type = CPUID_FEATURE_WORD,
 .feat_names = {
 NULL, "avx512vbmi", "umip", "pku",
-NULL /* ospke */, NULL, "avx512vbmi2", NULL,
+NULL /* ospke */, NULL, "avx512vbmi2", "shstk",
 "gfni", "vaes", "vpclmulqdq", "avx512vnni",
 "avx512bitalg", NULL, "avx512-vpopcntdq", NULL,
 "la57", NULL, NULL, NULL,
@@ -1041,7 +1041,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = 
{
 NULL, NULL, NULL, NULL,
 NULL, NULL, NULL, NULL,
 NULL, NULL, "pconfig", NULL,
-NULL, NULL, NULL, NULL,
+"ibt", NULL, NULL, NULL,
 NULL, NULL, "spec-ctrl", NULL,
 NULL, "arch-capabilities", NULL, "ssbd",
 },
@@ -1162,6 +1162,25 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] 
= {
 }
 },
 },
+/* Below are CET supervisor xsave features */
+[FEAT_XSAVE_SV_LO] = {
+.type = CPUID_FEATURE_WORD,
+.cpuid = {
+.eax = 0xD,
+.needs_ecx = true,
+.ecx = 1,
+.reg = R_ECX,
+},
+},
+[FEAT_XSAVE_SV_HI] = {
+.type = CPUID_FEATURE_WORD,
+.cpuid = {
+.eax = 0xD,
+.needs_ecx = true,
+.ecx = 1,
+.reg = R_EDX
+},
+}
 };
 
 typedef struct X86RegisterInfo32 {
@@ -1233,6 +1252,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 = offsetof(X86XSaveArea, cet_u),
+.size = sizeof(XSaveCETU) },
+[XSTATE_CET_S_BIT] = {
+.feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_CET_SHSTK,
+.offset = offsetof(X86XSaveArea, cet_s),
+.size = sizeof(XSaveCETS) },
 };
 
 static uint32_t xsave_area_size(uint64_t mask)
-- 
2.17.1




[Qemu-devel] [PATCH 4/4] Report CPUID xsave area support for CET.

2018-12-26 Thread Yang Weijiang
CPUID bit definition as below:
CPUID.(EAX=d, ECX=1):ECX.CET_U(bit 11): user mode state
CPUID.(EAX=d, ECX=1):ECX.CET_S(bit 12): kernel mode state

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index cf4f2798dc..78994bfa1d 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -4396,12 +4396,22 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, 
uint32_t count,
 *ebx = xsave_area_size(env->xcr0);
 } else if (count == 1) {
 *eax = env->features[FEAT_XSAVE];
+*ecx = env->features[FEAT_XSAVE_SV_LO];
+*edx = env->features[FEAT_XSAVE_SV_HI];
+*ebx = xsave_area_size_compat(x86_cpu_xsave_components(cpu) |
+x86_cpu_xsave_sv_components(cpu));
 } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {
 if ((x86_cpu_xsave_components(cpu) >> count) & 1) {
 const ExtSaveArea *esa = _ext_save_areas[count];
 *eax = esa->size;
 *ebx = esa->offset;
 }
+if ((x86_cpu_xsave_sv_components(cpu) >> count) & 1) {
+const ExtSaveArea *esa_sv = _ext_save_areas[count];
+*eax = esa_sv->size;
+*ebx = esa_sv->offset;
+*ecx = 1;
+}
 }
 break;
 }
-- 
2.17.1




[Qemu-devel] [PATCH 3/4] Add hepler functions for CPUID xsave area size calculation.

2018-12-26 Thread Yang Weijiang
These functions are called when return CPUID xsave area
size information.

Signed-off-by: Zhang Yi 
Signed-off-by: Yang Weijiang 
---
 target/i386/cpu.c | 26 +-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 3630c688d6..cf4f2798dc 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1281,12 +1281,34 @@ static inline bool accel_uses_host_cpuid(void)
 return kvm_enabled() || hvf_enabled();
 }
 
+static uint32_t xsave_area_size_compat(uint64_t mask)
+{
+int i;
+uint64_t ret = 0;
+uint32_t offset;
+
+for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
+const ExtSaveArea *esa = _ext_save_areas[i];
+offset = i > 1 ? ret : esa->offset;
+if ((mask >> i) & 1) {
+ret = MAX(ret, offset + esa->size);
+}
+}
+return ret;
+}
+
 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];
 }
 
+static inline uint64_t x86_cpu_xsave_sv_components(X86CPU *cpu)
+{
+return ((uint64_t)cpu->env.features[FEAT_XSAVE_SV_HI]) << 32 |
+   cpu->env.features[FEAT_XSAVE_SV_LO];
+}
+
 const char *get_register_name_32(unsigned int reg)
 {
 if (reg >= CPU_NB_REGS32) {
@@ -4913,8 +4935,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_XSAVE_SV_LO] = mask & CPUID_XSTATE_KERNEL_MASK;
+env->features[FEAT_XSAVE_SV_HI] = mask >> 32;
 }
 
 /* Steps involved on loading and filtering CPUID data
-- 
2.17.1




[Qemu-devel] [PATCH 0/4] This patch-set is to enable Guest CET support.

2018-12-26 Thread Yang Weijiang
Control-flow Enforcement Technology (CET) provides protection against
return/jump-oriented programming (ROP) attacks. To make kvm Guest OS
own the capability, this patch-set is required. It enables CET related
CPUID report and xsaves/xrstors support etc in qemu.

Yang Weijiang (4):
  Add CET xsaves/xrstors related macros and structures.
  Add CET SHSTK and IBT CPUID feature-word definitions.
  Add hepler functions for CPUID xsave area size calculation.
  Report CPUID xsave area support for CET.

 target/i386/cpu.c | 67 ---
 target/i386/cpu.h | 36 -
 2 files changed, 99 insertions(+), 4 deletions(-)

-- 
2.17.1




  1   2   >