Skip to content

Commit 6258849

Browse files
yang-weijiangsean-jc
authored andcommitted
KVM: nVMX: Prepare for enabling CET support for nested guest
Set up CET MSRs, related VM_ENTRY/EXIT control bits and fixed CR4 setting to enable CET for nested VM. vmcs12 and vmcs02 needs to be synced when L2 exits to L1 or when L1 wants to resume L2, that way correct CET states can be observed by one another. Please note that consistency checks regarding CET state during VM-Entry will be added later to prevent this patch from becoming too large. Advertising the new CET VM_ENTRY/EXIT control bits are also be deferred until after the consistency checks are added. Signed-off-by: Yang Weijiang <weijiang.yang@intel.com> Tested-by: Mathias Krause <minipli@grsecurity.net> Tested-by: John Allen <john.allen@amd.com> Tested-by: Rick Edgecombe <rick.p.edgecombe@intel.com> Signed-off-by: Chao Gao <chao.gao@intel.com> Reviewed-by: Xin Li (Intel) <xin@zytor.com> Tested-by: Xin Li (Intel) <xin@zytor.com> Link: https://lore.kernel.org/r/20250919223258.1604852-32-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 033cc16 commit 6258849

5 files changed

Lines changed: 101 additions & 1 deletion

File tree

arch/x86/kvm/vmx/nested.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,24 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu,
721721
nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0,
722722
MSR_IA32_MPERF, MSR_TYPE_R);
723723

724+
nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0,
725+
MSR_IA32_U_CET, MSR_TYPE_RW);
726+
727+
nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0,
728+
MSR_IA32_S_CET, MSR_TYPE_RW);
729+
730+
nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0,
731+
MSR_IA32_PL0_SSP, MSR_TYPE_RW);
732+
733+
nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0,
734+
MSR_IA32_PL1_SSP, MSR_TYPE_RW);
735+
736+
nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0,
737+
MSR_IA32_PL2_SSP, MSR_TYPE_RW);
738+
739+
nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0,
740+
MSR_IA32_PL3_SSP, MSR_TYPE_RW);
741+
724742
kvm_vcpu_unmap(vcpu, &map);
725743

726744
vmx->nested.force_msr_bitmap_recalc = false;
@@ -2521,6 +2539,32 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct loaded_vmcs *vmcs0
25212539
}
25222540
}
25232541

2542+
static void vmcs_read_cet_state(struct kvm_vcpu *vcpu, u64 *s_cet,
2543+
u64 *ssp, u64 *ssp_tbl)
2544+
{
2545+
if (guest_cpu_cap_has(vcpu, X86_FEATURE_IBT) ||
2546+
guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK))
2547+
*s_cet = vmcs_readl(GUEST_S_CET);
2548+
2549+
if (guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK)) {
2550+
*ssp = vmcs_readl(GUEST_SSP);
2551+
*ssp_tbl = vmcs_readl(GUEST_INTR_SSP_TABLE);
2552+
}
2553+
}
2554+
2555+
static void vmcs_write_cet_state(struct kvm_vcpu *vcpu, u64 s_cet,
2556+
u64 ssp, u64 ssp_tbl)
2557+
{
2558+
if (guest_cpu_cap_has(vcpu, X86_FEATURE_IBT) ||
2559+
guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK))
2560+
vmcs_writel(GUEST_S_CET, s_cet);
2561+
2562+
if (guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK)) {
2563+
vmcs_writel(GUEST_SSP, ssp);
2564+
vmcs_writel(GUEST_INTR_SSP_TABLE, ssp_tbl);
2565+
}
2566+
}
2567+
25242568
static void prepare_vmcs02_rare(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12)
25252569
{
25262570
struct hv_enlightened_vmcs *hv_evmcs = nested_vmx_evmcs(vmx);
@@ -2637,6 +2681,10 @@ static void prepare_vmcs02_rare(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12)
26372681
vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr);
26382682
vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr);
26392683

