Skip to content

Commit 9df398f

Browse files
xinli-intelsean-jc
authored andcommitted
KVM: VMX: Track CPU's MSR_IA32_VMX_BASIC as a single 64-bit value
Track the "basic" capabilities VMX MSR as a single u64 in vmcs_config instead of splitting it across three fields, that obviously don't combine into a single 64-bit value, so that KVM can use the macros that define MSR bits using their absolute position. Replace all open coded shifts and masks, many of which are relative to the "high" half, with the appropriate macro. Opportunistically use VMX_BASIC_32BIT_PHYS_ADDR_ONLY instead of an open coded equivalent, and clean up the related comment to not reference a specific SDM section (to the surprise of no one, the comment is stale). No functional change intended (though obviously the code generation will be quite different). Cc: Shan Kang <shan.kang@intel.com> Cc: Kai Huang <kai.huang@intel.com> Signed-off-by: Xin Li <xin3.li@intel.com> [sean: split to separate patch, write changelog] Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com> Reviewed-by: Kai Huang <kai.huang@intel.com> Reviewed-by: Zhao Liu <zhao1.liu@intel.com> Link: https://lore.kernel.org/r/20240605231918.2915961-6-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent d7bfc9f commit 9df398f

File tree

3 files changed

+21
-18
lines changed

3 files changed

+21
-18
lines changed

arch/x86/include/asm/vmx.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,11 @@ static inline u32 vmx_basic_vmcs_size(u64 vmx_basic)
152152
return (vmx_basic & GENMASK_ULL(44, 32)) >> 32;
153153
}
154154

155+
static inline u32 vmx_basic_vmcs_mem_type(u64 vmx_basic)
156+
{
157+
return (vmx_basic & GENMASK_ULL(53, 50)) >> 50;
158+
}
159+
155160
static inline int vmx_misc_preemption_timer_rate(u64 vmx_misc)
156161
{
157162
return vmx_misc & VMX_MISC_PREEMPTION_TIMER_RATE_MASK;

arch/x86/kvm/vmx/capabilities.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,7 @@ struct nested_vmx_msrs {
5454
};
5555

5656
struct vmcs_config {
57-
int size;
58-
u32 basic_cap;
59-
u32 revision_id;
57+
u64 basic;
6058
u32 pin_based_exec_ctrl;
6159
u32 cpu_based_exec_ctrl;
6260
u32 cpu_based_2nd_exec_ctrl;
@@ -76,7 +74,7 @@ extern struct vmx_capability vmx_capability __ro_after_init;
7674

7775
static inline bool cpu_has_vmx_basic_inout(void)
7876
{
79-
return (((u64)vmcs_config.basic_cap << 32) & VMX_BASIC_INOUT);
77+
return vmcs_config.basic & VMX_BASIC_INOUT;
8078
}
8179

8280
static inline bool cpu_has_virtual_nmis(void)

arch/x86/kvm/vmx/vmx.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2605,13 +2605,13 @@ static u64 adjust_vmx_controls64(u64 ctl_opt, u32 msr)
26052605
static int setup_vmcs_config(struct vmcs_config *vmcs_conf,
26062606
struct vmx_capability *vmx_cap)
26072607
{
2608-
u32 vmx_msr_low, vmx_msr_high;
26092608
u32 _pin_based_exec_control = 0;
26102609
u32 _cpu_based_exec_control = 0;
26112610
u32 _cpu_based_2nd_exec_control = 0;
26122611
u64 _cpu_based_3rd_exec_control = 0;
26132612
u32 _vmexit_control = 0;
26142613
u32 _vmentry_control = 0;
2614+
u64 basic_msr;
26152615
u64 misc_msr;
26162616
int i;
26172617

@@ -2734,29 +2734,29 @@ static int setup_vmcs_config(struct vmcs_config *vmcs_conf,
27342734
_vmexit_control &= ~x_ctrl;
27352735
}
27362736

2737-
rdmsr(MSR_IA32_VMX_BASIC, vmx_msr_low, vmx_msr_high);
2737+
rdmsrl(MSR_IA32_VMX_BASIC, basic_msr);
27382738

27392739
/* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */
2740-
if ((vmx_msr_high & 0x1fff) > PAGE_SIZE)
2740+
if (vmx_basic_vmcs_size(basic_msr) > PAGE_SIZE)
27412741
return -EIO;
27422742

27432743
#ifdef CONFIG_X86_64
2744-
/* IA-32 SDM Vol 3B: 64-bit CPUs always have VMX_BASIC_MSR[48]==0. */
2745-
if (vmx_msr_high & (1u<<16))
2744+
/*
2745+
* KVM expects to be able to shove all legal physical addresses into
2746+
* VMCS fields for 64-bit kernels, and per the SDM, "This bit is always
2747+
* 0 for processors that support Intel 64 architecture".
2748+
*/
2749+
if (basic_msr & VMX_BASIC_32BIT_PHYS_ADDR_ONLY)
27462750
return -EIO;
27472751
#endif
27482752

27492753
/* Require Write-Back (WB) memory type for VMCS accesses. */
2750-
if (((vmx_msr_high >> 18) & 15) != X86_MEMTYPE_WB)
2754+
if (vmx_basic_vmcs_mem_type(basic_msr) != X86_MEMTYPE_WB)
27512755
return -EIO;
27522756

27532757
rdmsrl(MSR_IA32_VMX_MISC, misc_msr);
27542758

2755-
vmcs_conf->size = vmx_msr_high & 0x1fff;
2756-
vmcs_conf->basic_cap = vmx_msr_high & ~0x1fff;
2757-
2758-
vmcs_conf->revision_id = vmx_msr_low;
2759-
2759+
vmcs_conf->basic = basic_msr;
27602760
vmcs_conf->pin_based_exec_ctrl = _pin_based_exec_control;
27612761
vmcs_conf->cpu_based_exec_ctrl = _cpu_based_exec_control;
27622762
vmcs_conf->cpu_based_2nd_exec_ctrl = _cpu_based_2nd_exec_control;
@@ -2903,13 +2903,13 @@ struct vmcs *alloc_vmcs_cpu(bool shadow, int cpu, gfp_t flags)
29032903
if (!pages)
29042904
return NULL;
29052905
vmcs = page_address(pages);
2906-
memset(vmcs, 0, vmcs_config.size);
2906+
memset(vmcs, 0, vmx_basic_vmcs_size(vmcs_config.basic));
29072907

29082908
/* KVM supports Enlightened VMCS v1 only */
29092909
if (kvm_is_using_evmcs())
29102910
vmcs->hdr.revision_id = KVM_EVMCS_VERSION;
29112911
else
2912-
vmcs->hdr.revision_id = vmcs_config.revision_id;
2912+
vmcs->hdr.revision_id = vmx_basic_vmcs_revision_id(vmcs_config.basic);
29132913

29142914
if (shadow)
29152915
vmcs->hdr.shadow_vmcs = 1;
@@ -3002,7 +3002,7 @@ static __init int alloc_kvm_area(void)
30023002
* physical CPU.
30033003
*/
30043004
if (kvm_is_using_evmcs())
3005-
vmcs->hdr.revision_id = vmcs_config.revision_id;
3005+
vmcs->hdr.revision_id = vmx_basic_vmcs_revision_id(vmcs_config.basic);
30063006

30073007
per_cpu(vmxarea, cpu) = vmcs;
30083008
}

0 commit comments

Comments
 (0)