[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