* [LTP] [PATCH 1/5] kvm_vmx01: Fix 32bit compiler warnings
2025-04-07 14:23 [LTP] [PATCH 0/5] KVM test for Intel VMX vAPIC Martin Doucha
@ 2025-04-07 14:23 ` Martin Doucha
2025-04-07 14:23 ` [LTP] [PATCH 2/5] KVM: Add kvm_vmx01 to the runtest file Martin Doucha
` (3 subsequent siblings)
4 siblings, 0 replies; 12+ messages in thread
From: Martin Doucha @ 2025-04-07 14:23 UTC (permalink / raw)
To: ltp
Fix printf formatting warnings due to type mismatch during 32bit
compilation.
Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
testcases/kernel/kvm/kvm_vmx01.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/testcases/kernel/kvm/kvm_vmx01.c b/testcases/kernel/kvm/kvm_vmx01.c
index c413b4148..31ad75137 100644
--- a/testcases/kernel/kvm/kvm_vmx01.c
+++ b/testcases/kernel/kvm/kvm_vmx01.c
@@ -25,7 +25,7 @@
struct vmcs_field_table {
unsigned long field_id;
const char *name;
- uint64_t value;
+ unsigned long value;
};
/* Data written into shadow VMCS by the parent VM and read by the nested VM */
@@ -110,7 +110,7 @@ static struct vmcs_field_table guest_data[SHADOW_DATA_LENGTH] = {
{VMCS_FIELD(VMX_VMCS_GUEST_LDTR_BASE), 0xb1d72}
};
-static uint64_t vmread_buffer[SHADOW_DATA_LENGTH];
+static unsigned long vmread_buffer[SHADOW_DATA_LENGTH];
int guest_main(void)
{
@@ -221,7 +221,7 @@ void main(void)
continue;
errors++;
- tst_res(TFAIL, "Shadow %s guest mismatch: %llx != %llx",
+ tst_res(TFAIL, "Shadow %s guest mismatch: %lx != %lx",
host_data[i].name, vmread_buffer[i],
host_data[i].value);
}
@@ -239,7 +239,7 @@ void main(void)
continue;
errors++;
- tst_res(TFAIL, "Shadow %s parent mismatch: %llx != %llx",
+ tst_res(TFAIL, "Shadow %s parent mismatch: %llx != %lx",
guest_data[i].name, val, guest_data[i].value);
}
--
2.49.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 12+ messages in thread* [LTP] [PATCH 2/5] KVM: Add kvm_vmx01 to the runtest file
2025-04-07 14:23 [LTP] [PATCH 0/5] KVM test for Intel VMX vAPIC Martin Doucha
2025-04-07 14:23 ` [LTP] [PATCH 1/5] kvm_vmx01: Fix 32bit compiler warnings Martin Doucha
@ 2025-04-07 14:23 ` Martin Doucha
2025-04-16 6:19 ` Petr Vorel
2025-04-07 14:23 ` [LTP] [PATCH 3/5] KVM: Simplify reading VMX control field masks Martin Doucha
` (2 subsequent siblings)
4 siblings, 1 reply; 12+ messages in thread
From: Martin Doucha @ 2025-04-07 14:23 UTC (permalink / raw)
To: ltp
Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
runtest/kvm | 1 +
1 file changed, 1 insertion(+)
diff --git a/runtest/kvm b/runtest/kvm
index 74a517add..091bcd43e 100644
--- a/runtest/kvm
+++ b/runtest/kvm
@@ -2,5 +2,6 @@ kvm_svm01 kvm_svm01
kvm_svm02 kvm_svm02
kvm_svm03 kvm_svm03
kvm_svm04 kvm_svm04
+kvm_vmx01 kvm_vmx01
# Tests below may interfere with bug reproducibility
kvm_pagefault01 kvm_pagefault01
--
2.49.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 12+ messages in thread* [LTP] [PATCH 3/5] KVM: Simplify reading VMX control field masks
2025-04-07 14:23 [LTP] [PATCH 0/5] KVM test for Intel VMX vAPIC Martin Doucha
2025-04-07 14:23 ` [LTP] [PATCH 1/5] kvm_vmx01: Fix 32bit compiler warnings Martin Doucha
2025-04-07 14:23 ` [LTP] [PATCH 2/5] KVM: Add kvm_vmx01 to the runtest file Martin Doucha
@ 2025-04-07 14:23 ` Martin Doucha
2025-04-16 6:22 ` Petr Vorel
2025-04-07 14:23 ` [LTP] [PATCH 4/5] KVM: Add constants for Intel VMX vAPIC control Martin Doucha
2025-04-07 14:23 ` [LTP] [PATCH 5/5] Add test for Intel VMX virtualized APIC Martin Doucha
4 siblings, 1 reply; 12+ messages in thread
From: Martin Doucha @ 2025-04-07 14:23 UTC (permalink / raw)
To: ltp
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
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [LTP] [PATCH 3/5] KVM: Simplify reading VMX control field masks
2025-04-07 14:23 ` [LTP] [PATCH 3/5] KVM: Simplify reading VMX control field masks Martin Doucha
@ 2025-04-16 6:22 ` Petr Vorel
2025-04-16 7:16 ` Petr Vorel
0 siblings, 1 reply; 12+ messages in thread
From: Petr Vorel @ 2025-04-16 6:22 UTC (permalink / raw)
To: Martin Doucha; +Cc: ltp
Hi Martin,
...
> /* 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);
I guess you're going to use in the future MSR_IA32_VMX_PINX_MASK2 and other
deleted masks (because now they are IMHO only in the structs).
Acked-by: Petr Vorel <pvorel@suse.cz>
Kind regards,
Petr
> - }
> + 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);
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [LTP] [PATCH 3/5] KVM: Simplify reading VMX control field masks
2025-04-16 6:22 ` Petr Vorel
@ 2025-04-16 7:16 ` Petr Vorel
2025-04-28 10:38 ` Martin Doucha
0 siblings, 1 reply; 12+ messages in thread
From: Petr Vorel @ 2025-04-16 7:16 UTC (permalink / raw)
To: Martin Doucha, ltp
Hi Martin,
> Hi Martin,
> ...
> > /* 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);
The rest of the patchset merged, thank you!
> I guess you're going to use in the future MSR_IA32_VMX_PINX_MASK2 and other
> deleted masks (because now they are IMHO only in the structs).
If you don't need the constants in the future, please remove it in a subsequent
patch.
Kind regards,
Petr
> Acked-by: Petr Vorel <pvorel@suse.cz>
> Kind regards,
> Petr
> > - }
> > + 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);
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [LTP] [PATCH 3/5] KVM: Simplify reading VMX control field masks
2025-04-16 7:16 ` Petr Vorel
@ 2025-04-28 10:38 ` Martin Doucha
2025-04-28 12:29 ` Petr Vorel
0 siblings, 1 reply; 12+ messages in thread
From: Martin Doucha @ 2025-04-28 10:38 UTC (permalink / raw)
To: Petr Vorel, ltp
Hi!
On 16. 04. 25 9:16, Petr Vorel wrote:
> Hi Martin,
>
>> Hi Martin,
>
>> ...
>>> /* 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);
>
> The rest of the patchset merged, thank you!
>
>> I guess you're going to use in the future MSR_IA32_VMX_PINX_MASK2 and other
>> deleted masks (because now they are IMHO only in the structs).
>
> If you don't need the constants in the future, please remove it in a subsequent
> patch.
Those constants are still used in kvm_vmx_read_vmctl_mask() via the
static lookup table in lib_x86.c. We can't remove them because the tests
would break on old CPUs.
--
Martin Doucha mdoucha@suse.cz
SW Quality Engineer
SUSE LINUX, s.r.o.
CORSO IIa
Krizikova 148/34
186 00 Prague 8
Czech Republic
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [LTP] [PATCH 3/5] KVM: Simplify reading VMX control field masks
2025-04-28 10:38 ` Martin Doucha
@ 2025-04-28 12:29 ` Petr Vorel
0 siblings, 0 replies; 12+ messages in thread
From: Petr Vorel @ 2025-04-28 12:29 UTC (permalink / raw)
To: Martin Doucha; +Cc: ltp
Hi Martin,
> Hi!
> On 16. 04. 25 9:16, Petr Vorel wrote:
> > Hi Martin,
> > > Hi Martin,
> > > ...
> > > > /* 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);
> > The rest of the patchset merged, thank you!
> > > I guess you're going to use in the future MSR_IA32_VMX_PINX_MASK2 and other
> > > deleted masks (because now they are IMHO only in the structs).
> > If you don't need the constants in the future, please remove it in a subsequent
> > patch.
> Those constants are still used in kvm_vmx_read_vmctl_mask() via the static
> lookup table in lib_x86.c. We can't remove them because the tests would
> break on old CPUs.
Good to know, thanks for info!
Kind regards,
Petr
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 12+ messages in thread
* [LTP] [PATCH 4/5] KVM: Add constants for Intel VMX vAPIC control
2025-04-07 14:23 [LTP] [PATCH 0/5] KVM test for Intel VMX vAPIC Martin Doucha
` (2 preceding siblings ...)
2025-04-07 14:23 ` [LTP] [PATCH 3/5] KVM: Simplify reading VMX control field masks Martin Doucha
@ 2025-04-07 14:23 ` Martin Doucha
2025-04-16 6:24 ` Petr Vorel
2025-04-07 14:23 ` [LTP] [PATCH 5/5] Add test for Intel VMX virtualized APIC Martin Doucha
4 siblings, 1 reply; 12+ messages in thread
From: Martin Doucha @ 2025-04-07 14:23 UTC (permalink / raw)
To: ltp
Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
testcases/kernel/kvm/include/kvm_x86_vmx.h | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/testcases/kernel/kvm/include/kvm_x86_vmx.h b/testcases/kernel/kvm/include/kvm_x86_vmx.h
index 92e3c683e..672c1b932 100644
--- a/testcases/kernel/kvm/include/kvm_x86_vmx.h
+++ b/testcases/kernel/kvm/include/kvm_x86_vmx.h
@@ -61,7 +61,10 @@
#define VMX_VMCS_HOST_GS 0xc0a
#define VMX_VMCS_HOST_TR 0xc0c
-#define VMX_VMCS_LINK_POINTER 0x2800
+#define VMX_VMCS_MSR_BITMAP_POINTER 0x2004
+#define VMX_VMCS_VIRT_APIC_POINTER 0x2012
+#define VMX_VMCS_VIRT_APIC_BASE 0x2014
+#define VMX_VMCS_LINK_POINTER 0x2800
#define VMX_VMCS_GUEST_ES_LIMIT 0x4800
#define VMX_VMCS_GUEST_CS_LIMIT 0x4802
@@ -143,8 +146,14 @@
#define VMX_VMCS_EXIT_QUALIFICATION 0x6400
#define VMX_INTERCEPT_HLT (1 << 7)
+#define VMX_EXECCTL_TPR_SHADOW (1 << 21)
+#define VMX_EXECCTL_MSR_BITMAP (1 << 28)
#define VMX_EXECCTL_ENABLE_CTL2 (1 << 31)
+#define VMX_EXECCTL2_VIRT_APIC (1 << 0)
+#define VMX_EXECCTL2_VIRT_X2APIC (1 << 4)
+#define VMX_EXECCTL2_VIRT_APIC_REG (1 << 8)
+#define VMX_EXECCTL2_VIRT_INTR (1 << 9)
#define VMX_EXECCTL2_SHADOW_VMCS (1 << 14)
#define VMX_EXITCTL_SAVE_DR (1 << 2)
@@ -160,6 +169,7 @@
#define VMX_INVALID_VMCS 0xffffffffffffffffULL
#define VMX_EXIT_HLT 12
+#define VMX_EXIT_RDMSR 31
#define VMX_EXIT_FAILED_ENTRY 0x80000000
struct kvm_vmcs {
--
2.49.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 12+ messages in thread* [LTP] [PATCH 5/5] Add test for Intel VMX virtualized APIC
2025-04-07 14:23 [LTP] [PATCH 0/5] KVM test for Intel VMX vAPIC Martin Doucha
` (3 preceding siblings ...)
2025-04-07 14:23 ` [LTP] [PATCH 4/5] KVM: Add constants for Intel VMX vAPIC control Martin Doucha
@ 2025-04-07 14:23 ` Martin Doucha
4 siblings, 0 replies; 12+ messages in thread
From: Martin Doucha @ 2025-04-07 14:23 UTC (permalink / raw)
To: ltp
Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
runtest/kvm | 1 +
testcases/kernel/kvm/.gitignore | 1 +
testcases/kernel/kvm/kvm_vmx02.c | 193 +++++++++++++++++++++++++++++++
3 files changed, 195 insertions(+)
create mode 100644 testcases/kernel/kvm/kvm_vmx02.c
diff --git a/runtest/kvm b/runtest/kvm
index 091bcd43e..5c285e656 100644
--- a/runtest/kvm
+++ b/runtest/kvm
@@ -3,5 +3,6 @@ kvm_svm02 kvm_svm02
kvm_svm03 kvm_svm03
kvm_svm04 kvm_svm04
kvm_vmx01 kvm_vmx01
+kvm_vmx02 kvm_vmx02
# Tests below may interfere with bug reproducibility
kvm_pagefault01 kvm_pagefault01
diff --git a/testcases/kernel/kvm/.gitignore b/testcases/kernel/kvm/.gitignore
index c18a31792..f6935c17a 100644
--- a/testcases/kernel/kvm/.gitignore
+++ b/testcases/kernel/kvm/.gitignore
@@ -4,3 +4,4 @@
/kvm_svm03
/kvm_svm04
/kvm_vmx01
+/kvm_vmx02
diff --git a/testcases/kernel/kvm/kvm_vmx02.c b/testcases/kernel/kvm/kvm_vmx02.c
new file mode 100644
index 000000000..3fcfebb3b
--- /dev/null
+++ b/testcases/kernel/kvm/kvm_vmx02.c
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2024 SUSE LLC <mdoucha@suse.cz>
+ */
+
+/*\
+ * Verify that reads and writes to virtualized APIC in nested VM get
+ * redirected to the memory page selected by parent VM.
+ */
+
+#include "kvm_test.h"
+
+#ifdef COMPILE_PAYLOAD
+#if defined(__i386__) || defined(__x86_64__)
+
+#include "kvm_x86_vmx.h"
+
+#define TPR_OFFSET 0x80
+#define TPR_VALUE 0x7
+#define TPR_OLD_VALUE 0x9
+#define MSR_TPR 0x808
+
+static void *apic_base;
+
+int memapic_guest_main(void)
+{
+ int ret;
+ uint32_t *ptr;
+
+ ptr = apic_base + TPR_OFFSET;
+ ret = *ptr;
+ *ptr = TPR_VALUE;
+ return ret;
+}
+
+int msrapic_guest_main(void)
+{
+ int ret;
+
+ ret = kvm_rdmsr(MSR_TPR);
+ kvm_wrmsr(MSR_TPR, TPR_VALUE);
+ return ret;
+}
+
+int setup_vmcs(void *apic_ptr, void *msr_mask, uint64_t ec2_flags)
+{
+ uint32_t *tpr;
+ uint64_t val, mask, flags;
+
+ /* Check secondary VMCS execctl support */
+ mask = kvm_vmx_read_vmctl_mask(VMX_CTLMASK_EXECCTL);
+
+ if (!((mask >> 32) & VMX_EXECCTL_ENABLE_CTL2))
+ return 0;
+
+ /* Create and configure guest VMCS */
+ tpr = apic_ptr + TPR_OFFSET;
+ memset(apic_ptr, 0xa9, PAGESIZE);
+ memset(apic_base, 0xab, PAGESIZE);
+ *tpr = TPR_OLD_VALUE;
+ val = kvm_vmx_vmread(VMX_VMCS_VMEXEC_CTL);
+ flags = VMX_EXECCTL_TPR_SHADOW | VMX_EXECCTL_ENABLE_CTL2;
+ flags |= VMX_EXECCTL_MSR_BITMAP;
+ flags &= mask >> 32;
+ kvm_vmx_vmwrite(VMX_VMCS_VMEXEC_CTL, val | flags);
+
+ if (flags & VMX_EXECCTL_MSR_BITMAP) {
+ kvm_vmx_vmwrite(VMX_VMCS_MSR_BITMAP_POINTER,
+ (uintptr_t)msr_mask);
+ }
+
+ mask = kvm_vmx_read_vmctl_mask(VMX_CTLMASK_EXECCTL2);
+ ec2_flags &= mask >> 32;
+
+ if (!ec2_flags)
+ return 0;
+
+ val = ec2_flags | (uint32_t)mask;
+ kvm_vmx_vmwrite(VMX_VMCS_VMEXEC_CTL2, val);
+ kvm_vmx_vmwrite(VMX_VMCS_VIRT_APIC_POINTER, (uintptr_t)apic_ptr);
+ kvm_vmx_vmwrite(VMX_VMCS_VIRT_APIC_BASE, (uintptr_t)apic_base);
+ return 1;
+}
+
+void check_result(struct kvm_vmx_vcpu *vcpu, unsigned int tpr,
+ unsigned int tpr_b)
+{
+ /* Cast RAX value to int. The upper 32 bits may contain garbage. */
+ int tpr_orig = vcpu->regs.rax;
+
+ if (tpr_orig == TPR_OLD_VALUE)
+ tst_res(TPASS, "vTPR has correct value");
+ else
+ tst_res(TFAIL, "Unexpected vTPR value: %x", tpr_orig);
+
+ if (tpr == TPR_VALUE)
+ tst_res(TPASS, "vAPIC write was handled correctly");
+ else if (tpr_b == TPR_VALUE)
+ tst_res(TFAIL, "vAPIC write was stored to literal address");
+ else
+ tst_res(TFAIL, "vAPIC write may have overwritten host memory!");
+}
+
+void main(void)
+{
+ void *apic_ptr, *msr_mask;
+ struct kvm_vmx_vcpu *vcpu;
+ uintptr_t rsp;
+ uint32_t *tpr, *tpr_b;
+ uint64_t reason;
+ uint16_t ss;
+
+ kvm_set_vmx_state(1);
+
+ apic_ptr = tst_heap_alloc_aligned(2 * PAGESIZE, PAGESIZE);
+ apic_base = apic_ptr + PAGESIZE;
+ tpr = apic_ptr + TPR_OFFSET;
+ tpr_b = apic_base + TPR_OFFSET;
+ msr_mask = tst_heap_alloc_aligned(PAGESIZE, PAGESIZE);
+ memset(msr_mask, 0, PAGESIZE);
+ vcpu = kvm_create_vmx_vcpu(memapic_guest_main, 1);
+ kvm_vmx_vmptrld(vcpu->vmcs);
+ ss = kvm_vmx_vmread(VMX_VMCS_GUEST_SS) >> 3;
+ rsp = kvm_vmx_vmread(VMX_VMCS_GUEST_RSP);
+ tst_res(TINFO, "Testing memory-mapped APIC");
+
+ if (setup_vmcs(apic_ptr, msr_mask, VMX_EXECCTL2_VIRT_APIC)) {
+ kvm_vmx_vmrun(vcpu);
+ reason = kvm_vmx_vmread(VMX_VMCS_EXIT_REASON);
+
+ if (reason != VMX_EXIT_HLT) {
+ tst_res(TFAIL, "Unexpected guest exit reason %llx",
+ reason);
+ } else {
+ check_result(vcpu, *tpr, *tpr_b);
+ }
+ } else {
+ tst_res(TCONF, "CPU does not support memory mapped vAPIC");
+ }
+
+ tst_res(TINFO, "Testing MSR-based APIC");
+ kvm_init_vmx_vcpu(vcpu, ss, (void *)rsp, msrapic_guest_main);
+
+ if (setup_vmcs(apic_ptr, msr_mask, VMX_EXECCTL2_VIRT_X2APIC)) {
+ kvm_vmx_vmrun(vcpu);
+ reason = kvm_vmx_vmread(VMX_VMCS_EXIT_REASON);
+
+ if (reason == VMX_EXIT_RDMSR) {
+ tst_res(TCONF, "CPU does not support MSR bitmaps");
+ } else if (reason != VMX_EXIT_HLT) {
+ tst_res(TFAIL, "Unexpected guest exit reason %llx",
+ reason);
+ } else {
+ check_result(vcpu, *tpr, *tpr_b);
+ }
+ } else {
+ tst_res(TCONF, "CPU does not support MSR-based vAPIC");
+ }
+}
+
+#else /* defined(__i386__) || defined(__x86_64__) */
+TST_TEST_TCONF("Test supported only on x86");
+#endif /* defined(__i386__) || defined(__x86_64__) */
+
+#else /* COMPILE_PAYLOAD */
+
+#include "tst_module.h"
+
+#define NESTED_INTEL_SYSFILE "/sys/module/kvm_intel/parameters/nested"
+
+static void setup(void)
+{
+ if (!tst_read_bool_sys_param(NESTED_INTEL_SYSFILE)) {
+ tst_module_reload("kvm_intel",
+ (char *const[]){"nested=1", NULL});
+ }
+
+ tst_kvm_setup();
+}
+
+static struct tst_test test = {
+ .test_all = tst_kvm_run,
+ .setup = setup,
+ .cleanup = tst_kvm_cleanup,
+ .needs_root = 1,
+ .supported_archs = (const char *const []) {
+ "x86_64",
+ "x86",
+ NULL
+ },
+};
+
+#endif /* COMPILE_PAYLOAD */
--
2.49.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 12+ messages in thread