From: Yang Weijiang <weijiang.yang@intel.com>
CET (architectural) 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_INT_SSP_TAB - linear address of interrupt SSP table
Since FRED also needs to save/restore MSR_IA32_PL0_SSP, to avoid duplicate
operations, make FRED only save/restore MSR_IA32_PL0_SSP when CET-SHSTK
is not enumerated.
And considerring MSR_IA32_SSP_TBL_ADDR is only presented on 64 bit
processor, wrap it with TARGET_X86_64 macro.
For other MSRs, add save/restore support directly.
Tested-by: Farrah Chen <farrah.chen@intel.com>
Suggested-by: Xin Li (Intel) <xin@zytor.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
Co-developed-by: Chao Gao <chao.gao@intel.com>
Signed-off-by: Chao Gao <chao.gao@intel.com>
Co-developed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
---
Changes Since v3:
- Make FRED only save/restore MSR_IA32_PL0_SSP when CET-SHSTK isn't
enumerated.
- Wrap MSR_IA32_INT_SSP_TAB with TARGET_X86_64 since it's a
x86_64-specific MSR.
Changes Since v2:
- Rename MSR_IA32_SSP_TBL_ADDR to MSR_IA32_INT_SSP_TAB.
- Rename X86CPUState.ssp_table_addr to X86CPUState.int_ssp_table.
- Drop X86CPUStete.guest_ssp since it is not used in current commit.
- Do not check CET-S & CET-U xtates when get/set MSTs since CET
is XSAVE-managed feature but is not XSAVE-enabled.
---
target/i386/cpu.h | 26 ++++++++++---
target/i386/kvm/kvm.c | 91 ++++++++++++++++++++++++++++++++++++-------
2 files changed, 98 insertions(+), 19 deletions(-)
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 0432af1769d2..661b798da4d0 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -543,7 +543,7 @@ typedef enum X86Seg {
#define MSR_IA32_XFD 0x000001c4
#define MSR_IA32_XFD_ERR 0x000001c5
-/* FRED MSRs */
+/* FRED MSRs (MSR_IA32_FRED_SSP0 is defined as MSR_IA32_PL0_SSP in CET MSRs) */
#define MSR_IA32_FRED_RSP0 0x000001cc /* Stack level 0 regular stack pointer */
#define MSR_IA32_FRED_RSP1 0x000001cd /* Stack level 1 regular stack pointer */
#define MSR_IA32_FRED_RSP2 0x000001ce /* Stack level 2 regular stack pointer */
@@ -554,9 +554,6 @@ typedef enum X86Seg {
#define MSR_IA32_FRED_SSP3 0x000001d3 /* Stack level 3 shadow stack pointer in ring 0 */
#define MSR_IA32_FRED_CONFIG 0x000001d4 /* FRED Entrypoint and interrupt stack level */
-/* FRED and CET MSR */
-#define MSR_IA32_PL0_SSP 0x000006a4 /* ring-0 shadow stack pointer (aka MSR_IA32_FRED_SSP0 for FRED) */
-
#define MSR_IA32_BNDCFGS 0x00000d90
#define MSR_IA32_XSS 0x00000da0
#define MSR_IA32_UMWAIT_CONTROL 0xe1
@@ -583,6 +580,15 @@ typedef enum X86Seg {
#define MSR_APIC_START 0x00000800
#define MSR_APIC_END 0x000008ff
+/* CET MSRs */
+#define MSR_IA32_U_CET 0x000006a0 /* user mode cet */
+#define MSR_IA32_S_CET 0x000006a2 /* kernel mode cet */
+#define MSR_IA32_PL0_SSP 0x000006a4 /* ring-0 shadow stack pointer */
+#define MSR_IA32_PL1_SSP 0x000006a5 /* ring-1 shadow stack pointer */
+#define MSR_IA32_PL2_SSP 0x000006a6 /* ring-2 shadow stack pointer */
+#define MSR_IA32_PL3_SSP 0x000006a7 /* ring-3 shadow stack pointer */
+#define MSR_IA32_INT_SSP_TAB 0x000006a8 /* exception shadow stack table */
+
#define XSTATE_FP_BIT 0
#define XSTATE_SSE_BIT 1
#define XSTATE_YMM_BIT 2
@@ -1976,8 +1982,16 @@ typedef struct CPUArchState {
uint64_t fred_config;
#endif
- /* MSR used for both FRED and CET (SHSTK) */
- uint64_t pl0_ssp;
+ /* CET MSRs */
+ uint64_t u_cet;
+ uint64_t s_cet;
+ uint64_t pl0_ssp; /* also used for FRED */
+ uint64_t pl1_ssp;
+ uint64_t pl2_ssp;
+ uint64_t pl3_ssp;
+#ifdef TARGET_X86_64
+ uint64_t int_ssp_table;
+#endif
uint64_t tsc_adjust;
uint64_t tsc_deadline;
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 00fead0827ed..4eb58ca19d79 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -4008,11 +4008,14 @@ static int kvm_put_msrs(X86CPU *cpu, KvmPutState level)
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);
- /*
- * Aka MSR_IA32_FRED_SSP0. This MSR is accessible even if
- * CET shadow stack is not supported.
- */
- kvm_msr_entry_add(cpu, MSR_IA32_PL0_SSP, env->pl0_ssp);
+
+ if (!(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_CET_SHSTK)) {
+ /*
+ * Aka MSR_IA32_FRED_SSP0. This MSR is accessible even if
+ * CET shadow stack is not supported.
+ */
+ kvm_msr_entry_add(cpu, MSR_IA32_PL0_SSP, env->pl0_ssp);
+ }
}
}
#endif
@@ -4266,6 +4269,26 @@ static int kvm_put_msrs(X86CPU *cpu, KvmPutState 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) {
+ 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_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_PL3_SSP, env->pl3_ssp);
+
+#ifdef TARGET_X86_64
+ if (lm_capable_kernel) {
+ kvm_msr_entry_add(cpu, MSR_IA32_INT_SSP_TAB,
+ env->int_ssp_table);
+ }
+#endif
+ }
+ }
+
return kvm_buf_set_msrs(cpu);
}
@@ -4500,11 +4523,14 @@ static int kvm_get_msrs(X86CPU *cpu)
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);
- /*
- * Aka MSR_IA32_FRED_SSP0. This MSR is accessible even if
- * CET shadow stack is not supported.
- */
- kvm_msr_entry_add(cpu, MSR_IA32_PL0_SSP, 0);
+
+ if (!(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_CET_SHSTK)) {
+ /*
+ * Aka MSR_IA32_FRED_SSP0. This MSR is accessible even if
+ * CET shadow stack is not supported.
+ */
+ kvm_msr_entry_add(cpu, MSR_IA32_PL0_SSP, 0);
+ }
}
}
#endif
@@ -4662,6 +4688,25 @@ 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) {
+ kvm_msr_entry_add(cpu, MSR_IA32_U_CET, 0);
+ kvm_msr_entry_add(cpu, MSR_IA32_S_CET, 0);
+
+ if (env->features[FEAT_7_0_EDX] & 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_PL3_SSP, 0);
+
+#ifdef TARGET_X86_64
+ if (lm_capable_kernel) {
+ kvm_msr_entry_add(cpu, MSR_IA32_INT_SSP_TAB, 0);
+ }
+#endif
+ }
+ }
+
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, cpu->kvm_msr_buf);
if (ret < 0) {
return ret;
@@ -4756,9 +4801,6 @@ static int kvm_get_msrs(X86CPU *cpu)
case MSR_IA32_FRED_CONFIG:
env->fred_config = msrs[i].data;
break;
- case MSR_IA32_PL0_SSP: /* aka MSR_IA32_FRED_SSP0 */
- env->pl0_ssp = msrs[i].data;
- break;
#endif
case MSR_IA32_TSC:
env->tsc = msrs[i].data;
@@ -5012,6 +5054,29 @@ static int kvm_get_msrs(X86CPU *cpu)
case MSR_ARCH_LBR_INFO_0 ... MSR_ARCH_LBR_INFO_0 + 31:
env->lbr_records[index - MSR_ARCH_LBR_INFO_0].info = 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: /* aka MSR_IA32_FRED_SSP0 */
+ 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;
+#ifdef TARGET_X86_64
+ case MSR_IA32_INT_SSP_TAB:
+ env->int_ssp_table = msrs[i].data;
+ break;
+#endif
case MSR_K7_HWCR:
env->msr_hwcr = msrs[i].data;
break;
--
2.34.1