From: Yang Weijiang <[email protected]> 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 <[email protected]> Suggested-by: Xin Li (Intel) <[email protected]> Signed-off-by: Yang Weijiang <[email protected]> Co-developed-by: Chao Gao <[email protected]> Signed-off-by: Chao Gao <[email protected]> Co-developed-by: Zhao Liu <[email protected]> Signed-off-by: Zhao Liu <[email protected]> --- 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