2684+
if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_CET_STATE)
2685+
vmcs_write_cet_state(&vmx->vcpu, vmcs12->guest_s_cet,
2686+
vmcs12->guest_ssp, vmcs12->guest_ssp_tbl);
2687+
26402688
set_cr4_guest_host_mask(vmx);
26412689
}
26422690

@@ -2676,6 +2724,13 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
26762724
kvm_set_dr(vcpu, 7, vcpu->arch.dr7);
26772725
vmx_guest_debugctl_write(vcpu, vmx->nested.pre_vmenter_debugctl);
26782726
}
2727+
2728+
if (!vmx->nested.nested_run_pending ||
2729+
!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_CET_STATE))
2730+
vmcs_write_cet_state(vcpu, vmx->nested.pre_vmenter_s_cet,
2731+
vmx->nested.pre_vmenter_ssp,
2732+
vmx->nested.pre_vmenter_ssp_tbl);
2733+
26792734
if (kvm_mpx_supported() && (!vmx->nested.nested_run_pending ||
26802735
!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS)))
26812736
vmcs_write64(GUEST_BNDCFGS, vmx->nested.pre_vmenter_bndcfgs);
@@ -3551,6 +3606,12 @@ enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu,
35513606
!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS)))
35523607
vmx->nested.pre_vmenter_bndcfgs = vmcs_read64(GUEST_BNDCFGS);
35533608

