Introduce support for guest CET feature
Subsystems (4)
v13 cover Introduce support for guest CET feature
Control-flow Enforcement Technology (CET) provides protection against Return/Jump-Oriented Programming (ROP/JOP) attack. There're two CET
sub-features: Shadow Stack (SHSTK) and Indirect Branch Tracking (IBT). SHSTK is to prevent ROP programming and IBT is to prevent JOP programming.
Several parts in KVM have been updated to provide VM CET support, including:
CPUID/XSAVES config, MSR pass-through, user space MSR access interface, vmentry/vmexit config, nested VM etc. These patches have dependency on CET kernel patches for xsaves support and CET definitions, e.g., MSR and related feature flags.
CET kernel patches are here:
https://lkml.kernel.org/r/[email protected]
v13:
- Added CET definitions as a separate patch to facilitate KVM test.
- Disabled CET support in KVM if unrestricted_guest is turned off since in this case CET related instructions/infrastructure cannot be emulated well.
v12:
- Fixed a few issues per Sean and Paolo's review feeback.
- Refactored patches to make them properly arranged.
- Removed unnecessary hard-coded CET states for host/guest.
- Added compile-time assertions for vmcs_field_to_offset_table to detect mismatch of the field type and field encoding number.
- Added a custom MSR MSR_KVM_GUEST_SSP for guest active SSP save/restore.
- Rebased patches to 5.7-rc3.
v11:
- Fixed a guest vmentry failure issue when guest reboots.
- Used vm_xxx_control_{set, clear}bit() to avoid side effect, it'll clear cached data instead of pure VMCS field bits.
- Added vcpu->arch.guest_supported_xss dedidated for guest runtime mask, this avoids supported_xss overwritten issue caused by an old qemu.
- Separated vmentry/vmexit state setting with CR0/CR4 dependency check to make the patch more clear.
- Added CET VMCS states in dump_vmcs() for debugging purpose.
- Other refactor based on testing.
- This patch serial is built on top of below branch and CET kernel patches for seeking xsaves support:
https://git.kernel.org/pub/scm/virt/kvm/kvm.git/log/?h=cpu-caps
v10:
- Refactored code per Sean's review feedback.
- Added CET support for nested VM.
- Removed fix-patch for CPUID(0xd,N) enumeration as this part is done by Paolo and Sean.
- This new patchset is based on Paolo's queued cpu_caps branch.
- Modified patch per XSAVES related change.
- Consolidated KVM unit-test patch with KVM patches.
v9:
- Refactored msr-check functions per Sean's feedback.
- Fixed a few issues per Sean's suggestion.
- Rebased patch to kernel-v5.4.
- Moved CET CPUID feature bits and CR4.CET to last patch.
v8:
- Addressed Jim and Sean's feedback on: 1) CPUID(0xD,i) enumeration. 2) sanity check when configure guest CET. 3) function improvement.
- Added more sanity check functions.
- Set host vmexit default status so that guest won't leak CET status to host when vmexit.
- Added CR0.WP vs. CR4.CET mutual constrains.
v7:
- Rebased patch to kernel v5.3
- Sean suggested to change CPUID(0xd, n) enumeration code as alined with existing one, and I think it's better to make the fix as an independent patch since XSS MSR are being used widely on X86 platforms.
- Check more host and guest status before configure guest CET
per Sean's feedback.
- Add error-check before guest accesses CET MSRs per Sean's feedback.
- Other minor fixes suggested by Sean.
v6:
- Rebase patch to kernel v5.2.
- Move CPUID(0xD, n>=1) helper to a seperate patch.
- Merge xsave size fix with other patch.
- Other minor fixes per community feedback.
v5:
- Rebase patch to kernel v5.1.
- Wrap CPUID(0xD, n>=1) code to a helper function.
- Pass through MSR_IA32_PL1_SSP and MSR_IA32_PL2_SSP to Guest.
- Add Co-developed-by expression in patch description.
- Refine patch description.
v4:
- Add Sean's patch for loading Guest fpu state before access XSAVES managed CET MSRs.
- Melt down CET bits setting into CPUID configuration patch.
- Add VMX interface to query Host XSS.
- Check Host and Guest XSS support bits before set Guest XSS.
- Make Guest SHSTK and IBT feature enabling independent.
- Do not report CET support to Guest when Host CET feature is Disabled.
v3:
- Modified patches to make Guest CET independent to Host enabling.
- Added patch 8 to add user space access for Guest CET MSR access.
- Modified code comments and patch description to reflect changes.
v2:
- Re-ordered patch sequence, combined one patch.
- Added more description for CET related VMCS fields.
- Added Host CET capability check while enabling Guest CET loading bit.
- Added Host CET capability check while reporting Guest CPUID(EAX=7, EXC=0).
- Modified code in reporting Guest CPUID(EAX=D,ECX>=1), make it clearer.
- Added Host and Guest XSS mask check while setting bits for Guest XSS.
Sean Christopherson (1):
KVM: x86: Load guest fpu state when access MSRs managed by XSAVES
Yang Weijiang (10):
KVM: x86: Include CET definitions for KVM test purpose
KVM: VMX: Introduce CET VMCS fields and flags
KVM: VMX: Set guest CET MSRs per KVM and host configuration
KVM: VMX: Configure CET settings upon guest CR0/4 changing
KVM: x86: Refresh CPUID once guest changes XSS bits
KVM: x86: Add userspace access interface for CET MSRs
KVM: VMX: Enable CET support for nested VM
KVM: VMX: Add VMCS dump and sanity check for CET states
KVM: x86: Add #CP support in guest exception dispatch
KVM: x86: Enable CET virtualization and advertise CET to userspace
arch/x86/include/asm/kvm_host.h | 4 +- arch/x86/include/asm/vmx.h | 8 + arch/x86/include/uapi/asm/kvm.h | 1 + arch/x86/include/uapi/asm/kvm_para.h | 7 +- arch/x86/kvm/cpuid.c | 28 ++- arch/x86/kvm/vmx/capabilities.h | 5 + arch/x86/kvm/vmx/nested.c | 34 ++++ arch/x86/kvm/vmx/vmcs12.c | 275 ++++++++++++++++----------- arch/x86/kvm/vmx/vmcs12.h | 14 +- arch/x86/kvm/vmx/vmx.c | 262 ++++++++++++++++++++++++- arch/x86/kvm/x86.c | 47 ++++- arch/x86/kvm/x86.h | 2 +- include/linux/kvm_host.h | 32 ++++ 13 files changed, 588 insertions(+), 131 deletions(-)
Signature · 1 line
2.17.2
PATCH v13 1/11 KVM: x86: Include CET definitions for KVM test purpose
These definitions are added by CET kernel patch and referenced by KVM, if the CET KVM patches are tested without CET kernel patches, this patch should be included.
--- include/linux/kvm_host.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+)
include/linux/kvm_host.h +32 -0
@@ -35,6 +35,38 @@#include <asm/kvm_host.h> +#ifndef CONFIG_X86_INTEL_CET +#define XFEATURE_CET_USER 11 +#define XFEATURE_CET_KERNEL 12 + +#define XFEATURE_MASK_CET_USER (1 << XFEATURE_CET_USER) +#define XFEATURE_MASK_CET_KERNEL (1 << XFEATURE_CET_KERNEL) + +/* Control-flow Enforcement Technology MSRs */ +#define MSR_IA32_U_CET 0x6a0/* user mode cet setting */ +#define MSR_IA32_S_CET 0x6a2/* kernel mode cet setting */ +#define MSR_IA32_PL0_SSP 0x6a4/* kernel shstk pointer */ +#define MSR_IA32_PL1_SSP 0x6a5/* ring-1 shstk pointer */ +#define MSR_IA32_PL2_SSP 0x6a6/* ring-2 shstk pointer */ +#define MSR_IA32_PL3_SSP 0x6a7/* user shstk pointer */ +#define MSR_IA32_INT_SSP_TAB 0x6a8/* exception shstk table */ + +#define X86_CR4_CET_BIT 23/* enable Control-flow Enforcement */ +#define X86_CR4_CET _BITUL(X86_CR4_CET_BIT) + +#define X86_FEATURE_SHSTK (16*32+ 7)/* Shadow Stack */ +#define X86_FEATURE_IBT (18*32+20)/* Indirect Branch Tracking */ + +/* MSR_IA32_U_CET and MSR_IA32_S_CET bits */ +#define MSR_IA32_CET_SHSTK_EN 0x0000000000000001ULL +#define MSR_IA32_CET_WRSS_EN 0x0000000000000002ULL +#define MSR_IA32_CET_ENDBR_EN 0x0000000000000004ULL +#define MSR_IA32_CET_LEG_IW_EN 0x0000000000000008ULL +#define MSR_IA32_CET_NO_TRACK_EN 0x0000000000000010ULL +#define MSR_IA32_CET_WAIT_ENDBR 0x00000000000000800UL +#define MSR_IA32_CET_BITMAP_MASK 0xfffffffffffff000ULL +#endif +#ifndef KVM_MAX_VCPU_ID #define KVM_MAX_VCPU_ID KVM_MAX_VCPUS#endif
Signature · 1 line
2.17.2
PATCH v13 2/11 KVM: VMX: Introduce CET VMCS fields and flags
In reply to Yang WeijiangCET(Control-flow Enforcement Technology) is a CPU feature used to prevent Return/Jump-Oriented Programming(ROP/JOP) attacks. It provides the following sub-features to defend against ROP/JOP style control-flow subversion attacks:
Shadow Stack (SHSTK):
A second stack for program which is used exclusively for control transfer operations.
Indirect Branch Tracking (IBT):
Code branching protection to defend against jump/call oriented programming.
Several new CET MSRs are defined in kernel to support CET:
MSR_IA32_{U,S}_CET: Controls the CET settings for user mode and kernel mode respectively.
MSR_IA32_PL{0,1,2,3}_SSP: Stores shadow stack pointers for CPL-0,1,2,3 protection respectively.
MSR_IA32_INT_SSP_TAB: Stores base address of shadow stack pointer table.
Two XSAVES state bits are introduced for CET:
IA32_XSS:[bit 11]: Control saving/restoring user mode CET states IA32_XSS:[bit 12]: Control saving/restoring kernel mode CET states.
Six VMCS fields are introduced for CET:
{HOST,GUEST}_S_CET: Stores CET settings for kernel mode. {HOST,GUEST}_SSP: Stores shadow stack pointer of current task/thread. {HOST,GUEST}_INTR_SSP_TABLE: Stores base address of shadow stack pointer table.
If VM_EXIT_LOAD_HOST_CET_STATE = 1, the host CET states are restored from below VMCS fields at VM-Exit:
HOST_S_CET
HOST_SSP
HOST_INTR_SSP_TABLE
If VM_ENTRY_LOAD_GUEST_CET_STATE = 1, the guest CET states are loaded from below VMCS fields at VM-Entry:
GUEST_S_CET
GUEST_SSP
GUEST_INTR_SSP_TABLE
--- arch/x86/include/asm/vmx.h | 8 ++++++++ 1 file changed, 8 insertions(+)
arch/x86/include/asm/vmx.h +8 -0
@@ -94,6 +94,7 @@#define VM_EXIT_CLEAR_BNDCFGS 0x00800000#define VM_EXIT_PT_CONCEAL_PIP 0x01000000#define VM_EXIT_CLEAR_IA32_RTIT_CTL 0x02000000 +#define VM_EXIT_LOAD_CET_STATE 0x10000000#define VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR 0x00036dff
@@ -107,6 +108,7 @@#define VM_ENTRY_LOAD_BNDCFGS 0x00010000#define VM_ENTRY_PT_CONCEAL_PIP 0x00020000#define VM_ENTRY_LOAD_IA32_RTIT_CTL 0x00040000 +#define VM_ENTRY_LOAD_CET_STATE 0x00100000#define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR 0x000011ff
@@ -328,6 +330,9 @@ enum vmcs_field {GUEST_PENDING_DBG_EXCEPTIONS =0x00006822 ,GUEST_SYSENTER_ESP =0x00006824 ,GUEST_SYSENTER_EIP =0x00006826 , +GUEST_S_CET =0x00006828 , +GUEST_SSP =0x0000682a , +GUEST_INTR_SSP_TABLE =0x0000682c ,HOST_CR0 =0x00006c00 ,HOST_CR3 =0x00006c02 , HOST_CR4 = 0x00006c04,
@@ -340,6 +345,9 @@ enum vmcs_field {HOST_IA32_SYSENTER_EIP =0x00006c12 ,HOST_RSP =0x00006c14 ,HOST_RIP =0x00006c16 , +HOST_S_CET =0x00006c18 , +HOST_SSP =0x00006c1a , + HOST_INTR_SSP_TABLE = 0x00006c1c };/*
Signature · 1 line
2.17.2
PATCH v13 3/11 KVM: VMX: Set guest CET MSRs per KVM and host configuration
In reply to Yang WeijiangCET MSRs pass through guest directly to enhance performance. CET runtime control settings are stored in MSR_IA32_{U,S}_CET, Shadow Stack Pointer(SSP) are stored in MSR_IA32_PL{0,1,2,3}_SSP, SSP table base address is stored in MSR_IA32_INT_SSP_TAB, these MSRs are defined in kernel and re-used here.
MSR_IA32_U_CET and MSR_IA32_PL3_SSP are used for user-mode protection,the MSR contents are switched between threads during scheduling, it makes sense to pass through them so that the guest kernel can use xsaves/xrstors to operate them efficiently. Other MSRs are used for non-user mode protection. See SDM for detailed info.
The difference between CET VMCS fields and CET MSRs is that,the former are used during VMEnter/VMExit, whereas the latter are used for CET state storage between task/thread scheduling.
--- arch/x86/kvm/vmx/vmx.c | 46 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/kvm/x86.c | 3 +++ 2 files changed, 49 insertions(+)
arch/x86/kvm/vmx/vmx.c +46 -0
@@ -3020,6 +3020,13 @@ void vmx_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long cr3)vmcs_writel (GUEST_CR3 , guest_cr3); } +static bool is_cet_state_supported (struct kvm_vcpu *vcpu,u32 xss_states) +{ +return ((supported_xss & xss_states) && + (guest_cpuid_has (vcpu,X86_FEATURE_SHSTK ) || +guest_cpuid_has (vcpu,X86_FEATURE_IBT ))); +} +int vmx_set_cr4 (struct kvm_vcpu *vcpu,unsigned long cr4) {struct vcpu_vmx *vmx =to_vmx (vcpu);
@@ -7098,6 +7105,42 @@ static void update_intel_pt_cfg(struct kvm_vcpu *vcpu) vmx->pt_desc.ctl_bitmask &= ~(0xfULL << (32 + i *4 )); } +static void vmx_update_intercept_for_cet_msr (struct kvm_vcpu *vcpu) +{ +struct vcpu_vmx *vmx =to_vmx (vcpu); +unsigned long *msr_bitmap = vmx->vmcs01.msr_bitmap; +bool incpt; + + incpt = !is_cet_state_supported (vcpu,XFEATURE_MASK_CET_USER ); +/* +* U_CET is required for USER CET, and U_CET, PL3_SPP are bound as +* one component and controlled by IA32_XSS[bit 11]. +*/ +vmx_set_intercept_for_msr (msr_bitmap,MSR_IA32_U_CET ,MSR_TYPE_RW , + incpt); +vmx_set_intercept_for_msr (msr_bitmap,MSR_IA32_PL3_SSP ,MSR_TYPE_RW , + incpt); + + incpt = !is_cet_state_supported (vcpu,XFEATURE_MASK_CET_KERNEL ); +/* +* S_CET is required for KERNEL CET, and PL0_SSP ... PL2_SSP are +* bound as one component and controlled by IA32_XSS[bit 12]. +*/ +vmx_set_intercept_for_msr (msr_bitmap,MSR_IA32_S_CET ,MSR_TYPE_RW , + incpt); +vmx_set_intercept_for_msr (msr_bitmap,MSR_IA32_PL0_SSP ,MSR_TYPE_RW , + incpt); +vmx_set_intercept_for_msr (msr_bitmap,MSR_IA32_PL1_SSP ,MSR_TYPE_RW , + incpt); +vmx_set_intercept_for_msr (msr_bitmap,MSR_IA32_PL2_SSP ,MSR_TYPE_RW , + incpt); + + incpt |= !guest_cpuid_has (vcpu,X86_FEATURE_SHSTK ); +/* SSP_TAB is only available for KERNEL SHSTK.*/ +vmx_set_intercept_for_msr (msr_bitmap,MSR_IA32_INT_SSP_TAB ,MSR_TYPE_RW , + incpt); +} +static void vmx_cpuid_update (struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu);
@@ -7136,6 +7179,9 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)vmx_set_guest_msr (vmx, msr, enabled ?0 :TSX_CTRL_RTM_DISABLE ); } } + +if (supported_xss & (XFEATURE_MASK_CET_KERNEL |XFEATURE_MASK_CET_USER )) +vmx_update_intercept_for_cet_msr (vcpu); }static __init void vmx_set_cpu_caps (void )
arch/x86/kvm/x86.c +3 -0
@@ -186,6 +186,9 @@ static struct kvm_shared_msrs __percpu *shared_msrs; | XFEATURE_MASK_BNDCSR | XFEATURE_MASK_AVX512 \ | XFEATURE_MASK_PKRU) +#define KVM_SUPPORTED_XSS (XFEATURE_MASK_CET_USER | \ + XFEATURE_MASK_CET_KERNEL) +u64 __read_mostly host_efer;EXPORT_SYMBOL_GPL (host_efer);
Signature · 1 line
2.17.2
Re: [PATCH v13 03/11] KVM: VMX: Set guest CET MSRs per KVM and host configuration
Quoted 99 lines · Yang Weijiang
CET MSRs pass through guest directly to enhance performance. CET runtime control settings are stored in MSR_IA32_{U,S}_CET, Shadow Stack Pointer(SSP) are stored in MSR_IA32_PL{0,1,2,3}_SSP, SSP table base address is stored in
MSR_IA32_INT_SSP_TAB, these MSRs are defined in kernel and re-used here.
MSR_IA32_U_CETandMSR_IA32_PL3_SSPare used for user-mode protection,the MSR contents are switched between threads during scheduling, it makes sense to pass through them so that the guest kernel can use xsaves/xrstors to operate them efficiently. Other MSRs are used for non-user mode protection. See SDM for detailed info.The difference between CET VMCS fields and CET MSRs is that,the former are used during VMEnter/VMExit, whereas the latter are used for CET state storage between task/thread scheduling.
Co-developed-by Zhang Yi Z <[email protected]>Signed-off-by Zhang Yi Z <[email protected]>Signed-off-by Yang Weijiang <[email protected]>--- arch/x86/kvm/vmx/vmx.c | 46 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/kvm/x86.c | 3 +++ 2 files changed, 49 insertions(+)arch/x86/kvm/vmx/vmx.c +46
-0@@ -3020,6 +3020,13 @@ void vmx_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long cr3)vmcs_writel (GUEST_CR3 , guest_cr3); } +static bool is_cet_state_supported (struct kvm_vcpu *vcpu,u32 xss_states) +{ +return ((supported_xss & xss_states) && + (guest_cpuid_has (vcpu,X86_FEATURE_SHSTK ) || +guest_cpuid_has (vcpu,X86_FEATURE_IBT ))); +} +int vmx_set_cr4 (struct kvm_vcpu *vcpu,unsigned long cr4) {struct vcpu_vmx *vmx =to_vmx (vcpu);@@ -7098,6 +7105,42 @@ static void update_intel_pt_cfg(struct kvm_vcpu *vcpu) vmx->pt_desc.ctl_bitmask &= ~(0xfULL << (32 + i *4 )); } +static void vmx_update_intercept_for_cet_msr (struct kvm_vcpu *vcpu) +{ +struct vcpu_vmx *vmx =to_vmx (vcpu); +unsigned long *msr_bitmap = vmx->vmcs01.msr_bitmap; +bool incpt; + + incpt = !is_cet_state_supported (vcpu,XFEATURE_MASK_CET_USER ); +/* +* U_CET is required for USER CET, and U_CET, PL3_SPP are bound as +* one component and controlled by IA32_XSS[bit 11]. +*/ +vmx_set_intercept_for_msr (msr_bitmap,MSR_IA32_U_CET ,MSR_TYPE_RW , + incpt); +vmx_set_intercept_for_msr (msr_bitmap,MSR_IA32_PL3_SSP ,MSR_TYPE_RW , + incpt); + + incpt = !is_cet_state_supported (vcpu,XFEATURE_MASK_CET_KERNEL ); +/* +* S_CET is required for KERNEL CET, and PL0_SSP ... PL2_SSP are +* bound as one component and controlled by IA32_XSS[bit 12]. +*/ +vmx_set_intercept_for_msr (msr_bitmap,MSR_IA32_S_CET ,MSR_TYPE_RW , + incpt); +vmx_set_intercept_for_msr (msr_bitmap,MSR_IA32_PL0_SSP ,MSR_TYPE_RW , + incpt); +vmx_set_intercept_for_msr (msr_bitmap,MSR_IA32_PL1_SSP ,MSR_TYPE_RW , + incpt); +vmx_set_intercept_for_msr (msr_bitmap,MSR_IA32_PL2_SSP ,MSR_TYPE_RW , + incpt); + + incpt |= !guest_cpuid_has (vcpu,X86_FEATURE_SHSTK ); +/* SSP_TAB is only available for KERNEL SHSTK.*/ +vmx_set_intercept_for_msr (msr_bitmap,MSR_IA32_INT_SSP_TAB ,MSR_TYPE_RW , + incpt); +} +static void vmx_cpuid_update (struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu);@@ -7136,6 +7179,9 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)vmx_set_guest_msr (vmx, msr, enabled ?0 :TSX_CTRL_RTM_DISABLE ); } } + +if (supported_xss & (XFEATURE_MASK_CET_KERNEL |XFEATURE_MASK_CET_USER )) +vmx_update_intercept_for_cet_msr (vcpu); }static __init void vmx_set_cpu_caps (void )arch/x86/kvm/x86.c +0
-0
arch/x86/kvm/x86.c static struct kvm_shared_msrs __percpu *shared_msrs; · line 191
Quoted 6 lines
arch/x86/kvm/x86.c +3
-0@@ -186,6 +186,9 @@ static struct kvm_shared_msrs __percpu *shared_msrs; | XFEATURE_MASK_BNDCSR | XFEATURE_MASK_AVX512 \ | XFEATURE_MASK_PKRU) +#define KVM_SUPPORTED_XSS (XFEATURE_MASK_CET_USER | \ + XFEATURE_MASK_CET_KERNEL) +
This definition need to be moved to Patch 5?
Quoted 4 lines
arch/x86/kvm/x86.c +0
-0u64 __read_mostly host_efer;EXPORT_SYMBOL_GPL (host_efer);
Re: [PATCH v13 03/11] KVM: VMX: Set guest CET MSRs per KVM and host configuration
Quoted 14 lines · Xiaoyao Li
arch/x86/kvm/x86.c static struct kvm_shared_msrs __percpu *shared_msrs; · line 190
Quoted 10 lines · Yang Weijiang
arch/x86/kvm/x86.c +3
-0@@ -186,6 +186,9 @@ static struct kvm_shared_msrs __percpu *shared_msrs; | XFEATURE_MASK_BNDCSR | XFEATURE_MASK_AVX512 \ | XFEATURE_MASK_PKRU) +#define KVM_SUPPORTED_XSS (XFEATURE_MASK_CET_USER | \ + XFEATURE_MASK_CET_KERNEL) +This definition need to be moved to Patch 5?
Good capture, thanks! I'll move it in next series.
Quoted 3 lines
Quoted 3 lines
arch/x86/kvm/x86.c +0
-0u64 __read_mostly host_efer;EXPORT_SYMBOL_GPL (host_efer);
PATCH v13 4/11 KVM: VMX: Configure CET settings upon guest CR0/4 changing
In reply to Yang WeijiangCR4.CET is master control bit for CET function. There're mutual constrains between CR0.WP and CR4.CET, so need to check the dependent bit while changing the control registers.
The processor does not allow CR4.CET to be set if CR0.WP = 0,similarly, it does not allow CR0.WP to be cleared while CR4.CET = 1. In either case, KVM would inject #GP to guest.
CET state load bit is set/cleared along with CR4.CET bit set/clear.
Note:
SHSTK and IBT features share one control MSR: MSR_IA32_{U,S}_CET, which means it's difficult to hide one feature from another in the case of SHSTK != IBT, after discussed in community, it's agreed to allow guest control two features independently as it won't introduce security hole.
--- arch/x86/kvm/vmx/capabilities.h | 5 +++++ arch/x86/kvm/vmx/vmx.c | 30 ++++++++++++++++++++++++++++-- arch/x86/kvm/x86.c | 3 +++ 3 files changed, 36 insertions(+), 2 deletions(-)
arch/x86/kvm/vmx/capabilities.h +5 -0
@@ -101,6 +101,11 @@ static inline bool cpu_has_load_perf_global_ctrl(void) (vmcs_config.vmexit_ctrl &VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL ); } +static inline bool cpu_has_load_cet_ctrl (void ) +{ +return (vmcs_config.vmentry_ctrl &VM_ENTRY_LOAD_CET_STATE ) && + (vmcs_config.vmexit_ctrl &VM_EXIT_LOAD_CET_STATE ); +}static inline bool cpu_has_vmx_mpx (void ) { return (vmcs_config.vmexit_ctrl & VM_EXIT_CLEAR_BNDCFGS) &&
arch/x86/kvm/vmx/vmx.c +28 -2
@@ -2440,7 +2440,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,VM_EXIT_LOAD_IA32_EFER |VM_EXIT_CLEAR_BNDCFGS |VM_EXIT_PT_CONCEAL_PIP | -VM_EXIT_CLEAR_IA32_RTIT_CTL ; +VM_EXIT_CLEAR_IA32_RTIT_CTL | +VM_EXIT_LOAD_CET_STATE ;if (adjust_vmx_controls (min, opt,MSR_IA32_VMX_EXIT_CTLS , &_vmexit_control) <0 )return -EIO ;
@@ -2464,7 +2465,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,VM_ENTRY_LOAD_IA32_EFER |VM_ENTRY_LOAD_BNDCFGS |VM_ENTRY_PT_CONCEAL_PIP | -VM_ENTRY_LOAD_IA32_RTIT_CTL ; +VM_ENTRY_LOAD_IA32_RTIT_CTL | +VM_ENTRY_LOAD_CET_STATE ;if (adjust_vmx_controls (min, opt,MSR_IA32_VMX_ENTRY_CTLS , &_vmentry_control) <0 )return -EIO ;
@@ -3027,6 +3029,12 @@ static bool is_cet_state_supported(struct kvm_vcpu *vcpu, u32 xss_states) guest_cpuid_has(vcpu, X86_FEATURE_IBT))); } +static bool is_cet_supported (struct kvm_vcpu *vcpu) +{ +return is_cet_state_supported (vcpu,XFEATURE_MASK_CET_USER | +XFEATURE_MASK_CET_KERNEL ); +} +int vmx_set_cr4 (struct kvm_vcpu *vcpu,unsigned long cr4) {struct vcpu_vmx *vmx =to_vmx (vcpu);
@@ -3067,6 +3075,10 @@ int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)return 1 ; } +if ((cr4 &X86_CR4_CET ) && (!is_cet_supported (vcpu) || + !(kvm_read_cr0 (vcpu) &X86_CR0_WP ))) +return 1 ; +if (vmx->nested.vmxon && !nested_cr4_valid (vcpu, cr4))return 1 ;
@@ -3097,6 +3109,20 @@ int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) hw_cr4 &= ~(X86_CR4_SMEP |X86_CR4_SMAP |X86_CR4_PKE ); } +if (cpu_has_load_cet_ctrl ()) { +if ((hw_cr4 &X86_CR4_CET ) &&is_cet_supported (vcpu)) { +vm_entry_controls_setbit (to_vmx (vcpu), +VM_ENTRY_LOAD_CET_STATE ); +vm_exit_controls_setbit (to_vmx (vcpu), +VM_EXIT_LOAD_CET_STATE ); + }else { +vm_entry_controls_clearbit (to_vmx (vcpu), +VM_ENTRY_LOAD_CET_STATE ); +vm_exit_controls_clearbit (to_vmx (vcpu), +VM_EXIT_LOAD_CET_STATE ); + } + } +vmcs_writel (CR4_READ_SHADOW , cr4);vmcs_writel (GUEST_CR4 , hw_cr4);return 0 ;
arch/x86/kvm/x86.c +3 -0
@@ -803,6 +803,9 @@ int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)if (!(cr0 &X86_CR0_PG ) &&kvm_read_cr4_bits (vcpu,X86_CR4_PCIDE ))return 1 ; +if (!(cr0 &X86_CR0_WP ) &&kvm_read_cr4_bits (vcpu,X86_CR4_CET )) +return 1 ; + kvm_x86_ops.set_cr0 (vcpu, cr0);if ((cr0 ^ old_cr0) &X86_CR0_PG ) {
Signature · 1 line
2.17.2
PATCH v13 5/11 KVM: x86: Refresh CPUID once guest changes XSS bits
In reply to Yang WeijiangCPUID(0xd, 1) reports the current required storage size of XCR0 | XSS, when guest updates the XSS, it's necessary to update the CPUID leaf, otherwise guest will fetch old state size, and results to some WARN traces during guest running.
supported_xss is initialized to host_xss & KVM_SUPPORTED_XSS to indicate current MSR_IA32_XSS bits supported in KVM, but actual XSS bits seen in guest depends on the setting of CPUID(0xd,1).{ECX, EDX} for guest.
--- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/cpuid.c | 23 +++++++++++++++++++---- arch/x86/kvm/x86.c | 12 ++++++++---- 3 files changed, 28 insertions(+), 8 deletions(-)
arch/x86/include/asm/kvm_host.h +1 -0
@@ -649,6 +649,7 @@ struct kvm_vcpu_arch {u64 xcr0;u64 guest_supported_xcr0; +u64 guest_supported_xss;u32 guest_xstate_size;struct kvm_pio_request pio;
arch/x86/kvm/cpuid.c +19 -4
@@ -89,15 +89,30 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu) vcpu->arch.guest_xstate_size =XSAVE_HDR_SIZE +XSAVE_HDR_OFFSET ; }else { vcpu->arch.guest_supported_xcr0 = - (best->eax | ((u64 )best->edx <<32 )) & supported_xcr0; + (((u64 )best->edx <<32 ) | best->eax) & supported_xcr0; vcpu->arch.guest_xstate_size = best->ebx =xstate_required_size (vcpu->arch.xcr0, false); } best =kvm_find_cpuid_entry (vcpu,0xD ,1 ); -if (best && (cpuid_entry_has (best,X86_FEATURE_XSAVES ) || -cpuid_entry_has (best,X86_FEATURE_XSAVEC ))) - best->ebx =xstate_required_size (vcpu->arch.xcr0, true); +if (best) { +if (cpuid_entry_has (best,X86_FEATURE_XSAVES ) || +cpuid_entry_has (best,X86_FEATURE_XSAVEC )) { +u64 xstate = vcpu->arch.xcr0 | vcpu->arch.ia32_xss; + + best->ebx =xstate_required_size (xstate, true); + } + +if (!cpuid_entry_has (best,X86_FEATURE_XSAVES )) { + best->ecx =0 ; + best->edx =0 ; + } + vcpu->arch.guest_supported_xss = + (((u64 )best->edx <<32 ) | best->ecx) & supported_xss; + + }else { + vcpu->arch.guest_supported_xss =0 ; + }/* * The existing code assumes virtual address is 48-bit or 57-bit in the
arch/x86/kvm/x86.c +8 -4
@@ -2843,9 +2843,12 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)* IA32_XSS[bit 8]. Guests have to use RDMSR/WRMSR rather than * XSAVES/XRSTORS to save/restore PT MSRs. */ -if (data & ~supported_xss) +if (data & ~vcpu->arch.guest_supported_xss)return 1 ; - vcpu->arch.ia32_xss = data; +if (vcpu->arch.ia32_xss != data) { + vcpu->arch.ia32_xss = data; +kvm_update_cpuid (vcpu); + }break ;case MSR_SMI_COUNT :if (!msr_info->host_initiated)
@@ -9678,8 +9681,9 @@ int kvm_arch_hardware_setup(void *opaque)memcpy (&kvm_x86_ops, ops->runtime_ops,sizeof (kvm_x86_ops)); -if (!kvm_cpu_cap_has (X86_FEATURE_XSAVES )) - supported_xss =0 ; + supported_xss =0 ; +if (kvm_cpu_cap_has (X86_FEATURE_XSAVES )) + supported_xss = host_xss &KVM_SUPPORTED_XSS ; cr4_reserved_bits =kvm_host_cr4_reserved_bits (&boot_cpu_data);
Signature · 1 line
2.17.2
PATCH v13 6/11 KVM: x86: Load guest fpu state when access MSRs managed by XSAVES
In reply to Yang WeijiangFrom: Sean Christopherson <[email protected]>
A handful of CET MSRs are not context switched through "traditional" methods, e.g. VMCS or manual switching, but rather are passed through to the guest and are saved and restored by XSAVES/XRSTORS, i.e. in the guest's FPU state.
Load the guest's FPU state if userspace is accessing MSRs whose values are managed by XSAVES so that the MSR helper, e.g. vmx_{get,set}_msr(), can simply do {RD,WR}MSR to access the guest's value.
Note that guest_cpuid_has() is not queried as host userspace is allowed to access MSRs that have not been exposed to the guest, e.g. it might do KVM_SET_MSRS prior to KVM_SET_CPUID2.
--- arch/x86/kvm/x86.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-)
arch/x86/kvm/x86.c +18 -1
@@ -109,6 +109,8 @@ static void enter_smm(struct kvm_vcpu *vcpu);static void __kvm_set_rflags (struct kvm_vcpu *vcpu,unsigned long rflags);static void store_regs (struct kvm_vcpu *vcpu);static int sync_regs (struct kvm_vcpu *vcpu); +static void kvm_load_guest_fpu (struct kvm_vcpu *vcpu); +static void kvm_put_guest_fpu (struct kvm_vcpu *vcpu);struct kvm_x86_ops kvm_x86_ops__read_mostly ;EXPORT_SYMBOL_GPL (kvm_x86_ops);
@@ -3267,6 +3269,12 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) }EXPORT_SYMBOL_GPL (kvm_get_msr_common); +static bool is_xsaves_msr (u32 index) +{ +return index ==MSR_IA32_U_CET || + (index >=MSR_IA32_PL0_SSP && index <=MSR_IA32_PL3_SSP ); +} +/* * Read or write a bunch of msrs. All parameters are kernel addresses. *
@@ -3277,11 +3285,20 @@ static int __msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs *msrs,int (*do_msr)(struct kvm_vcpu *vcpu, unsigned index, u64 *data)) { +bool fpu_loaded = false;int i; -for (i =0 ; i < msrs->nmsrs; ++i) +for (i =0 ; i < msrs->nmsrs; ++i) { +if (vcpu && !fpu_loaded && supported_xss && +is_xsaves_msr (entries[i].index)) { +kvm_load_guest_fpu (vcpu); + fpu_loaded = true; + }if (do_msr (vcpu, entries[i].index, &entries[i].data))break ; + } +if (fpu_loaded) +kvm_put_guest_fpu (vcpu);return i; }
Signature · 1 line
2.17.2
PATCH v13 7/11 KVM: x86: Add userspace access interface for CET MSRs
In reply to Yang WeijiangThere're two different places storing Guest CET states, states managed with XSAVES/XRSTORS, as restored/saved in previous patch, can be read/write directly from/to the MSRs. For those stored in VMCS fields, they're access via vmcs_read/vmcs_write.
To correctly read/write the CET MSRs, it's necessary to check whether the kernel FPU context switch happened and reload guest FPU context if needed.
--- arch/x86/include/uapi/asm/kvm_para.h | 7 +- arch/x86/kvm/vmx/vmx.c | 148 +++++++++++++++++++++++++++ arch/x86/kvm/x86.c | 4 + 3 files changed, 156 insertions(+), 3 deletions(-)
arch/x86/include/uapi/asm/kvm_para.h +4 -3
@@ -46,10 +46,11 @@/* Custom MSRs falls in the range 0x4b564d00-0x4b564dff */ #define MSR_KVM_WALL_CLOCK_NEW 0x4b564d00#define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01 -#define MSR_KVM_ASYNC_PF_EN 0x4b564d02 -#define MSR_KVM_STEAL_TIME 0x4b564d03 -#define MSR_KVM_PV_EOI_EN 0x4b564d04 +#define MSR_KVM_ASYNC_PF_EN 0x4b564d02 +#define MSR_KVM_STEAL_TIME 0x4b564d03 +#define MSR_KVM_PV_EOI_EN 0x4b564d04#define MSR_KVM_POLL_CONTROL 0x4b564d05 +#define MSR_KVM_GUEST_SSP 0x4b564d06struct kvm_steal_time {__u64 steal;
arch/x86/kvm/vmx/vmx.c +148 -0
166 lines not on this page · raw message
arch/x86/kvm/x86.c +4 -0
@@ -1228,6 +1228,10 @@ static const u32 msrs_to_save_all[] = {MSR_ARCH_PERFMON_EVENTSEL0 +12 ,MSR_ARCH_PERFMON_EVENTSEL0 +13 ,MSR_ARCH_PERFMON_EVENTSEL0 +14 ,MSR_ARCH_PERFMON_EVENTSEL0 +15 ,MSR_ARCH_PERFMON_EVENTSEL0 +16 ,MSR_ARCH_PERFMON_EVENTSEL0 +17 , + +MSR_IA32_XSS ,MSR_IA32_U_CET ,MSR_IA32_S_CET , +MSR_IA32_PL0_SSP ,MSR_IA32_PL1_SSP ,MSR_IA32_PL2_SSP , + MSR_IA32_PL3_SSP, MSR_IA32_INT_SSP_TAB, MSR_KVM_GUEST_SSP, };static u32 msrs_to_save[ARRAY_SIZE (msrs_to_save_all)];
Signature · 1 line
2.17.2
PATCH v13 8/11 KVM: VMX: Enable CET support for nested VM
In reply to Yang WeijiangCET MSRs pass through guests for performance consideration. Configure the MSRs to match L0/L1 settings so that nested VM is able to run with CET.
Add assertions for vmcs12 offset table initialization, these assertions can detect the mismatch of VMCS field encoding and data type at compiling time.
--- arch/x86/kvm/vmx/nested.c | 34 +++++ arch/x86/kvm/vmx/vmcs12.c | 275 ++++++++++++++++++++++---------------- arch/x86/kvm/vmx/vmcs12.h | 14 +- arch/x86/kvm/vmx/vmx.c | 10 ++ 4 files changed, 220 insertions(+), 113 deletions(-)
arch/x86/kvm/vmx/nested.c +34 -0
@@ -555,6 +555,18 @@ static inline void enable_x2apic_msr_intercepts(unsigned long *msr_bitmap) } } +static void nested_vmx_update_intercept_for_msr (struct kvm_vcpu *vcpu, +u32 msr, +unsigned long *msr_bitmap_l1, +unsigned long *msr_bitmap_l0, +int type) +{ +if (!msr_write_intercepted_l01 (vcpu, msr)) +nested_vmx_disable_intercept_for_msr (msr_bitmap_l1, + msr_bitmap_l0, + msr, type); +} +/* * Merge L0's and L1's MSR bitmap, return false to indicate that * we do not use the hardware.
@@ -626,6 +638,28 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu,nested_vmx_disable_intercept_for_msr (msr_bitmap_l1, msr_bitmap_l0,MSR_KERNEL_GS_BASE ,MSR_TYPE_RW ); +/* Pass CET MSRs to nested VM if L0 and L1 are set to pass-through. */ +nested_vmx_update_intercept_for_msr (vcpu,MSR_IA32_U_CET , + msr_bitmap_l1, msr_bitmap_l0, +MSR_TYPE_RW ); +nested_vmx_update_intercept_for_msr (vcpu,MSR_IA32_PL3_SSP , + msr_bitmap_l1, msr_bitmap_l0, +MSR_TYPE_RW ); +nested_vmx_update_intercept_for_msr (vcpu,MSR_IA32_S_CET , + msr_bitmap_l1, msr_bitmap_l0, +MSR_TYPE_RW ); +nested_vmx_update_intercept_for_msr (vcpu,MSR_IA32_PL0_SSP , + msr_bitmap_l1, msr_bitmap_l0, +MSR_TYPE_RW ); +nested_vmx_update_intercept_for_msr (vcpu,MSR_IA32_PL1_SSP , + msr_bitmap_l1, msr_bitmap_l0, +MSR_TYPE_RW ); +nested_vmx_update_intercept_for_msr (vcpu,MSR_IA32_PL2_SSP , + msr_bitmap_l1, msr_bitmap_l0, +MSR_TYPE_RW ); +nested_vmx_update_intercept_for_msr (vcpu,MSR_IA32_INT_SSP_TAB , + msr_bitmap_l1, msr_bitmap_l0, +MSR_TYPE_RW );/* * Checking the L0->L1 bitmap is trying to verify two things: *
arch/x86/kvm/vmx/vmcs12.c +163 -112
288 lines not on this page · raw message
arch/x86/kvm/vmx/vmcs12.h +13 -1
@@ -118,7 +118,13 @@ struct __packed vmcs12 {natural_width host_ia32_sysenter_eip;natural_width host_rsp;natural_width host_rip; -natural_width paddingl[8 ];/* room for future expansion */ +natural_width host_s_cet; +natural_width host_ssp; +natural_width host_ssp_tbl; +natural_width guest_s_cet; +natural_width guest_ssp; +natural_width guest_ssp_tbl; +natural_width paddingl[2 ];/* room for future expansion */ u32 pin_based_vm_exec_control;u32 cpu_based_vm_exec_control;u32 exception_bitmap;
@@ -301,6 +307,12 @@ static inline void vmx_check_vmcs12_offsets(void)CHECK_OFFSET (host_ia32_sysenter_eip,656 );CHECK_OFFSET (host_rsp,664 );CHECK_OFFSET (host_rip,672 ); +CHECK_OFFSET (host_s_cet,680 ); +CHECK_OFFSET (host_ssp,688 ); +CHECK_OFFSET (host_ssp_tbl,696 ); +CHECK_OFFSET (guest_s_cet,704 ); +CHECK_OFFSET (guest_ssp,712 ); +CHECK_OFFSET (guest_ssp_tbl,720 );CHECK_OFFSET (pin_based_vm_exec_control,744 );CHECK_OFFSET (cpu_based_vm_exec_control,748 );CHECK_OFFSET (exception_bitmap,752 );
arch/x86/kvm/vmx/vmx.c +10 -0
@@ -7189,6 +7189,7 @@ static void nested_vmx_cr_fixed1_bits_update(struct kvm_vcpu *vcpu)cr4_fixed1_update (X86_CR4_PKE , ecx,feature_bit (PKU ));cr4_fixed1_update (X86_CR4_UMIP , ecx,feature_bit (UMIP ));cr4_fixed1_update (X86_CR4_LA57 , ecx,feature_bit (LA57 )); +cr4_fixed1_update (X86_CR4_CET , ecx,feature_bit (SHSTK ));#undef cr4_fixed1_update }
@@ -7208,6 +7209,15 @@ static void nested_vmx_entry_exit_ctls_update(struct kvm_vcpu *vcpu) vmx->nested.msrs.exit_ctls_high &= ~VM_EXIT_CLEAR_BNDCFGS ; } } + +if (is_cet_state_supported (vcpu,XFEATURE_MASK_CET_USER | +XFEATURE_MASK_CET_KERNEL )) { + vmx->nested.msrs.entry_ctls_high |=VM_ENTRY_LOAD_CET_STATE ; + vmx->nested.msrs.exit_ctls_high |=VM_EXIT_LOAD_CET_STATE ; + }else { + vmx->nested.msrs.entry_ctls_high &= ~VM_ENTRY_LOAD_CET_STATE ; + vmx->nested.msrs.exit_ctls_high &= ~VM_EXIT_LOAD_CET_STATE ; + } }static void update_intel_pt_cfg (struct kvm_vcpu *vcpu)
Signature · 1 line
2.17.2
PATCH v13 9/11 KVM: VMX: Add VMCS dump and sanity check for CET states
In reply to Yang WeijiangDump CET VMCS states for debug purpose. Since CET kernel protection is not enabled, if related MSRs in host are filled by mistake, warn once on detecting it.
--- arch/x86/kvm/vmx/vmx.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
arch/x86/kvm/vmx/vmx.c +23 -0
@@ -5941,6 +5941,12 @@ void dump_vmcs(void)pr_err ("InterruptStatus = %04x\n" ,vmcs_read16 (GUEST_INTR_STATUS )); +if (vmentry_ctl &VM_ENTRY_LOAD_CET_STATE ) { +pr_err ("S_CET = 0x%016lx\n" ,vmcs_readl (GUEST_S_CET )); +pr_err ("SSP = 0x%016lx\n" ,vmcs_readl (GUEST_SSP )); +pr_err ("SSP TABLE = 0x%016lx\n" , +vmcs_readl (GUEST_INTR_SSP_TABLE )); + }pr_err ("*** Host State ***\n" );pr_err ("RIP = 0x%016lx RSP = 0x%016lx\n" ,vmcs_readl (HOST_RIP ),vmcs_readl (HOST_RSP ));
@@ -6023,6 +6029,12 @@ void dump_vmcs(void)if (secondary_exec_control &SECONDARY_EXEC_ENABLE_VPID )pr_err ("Virtual processor ID = 0x%04x\n" ,vmcs_read16 (VIRTUAL_PROCESSOR_ID )); +if (vmexit_ctl &VM_EXIT_LOAD_CET_STATE ) { +pr_err ("S_CET = 0x%016lx\n" ,vmcs_readl (HOST_S_CET )); +pr_err ("SSP = 0x%016lx\n" ,vmcs_readl (HOST_SSP )); +pr_err ("SSP TABLE = 0x%016lx\n" , +vmcs_readl (HOST_INTR_SSP_TABLE )); + } }/*
@@ -8075,6 +8087,7 @@ static __init int hardware_setup(void)unsigned long host_bndcfgs;struct desc_ptr dt;int r, i, ept_lpage_level; +u64 cet_msr;store_idt (&dt); host_idt_base = dt.address;
@@ -8236,6 +8249,16 @@ static __init int hardware_setup(void)return r; } +if (boot_cpu_has (X86_FEATURE_IBT ) ||boot_cpu_has (X86_FEATURE_SHSTK )) { +rdmsrl (MSR_IA32_S_CET , cet_msr); +WARN_ONCE (cet_msr,"KVM: CET S_CET in host will be lost!\n" ); + } + +if (boot_cpu_has (X86_FEATURE_SHSTK )) { +rdmsrl (MSR_IA32_PL0_SSP , cet_msr); +WARN_ONCE (cet_msr,"KVM: CET PL0_SSP in host will be lost!\n" ); + } +vmx_set_cpu_caps (); r =alloc_kvm_area ();
Signature · 1 line
2.17.2
PATCH v13 10/11 KVM: x86: Add #CP support in guest exception dispatch
In reply to Yang WeijiangCPU defined #CP(21) to handle CET induced exception, it's accompanied with several error codes corresponding to different CET violation cases, see SDM for detailed description. The exception is classified as a contibutory exception w.r.t #DF.
--- arch/x86/include/uapi/asm/kvm.h | 1 + arch/x86/kvm/x86.c | 1 + arch/x86/kvm/x86.h | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-)
arch/x86/include/uapi/asm/kvm.h +1 -0
@@ -31,6 +31,7 @@#define MC_VECTOR 18#define XM_VECTOR 19#define VE_VECTOR 20 +#define CP_VECTOR 21/* Select x86 specific features in <linux/kvm.h> */ #define __KVM_HAVE_PIT
arch/x86/kvm/x86.c +1 -0
@@ -407,6 +407,7 @@ static int exception_class(int vector)case NP_VECTOR :case SS_VECTOR :case GP_VECTOR : +case CP_VECTOR :return EXCPT_CONTRIBUTORY ;default :break ;
arch/x86/kvm/x86.h +1 -1
@@ -115,7 +115,7 @@ static inline bool x86_exception_has_error_code(unsigned int vector) {static u32 exception_has_error_code =BIT (DF_VECTOR ) |BIT (TS_VECTOR ) |BIT (NP_VECTOR ) |BIT (SS_VECTOR ) |BIT (GP_VECTOR ) | -BIT (PF_VECTOR ) |BIT (AC_VECTOR ); +BIT (PF_VECTOR ) |BIT (AC_VECTOR ) |BIT (CP_VECTOR );return (1U << vector) & exception_has_error_code; }
Signature · 1 line
2.17.2
PATCH v13 11/11 KVM: x86: Enable CET virtualization and advertise CET to userspace
In reply to Yang WeijiangSet the feature bits so that CET capabilities can be seen in guest via CPUID enumeration. Add CR4.CET bit support in order to allow guest set CET master control bit(CR4.CET).
Disable KVM CET feature once unrestricted_guest is turned off because KVM cannot emulate guest CET behavior well in this case.
--- arch/x86/include/asm/kvm_host.h | 3 ++- arch/x86/kvm/cpuid.c | 5 +++-- arch/x86/kvm/vmx/vmx.c | 5 +++++ arch/x86/kvm/x86.c | 5 +++++ 4 files changed, 15 insertions(+), 3 deletions(-)
arch/x86/include/asm/kvm_host.h +2 -1
@@ -95,7 +95,8 @@ | X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR | X86_CR4_PCIDE \ | X86_CR4_OSXSAVE | X86_CR4_SMEP | X86_CR4_FSGSBASE \ | X86_CR4_OSXMMEXCPT | X86_CR4_LA57 | X86_CR4_VMXE \ - | X86_CR4_SMAP | X86_CR4_PKE | X86_CR4_UMIP)) + | X86_CR4_SMAP | X86_CR4_PKE | X86_CR4_UMIP \ + | X86_CR4_CET))#define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR)
arch/x86/kvm/cpuid.c +3 -2
@@ -344,7 +344,8 @@ void kvm_set_cpu_caps(void)F (AVX512VBMI ) |F (LA57 ) |0 /*PKU*/ |0 /*OSPKE*/ |F (RDPID ) |F (AVX512_VPOPCNTDQ ) |F (UMIP ) |F (AVX512_VBMI2 ) |F (GFNI ) |F (VAES ) |F (VPCLMULQDQ ) |F (AVX512_VNNI ) |F (AVX512_BITALG ) | -F (CLDEMOTE ) |F (MOVDIRI ) |F (MOVDIR64B ) |0 /*WAITPKG*/ +F (CLDEMOTE ) |F (MOVDIRI ) |F (MOVDIR64B ) |0 /*WAITPKG*/ | +F (SHSTK ) );/* Set LA57 based on hardware capability. */ if (cpuid_ecx (7 ) &F (LA57 ))
@@ -353,7 +354,7 @@ void kvm_set_cpu_caps(void)kvm_cpu_cap_mask (CPUID_7_EDX ,F (AVX512_4VNNIW ) |F (AVX512_4FMAPS ) |F (SPEC_CTRL ) |F (SPEC_CTRL_SSBD ) |F (ARCH_CAPABILITIES ) |F (INTEL_STIBP ) | -F (MD_CLEAR ) |F (AVX512_VP2INTERSECT ) |F (FSRM ) +F (MD_CLEAR ) |F (AVX512_VP2INTERSECT ) |F (FSRM ) |F (IBT ) );/* TSC_ADJUST and ARCH_CAPABILITIES are emulated in software. */
arch/x86/kvm/vmx/vmx.c +5 -0
@@ -7411,6 +7411,11 @@ static __init void vmx_set_cpu_caps(void)/* CPUID 0x80000001 */ if (!cpu_has_vmx_rdtscp ())kvm_cpu_cap_clear (X86_FEATURE_RDTSCP ); + +if (!enable_unrestricted_guest) { +kvm_cpu_cap_clear (X86_FEATURE_SHSTK ); +kvm_cpu_cap_clear (X86_FEATURE_IBT ); + } }static void vmx_request_immediate_exit (struct kvm_vcpu *vcpu)
arch/x86/kvm/x86.c +5 -0
@@ -9707,6 +9707,11 @@ int kvm_arch_hardware_setup(void *opaque)if (kvm_cpu_cap_has (X86_FEATURE_XSAVES )) supported_xss = host_xss &KVM_SUPPORTED_XSS ; +if (!kvm_cpu_cap_has (X86_FEATURE_SHSTK ) && + !kvm_cpu_cap_has (X86_FEATURE_IBT )) + supported_xss &= ~(XFEATURE_MASK_CET_USER | +XFEATURE_MASK_CET_KERNEL ); + cr4_reserved_bits =kvm_host_cr4_reserved_bits (&boot_cpu_data);if (kvm_has_tsc_control) {
Signature · 1 line
2.17.2
Quoted 11 lines · Yang Weijiang
Control-flow Enforcement Technology (CET) provides protection against Return/Jump-Oriented Programming (ROP/JOP) attack. There're two CET
sub-features: Shadow Stack (SHSTK) and Indirect Branch Tracking (IBT). SHSTK is to prevent ROP programming and IBT is to prevent JOP programming.Several parts in KVM have been updated to provide VM CET support, including:
CPUID/XSAVES config, MSR pass-through, user space MSR access interface, vmentry/vmexit config, nested VM etc. These patches have dependency on CET kernel patches for xsaves support and CET definitions, e.g., MSR and related feature flags.
Quoted 8 lines
CET kernel patches are here:
https://lkml.kernel.org/r/[email protected]v13:
- Added CET definitions as a separate patch to facilitate KVM test.
- Disabled CET support in KVM ifunrestricted_guestis turned off since in this case CET related instructions/infrastructure cannot be emulated well.
This needs to be rebased, I can't get it to apply on any kvm branch nor on any 5.8 rc. And when you send series, especially large series that touch lots of code, please explicitly state what commit the series is based on to make it easy for reviewers to apply the patches, even if the series needs a rebase.
Quoted 21 lines · Sean Christopherson
Quoted 11 lines · Yang Weijiang
Control-flow Enforcement Technology (CET) provides protection against Return/Jump-Oriented Programming (ROP/JOP) attack. There're two CET
sub-features: Shadow Stack (SHSTK) and Indirect Branch Tracking (IBT). SHSTK is to prevent ROP programming and IBT is to prevent JOP programming.Several parts in KVM have been updated to provide VM CET support, including:
CPUID/XSAVES config, MSR pass-through, user space MSR access interface, vmentry/vmexit config, nested VM etc. These patches have dependency on CET kernel patches for xsaves support and CET definitions, e.g., MSR and related feature flags.Quoted 8 lines
CET kernel patches are here:
https://lkml.kernel.org/r/[email protected]v13:
- Added CET definitions as a separate patch to facilitate KVM test.
- Disabled CET support in KVM ifunrestricted_guestis turned off since in this case CET related instructions/infrastructure cannot be emulated well.
Quoted 5 lines
This needs to be rebased, I can't get it to apply on any kvm branch nor on any 5.8 rc. And when you send series, especially large series that touch lots of code, please explicitly state what commit the series is based on to make it easy for reviewers to apply the patches, even if the series needs a rebase.
Sorry for the inconvenience, I'll rebase and resend this series.