[LTP] [PATCH 3/5] KVM: Simplify reading VMX control field masks
Martin Doucha
mdoucha@suse.cz
Mon Apr 7 16:23:47 CEST 2025
Some VMX control fields have two different MSRs holding supported bit
masks. Add a helper function to read the correct MSR.
Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
testcases/kernel/kvm/include/kvm_x86_vmx.h | 10 +++++
testcases/kernel/kvm/kvm_vmx01.c | 7 +---
testcases/kernel/kvm/lib_x86.c | 48 +++++++++++++++++-----
3 files changed, 49 insertions(+), 16 deletions(-)
diff --git a/testcases/kernel/kvm/include/kvm_x86_vmx.h b/testcases/kernel/kvm/include/kvm_x86_vmx.h
index 180a114e7..92e3c683e 100644
--- a/testcases/kernel/kvm/include/kvm_x86_vmx.h
+++ b/testcases/kernel/kvm/include/kvm_x86_vmx.h
@@ -28,6 +28,15 @@
#define MSR_IA32_VMX_EXECCTL_MASK2 0x48e
#define MSR_IA32_VMX_EXITCTL_MASK2 0x48f
#define MSR_IA32_VMX_ENTRYCTL_MASK2 0x490
+#define MSR_IA32_VMX_EXECCTL3_MASK 0x492
+
+#define VMX_CTLMASK_PINX 0
+#define VMX_CTLMASK_EXECCTL 1
+#define VMX_CTLMASK_EXECCTL2 2
+#define VMX_CTLMASK_EXECCTL3 3
+#define VMX_CTLMASK_EXITCTL 4
+#define VMX_CTLMASK_ENTRYCTL 5
+#define VMX_CTLMASK_MAX 6
#define IA32FC_LOCK (1 << 0)
#define IA32FC_VMXON_SMX (1 << 1)
@@ -174,6 +183,7 @@ struct kvm_vmcs *kvm_alloc_vmcs(void);
void kvm_vmcs_copy_gdt_descriptor(unsigned int gdt_id,
unsigned long vmcs_selector, unsigned long vmcs_flags,
unsigned long vmcs_limit, unsigned long vmcs_baseaddr);
+uint64_t kvm_vmx_read_vmctl_mask(unsigned int ctl_id);
void kvm_init_vmx_vcpu(struct kvm_vmx_vcpu *cpu, uint16_t ss, void *rsp,
int (*guest_main)(void));
struct kvm_vmx_vcpu *kvm_create_vmx_vcpu(int (*guest_main)(void),
diff --git a/testcases/kernel/kvm/kvm_vmx01.c b/testcases/kernel/kvm/kvm_vmx01.c
index 31ad75137..5bffbe946 100644
--- a/testcases/kernel/kvm/kvm_vmx01.c
+++ b/testcases/kernel/kvm/kvm_vmx01.c
@@ -152,10 +152,7 @@ void main(void)
kvm_set_vmx_state(1);
/* Check secondary VMCS execctl support */
- if (kvm_rdmsr(MSR_IA32_VMX_BASIC) & IA32_VMXBASIC_USELESS_CTL_MASKS)
- val = kvm_rdmsr(MSR_IA32_VMX_EXECCTL_MASK2);
- else
- val = kvm_rdmsr(MSR_IA32_VMX_EXECCTL_MASK);
+ val = kvm_vmx_read_vmctl_mask(VMX_CTLMASK_EXECCTL);
if (!((val >> 32) & VMX_EXECCTL_ENABLE_CTL2))
tst_brk(TCONF, "CPU does not support shadow VMCS");
@@ -169,7 +166,7 @@ void main(void)
val = kvm_vmx_vmread(VMX_VMCS_VMEXEC_CTL);
val |= VMX_EXECCTL_ENABLE_CTL2;
kvm_vmx_vmwrite(VMX_VMCS_VMEXEC_CTL, val);
- val = kvm_rdmsr(MSR_IA32_VMX_EXECCTL2_MASK);
+ val = kvm_vmx_read_vmctl_mask(VMX_CTLMASK_EXECCTL2);
if (!((val >> 32) & VMX_EXECCTL2_SHADOW_VMCS))
tst_brk(TCONF, "CPU does not support shadow VMCS");
diff --git a/testcases/kernel/kvm/lib_x86.c b/testcases/kernel/kvm/lib_x86.c
index e6acc0797..c3363e033 100644
--- a/testcases/kernel/kvm/lib_x86.c
+++ b/testcases/kernel/kvm/lib_x86.c
@@ -119,6 +119,24 @@ static const char *vmx_error_description[VMX_VMINST_ERR_COUNT] = {
"Invalid operand to INVEPT/INVVPID"
};
+static const unsigned int vmx_ctl_masks_old[VMX_CTLMASK_MAX] = {
+ MSR_IA32_VMX_PINX_MASK,
+ MSR_IA32_VMX_EXECCTL_MASK,
+ MSR_IA32_VMX_EXECCTL2_MASK,
+ MSR_IA32_VMX_EXECCTL3_MASK,
+ MSR_IA32_VMX_EXITCTL_MASK,
+ MSR_IA32_VMX_ENTRYCTL_MASK
+};
+
+static const unsigned int vmx_ctl_masks_new[VMX_CTLMASK_MAX] = {
+ MSR_IA32_VMX_PINX_MASK2,
+ MSR_IA32_VMX_EXECCTL_MASK2,
+ MSR_IA32_VMX_EXECCTL2_MASK,
+ MSR_IA32_VMX_EXECCTL3_MASK,
+ MSR_IA32_VMX_EXITCTL_MASK2,
+ MSR_IA32_VMX_ENTRYCTL_MASK2
+};
+
static void kvm_set_intr_handler(unsigned int id, uintptr_t func)
{
memset(kvm_idt + id, 0, sizeof(kvm_idt[0]));
@@ -711,6 +729,21 @@ void kvm_vmcs_copy_gdt_descriptor(unsigned int gdt_id,
kvm_vmx_vmwrite(vmcs_baseaddr, baseaddr);
}
+uint64_t kvm_vmx_read_vmctl_mask(unsigned int ctl_id)
+{
+ unsigned int msr;
+
+ if (ctl_id >= VMX_CTLMASK_MAX)
+ tst_brk(TBROK, "Invalid VMX control ID %u", ctl_id);
+
+ if (kvm_rdmsr(MSR_IA32_VMX_BASIC) & IA32_VMXBASIC_USELESS_CTL_MASKS)
+ msr = vmx_ctl_masks_new[ctl_id];
+ else
+ msr = vmx_ctl_masks_old[ctl_id];
+
+ return kvm_rdmsr(msr);
+}
+
void kvm_init_vmx_vcpu(struct kvm_vmx_vcpu *cpu, uint16_t ss, void *rsp,
int (*guest_main)(void))
{
@@ -730,17 +763,10 @@ void kvm_init_vmx_vcpu(struct kvm_vmx_vcpu *cpu, uint16_t ss, void *rsp,
kvm_vmx_vmptrld(cpu->vmcs);
/* Configure VM execution control fields */
- if (kvm_rdmsr(MSR_IA32_VMX_BASIC) & IA32_VMXBASIC_USELESS_CTL_MASKS) {
- pinxctl = (uint32_t)kvm_rdmsr(MSR_IA32_VMX_PINX_MASK2);
- execctl = (uint32_t)kvm_rdmsr(MSR_IA32_VMX_EXECCTL_MASK2);
- exitctl = (uint32_t)kvm_rdmsr(MSR_IA32_VMX_EXITCTL_MASK2);
- entryctl = (uint32_t)kvm_rdmsr(MSR_IA32_VMX_ENTRYCTL_MASK2);
- } else {
- pinxctl = (uint32_t)kvm_rdmsr(MSR_IA32_VMX_PINX_MASK);
- execctl = (uint32_t)kvm_rdmsr(MSR_IA32_VMX_EXECCTL_MASK);
- exitctl = (uint32_t)kvm_rdmsr(MSR_IA32_VMX_EXITCTL_MASK);
- entryctl = (uint32_t)kvm_rdmsr(MSR_IA32_VMX_ENTRYCTL_MASK);
- }
+ pinxctl = (uint32_t)kvm_vmx_read_vmctl_mask(VMX_CTLMASK_PINX);
+ execctl = (uint32_t)kvm_vmx_read_vmctl_mask(VMX_CTLMASK_EXECCTL);
+ exitctl = (uint32_t)kvm_vmx_read_vmctl_mask(VMX_CTLMASK_EXITCTL);
+ entryctl = (uint32_t)kvm_vmx_read_vmctl_mask(VMX_CTLMASK_ENTRYCTL);
execctl |= VMX_INTERCEPT_HLT;
--
2.49.0
More information about the ltp
mailing list