3609+
if (!vmx->nested.nested_run_pending ||
3610+
!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_CET_STATE))
3611+
vmcs_read_cet_state(vcpu, &vmx->nested.pre_vmenter_s_cet,
3612+
&vmx->nested.pre_vmenter_ssp,
3613+
&vmx->nested.pre_vmenter_ssp_tbl);
3614+
35543615
/*
35553616
* Overwrite vmcs01.GUEST_CR3 with L1's CR3 if EPT is disabled *and*
35563617
* nested early checks are disabled. In the event of a "late" VM-Fail,
@@ -4634,6 +4695,10 @@ static void sync_vmcs02_to_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
46344695

46354696
if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_IA32_EFER)
46364697
vmcs12->guest_ia32_efer = vcpu->arch.efer;
4698+
4699+
vmcs_read_cet_state(&vmx->vcpu, &vmcs12->guest_s_cet,
4700+
&vmcs12->guest_ssp,
4701+
&vmcs12->guest_ssp_tbl);
46374702
}
46384703

46394704
/*
@@ -4759,6 +4824,18 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
47594824
if (vmcs12->vm_exit_controls & VM_EXIT_CLEAR_BNDCFGS)
47604825
vmcs_write64(GUEST_BNDCFGS, 0);
47614826

4827+
/*
4828+
* Load CET state from host state if VM_EXIT_LOAD_CET_STATE is set.
4829+
* otherwise CET state should be retained across VM-exit, i.e.,
4830+
* guest values should be propagated from vmcs12 to vmcs01.
4831+
*/
4832+
if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_CET_STATE)
4833+
vmcs_write_cet_state(vcpu, vmcs12->host_s_cet, vmcs12->host_ssp,
4834+
vmcs12->host_ssp_tbl);
4835+
else
4836+
vmcs_write_cet_state(vcpu, vmcs12->guest_s_cet, vmcs12->guest_ssp,
4837+
vmcs12->guest_ssp_tbl);
4838+
47624839
if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_PAT) {
47634840
vmcs_write64(GUEST_IA32_PAT, vmcs12->host_ia32_pat);
47644841
vcpu->arch.pat = vmcs12->host_ia32_pat;

arch/x86/kvm/vmx/vmcs12.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ const unsigned short vmcs12_field_offsets[] = {
139139
FIELD(GUEST_PENDING_DBG_EXCEPTIONS, guest_pending_dbg_exceptions),
140140
FIELD(GUEST_SYSENTER_ESP, guest_sysenter_esp),
141141
FIELD(GUEST_SYSENTER_EIP, guest_sysenter_eip),
142+
FIELD(GUEST_S_CET, guest_s_cet),
143+
FIELD(GUEST_SSP, guest_ssp),
144+
FIELD(GUEST_INTR_SSP_TABLE, guest_ssp_tbl),
142145
FIELD(HOST_CR0, host_cr0),
143146
FIELD(HOST_CR3, host_cr3),
144147
FIELD(HOST_CR4, host_cr4),
@@ -151,5 +154,8 @@ const unsigned short vmcs12_field_offsets[] = {
151154
FIELD(HOST_IA32_SYSENTER_EIP, host_ia32_sysenter_eip),
152155
FIELD(HOST_RSP, host_rsp),
153156
FIELD(HOST_RIP, host_rip),
157+
FIELD(HOST_S_CET, host_s_cet),
158+
FIELD(HOST_SSP, host_ssp),
159+
FIELD(HOST_INTR_SSP_TABLE, host_ssp_tbl),
154160
};
155161
const unsigned int nr_vmcs12_fields = ARRAY_SIZE(vmcs12_field_offsets);

arch/x86/kvm/vmx/vmcs12.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,13 @@ struct __packed vmcs12 {
117117
natural_width host_ia32_sysenter_eip;
118118
natural_width host_rsp;
119119
natural_width host_rip;
120-
natural_width paddingl[8]; /* room for future expansion */
120+
natural_width host_s_cet;
121+
natural_width host_ssp;
122+
natural_width host_ssp_tbl;
123+
natural_width guest_s_cet;
124+
natural_width guest_ssp;
125+
natural_width guest_ssp_tbl;
126+
natural_width paddingl[2]; /* room for future expansion */
121127
u32 pin_based_vm_exec_control;
122128
u32 cpu_based_vm_exec_control;
123129
u32 exception_bitmap;
@@ -294,6 +300,12 @@ static inline void vmx_check_vmcs12_offsets(void)
294300
CHECK_OFFSET(host_ia32_sysenter_eip, 656);
295301
CHECK_OFFSET(host_rsp, 664);
296302
CHECK_OFFSET(host_rip, 672);
303+
CHECK_OFFSET(host_s_cet, 680);
304+
CHECK_OFFSET(host_ssp, 688);
305+
CHECK_OFFSET(host_ssp_tbl, 696);
306+
CHECK_OFFSET(guest_s_cet, 704);
307+
CHECK_OFFSET(guest_ssp, 712);
308+
CHECK_OFFSET(guest_ssp_tbl, 720);
297309
CHECK_OFFSET(pin_based_vm_exec_control, 744);
298310
CHECK_OFFSET(cpu_based_vm_exec_control, 748);
299311
CHECK_OFFSET(exception_bitmap, 752);

arch/x86/kvm/vmx/vmx.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7735,6 +7735,8 @@ static void nested_vmx_cr_fixed1_bits_update(struct kvm_vcpu *vcpu)
77357735
cr4_fixed1_update(X86_CR4_PKE, ecx, feature_bit(PKU));
77367736
cr4_fixed1_update(X86_CR4_UMIP, ecx, feature_bit(UMIP));
77377737
cr4_fixed1_update(X86_CR4_LA57, ecx, feature_bit(LA57));
7738+
cr4_fixed1_update(X86_CR4_CET, ecx, feature_bit(SHSTK));
7739+
cr4_fixed1_update(X86_CR4_CET, edx, feature_bit(IBT));
77387740

77397741
entry = kvm_find_cpuid_entry_index(vcpu, 0x7, 1);
77407742
cr4_fixed1_update(X86_CR4_LAM_SUP, eax, feature_bit(LAM));

arch/x86/kvm/vmx/vmx.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ struct nested_vmx {
181181
*/
182182
u64 pre_vmenter_debugctl;
183183
u64 pre_vmenter_bndcfgs;
184+
u64 pre_vmenter_s_cet;
185+
u64 pre_vmenter_ssp;
186+
u64 pre_vmenter_ssp_tbl;
184187

185188
/* to migrate it to L1 if L2 writes to L1's CR8 directly */
186189
int l1_tpr_threshold;

0 commit comments

Comments
 (0)