Message ID | 20200925073624.245578-1-yadong.qi@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [kvm-unit-tests] x86: vmx: Add test for SIPI signal processing | expand |
> -----Original Message----- > From: Qi, Yadong <yadong.qi@intel.com> > Sent: Friday, September 25, 2020 3:36 PM > To: kvm@vger.kernel.org > Cc: pbonzini@redhat.com; Qi, Yadong <yadong.qi@intel.com> > Subject: [kvm-unit-tests PATCH] x86: vmx: Add test for SIPI signal processing > > From: Yadong Qi <yadong.qi@intel.com> > > The test verifies the following functionality: > A SIPI signal received when CPU is in VMX non-root mode: > if ACTIVITY_STATE == WAIT_SIPI > VMExit with (reason == 4) > else > SIPI signal is ignored > > The test cases depends on IA32_VMX_MISC:bit(8), if this bit is 1 then the test > cases would be executed, otherwise the test cases would be skiped. > > Signed-off-by: Yadong Qi <yadong.qi@intel.com> > --- > lib/x86/msr.h | 1 + > x86/unittests.cfg | 8 +++ > x86/vmx.c | 2 +- > x86/vmx.h | 3 ++ > x86/vmx_tests.c | 134 > ++++++++++++++++++++++++++++++++++++++++++++++ > 5 files changed, 147 insertions(+), 1 deletion(-) > > diff --git a/lib/x86/msr.h b/lib/x86/msr.h index 6ef5502..29e3947 100644 > --- a/lib/x86/msr.h > +++ b/lib/x86/msr.h > @@ -421,6 +421,7 @@ > #define MSR_IA32_VMX_TRUE_ENTRY 0x00000490 > > /* MSR_IA32_VMX_MISC bits */ > +#define MSR_IA32_VMX_MISC_ACTIVITY_WAIT_SIPI (1ULL << 8) > #define MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS (1ULL << 29) > > #define MSR_IA32_TSCDEADLINE 0x000006e0 > diff --git a/x86/unittests.cfg b/x86/unittests.cfg index 3a79151..3e14a65 > 100644 > --- a/x86/unittests.cfg > +++ b/x86/unittests.cfg > @@ -293,6 +293,14 @@ arch = x86_64 > groups = vmx > timeout = 10 > > +[vmx_sipi_signal_test] > +file = vmx.flat > +smp = 2 > +extra_params = -cpu host,+vmx -m 2048 -append vmx_sipi_signal_test arch > += x86_64 groups = vmx timeout = 10 > + > [vmx_apic_passthrough_tpr_threshold_test] > file = vmx.flat > extra_params = -cpu host,+vmx -m 2048 -append > vmx_apic_passthrough_tpr_threshold_test > diff --git a/x86/vmx.c b/x86/vmx.c > index 07415b4..e3a3fbf 100644 > --- a/x86/vmx.c > +++ b/x86/vmx.c > @@ -1369,7 +1369,7 @@ static void init_vmcs_guest(void) > vmcs_write(GUEST_INTR_STATE, 0); > } > > -static int init_vmcs(struct vmcs **vmcs) > +int init_vmcs(struct vmcs **vmcs) > { > *vmcs = alloc_page(); > (*vmcs)->hdr.revision_id = basic.revision; diff --git a/x86/vmx.h > b/x86/vmx.h index d1c2436..9b17074 100644 > --- a/x86/vmx.h > +++ b/x86/vmx.h > @@ -697,6 +697,8 @@ enum vm_entry_failure_code { > > #define ACTV_ACTIVE 0 > #define ACTV_HLT 1 > +#define ACTV_SHUTDOWN 2 > +#define ACTV_WAIT_SIPI 3 > > /* > * VMCS field encoding: > @@ -856,6 +858,7 @@ static inline bool invvpid(unsigned long type, u64 vpid, > u64 gla) > > void enable_vmx(void); > void init_vmx(u64 *vmxon_region); > +int init_vmcs(struct vmcs **vmcs); > > const char *exit_reason_description(u64 reason); void print_vmexit_info(union > exit_reason exit_reason); diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index > 22f0c7b..45b0f80 100644 > --- a/x86/vmx_tests.c > +++ b/x86/vmx_tests.c > @@ -9608,6 +9608,139 @@ static void vmx_init_signal_test(void) > */ > } > > +#define SIPI_SIGNAL_TEST_DELAY 100000000ULL > + > +static void vmx_sipi_test_guest(void) > +{ > + if (apic_id() == 0) { > + /* wait AP enter guest with activity=WAIT_SIPI */ > + while (vmx_get_test_stage() != 1) > + ; > + delay(SIPI_SIGNAL_TEST_DELAY); > + > + /* First SIPI signal */ > + apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_STARTUP | > APIC_INT_ASSERT, id_map[1]); > + report(1, "BSP(L2): Send first SIPI to cpu[%d]", id_map[1]); > + > + /* wait AP enter guest */ > + while (vmx_get_test_stage() != 2) > + ; > + delay(SIPI_SIGNAL_TEST_DELAY); > + > + /* Second SIPI signal should be ignored since AP is not in > WAIT_SIPI state */ > + apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_STARTUP | > APIC_INT_ASSERT, id_map[1]); > + report(1, "BSP(L2): Send second SIPI to cpu[%d]", id_map[1]); > + > + /* Delay a while to check whether second SIPI would cause > VMExit */ > + delay(SIPI_SIGNAL_TEST_DELAY); > + > + /* Test is done, notify AP to exit test */ > + vmx_set_test_stage(3); > + > + /* wait AP exit non-root mode */ > + while (vmx_get_test_stage() != 5) > + ; > + } else { > + /* wait BSP notify test is done */ > + while (vmx_get_test_stage() != 3) > + ; > + > + /* AP exit guest */ > + vmx_set_test_stage(4); > + } > +} > + > +static void sipi_test_ap_thread(void *data) { > + struct vmcs *ap_vmcs; > + u64 *ap_vmxon_region; > + void *ap_stack, *ap_syscall_stack; > + u64 cpu_ctrl_0 = CPU_SECONDARY; > + u64 cpu_ctrl_1 = 0; > + > + /* Enter VMX operation (i.e. exec VMXON) */ > + ap_vmxon_region = alloc_page(); > + enable_vmx(); > + init_vmx(ap_vmxon_region); > + _vmx_on(ap_vmxon_region); > + init_vmcs(&ap_vmcs); > + make_vmcs_current(ap_vmcs); > + > + /* Set stack for AP */ > + ap_stack = alloc_page(); > + ap_syscall_stack = alloc_page(); > + vmcs_write(GUEST_RSP, (u64)(ap_stack + PAGE_SIZE - 1)); > + vmcs_write(GUEST_SYSENTER_ESP, (u64)(ap_syscall_stack + PAGE_SIZE > - > +1)); > + > + /* passthrough lapic to L2 */ > + disable_intercept_for_x2apic_msrs(); > + vmcs_write(CPU_EXEC_CTRL0, vmcs_read(CPU_EXEC_CTRL0) | > cpu_ctrl_0); > + vmcs_write(CPU_EXEC_CTRL1, vmcs_read(CPU_EXEC_CTRL1) | > cpu_ctrl_1); > + > + /* Set guest activity state to wait-for-SIPI state */ > + vmcs_write(GUEST_ACTV_STATE, ACTV_WAIT_SIPI); > + > + vmx_set_test_stage(1); > + > + /* AP enter guest */ > + enter_guest(); > + > + if (vmcs_read(EXI_REASON) == VMX_SIPI) { > + report(1, "AP: Handle SIPI VMExit"); > + vmcs_write(GUEST_ACTV_STATE, ACTV_ACTIVE); > + vmx_set_test_stage(2); > + } else { > + report(0, "AP: Unexpected VMExit, reason=%ld", > vmcs_read(EXI_REASON)); > + vmx_off(); > + return; > + } > + > + /* AP enter guest */ > + enter_guest(); > + > + report(vmcs_read(EXI_REASON) != VMX_SIPI, > + "AP: should no SIPI VMExit since activity is not in WAIT_SIPI > +state"); > + > + /* notify BSP that AP is already exit from non-root mode */ > + vmx_set_test_stage(5); > + > + /* Leave VMX operation */ > + vmx_off(); > +} > + > +static void vmx_sipi_signal_test(void) > +{ > + if (!(rdmsr(MSR_IA32_VMX_MISC) & > MSR_IA32_VMX_MISC_ACTIVITY_WAIT_SIPI)) { > + printf("\tACTIVITY_WAIT_SIPI state is not supported.\n"); > + return; > + } > + > + if (cpu_count() < 2) { > + report_skip(__func__); > + return; > + } > + > + u64 cpu_ctrl_0 = CPU_SECONDARY; > + u64 cpu_ctrl_1 = 0; > + > + /* passthrough lapic */ > + disable_intercept_for_x2apic_msrs(); > + vmcs_write(PIN_CONTROLS, vmcs_read(PIN_CONTROLS) & > ~PIN_EXTINT); > + vmcs_write(CPU_EXEC_CTRL0, vmcs_read(CPU_EXEC_CTRL0) | > cpu_ctrl_0); > + vmcs_write(CPU_EXEC_CTRL1, vmcs_read(CPU_EXEC_CTRL1) | > cpu_ctrl_1); > + > + test_set_guest(vmx_sipi_test_guest); > + > + /* start AP */ > + on_cpu_async(1, sipi_test_ap_thread, NULL); > + > + vmx_set_test_stage(0); > + > + /* BSP enter guest */ > + enter_guest(); > +} > + > + > enum vmcs_access { > ACCESS_VMREAD, > ACCESS_VMWRITE, > @@ -10244,6 +10377,7 @@ struct vmx_test vmx_tests[] = { > TEST(vmx_apic_passthrough_thread_test), > TEST(vmx_apic_passthrough_tpr_threshold_test), > TEST(vmx_init_signal_test), > + TEST(vmx_sipi_signal_test), > /* VMCS Shadowing tests */ > TEST(vmx_vmcs_shadow_test), > /* Regression tests */ > -- > 2.25.1 Hi, Paolo Any comments of this patch? It is test case for https://patchwork.kernel.org/patch/11791499/ Best Regard Yadong
> On Oct 4, 2020, at 12:19 AM, Qi, Yadong <yadong.qi@intel.com> wrote: > >> -----Original Message----- >> From: Qi, Yadong <yadong.qi@intel.com> >> Sent: Friday, September 25, 2020 3:36 PM >> To: kvm@vger.kernel.org >> Cc: pbonzini@redhat.com; Qi, Yadong <yadong.qi@intel.com> >> Subject: [kvm-unit-tests PATCH] x86: vmx: Add test for SIPI signal processing >> >> From: Yadong Qi <yadong.qi@intel.com> >> >> The test verifies the following functionality: >> A SIPI signal received when CPU is in VMX non-root mode: >> if ACTIVITY_STATE == WAIT_SIPI >> VMExit with (reason == 4) >> else >> SIPI signal is ignored >> >> The test cases depends on IA32_VMX_MISC:bit(8), if this bit is 1 then the test >> cases would be executed, otherwise the test cases would be skiped. >> >> Signed-off-by: Yadong Qi <yadong.qi@intel.com> [ snip ] > > Hi, Paolo > > Any comments of this patch? > It is test case for https://patchwork.kernel.org/patch/11791499/ On my bare-metal machine, I get a #GP on the WRMSR that writes the EOI inside ipi() : Test suite: vmx_sipi_signal_test Unhandled exception 13 #GP at ip 0000000000417eba error_code=0000 rflags=00010002 cs=00000008 rax=0000000000000000 rcx=000000000000080b rdx=0000000000000000 rbx=0000000000000000 rbp=000000000053a238 rsi=0000000000000000 rdi=000000000000000b r8=000000000000000a r9=00000000000003f8 r10=000000000000000d r11=0000000000000000 r12=000000000040c7a5 r13=0000000000000000 r14=0000000000000000 r15=0000000000000000 cr0=0000000080000011 cr2=0000000000000000 cr3=000000000041f000 cr4=0000000000000020 cr8=0000000000000000 STACK: @417eba 417f36 417481 417383 I did not dig much deeper. Could it be that there is some confusion between xapic/x2apic ?
> > On my bare-metal machine, I get a #GP on the WRMSR that writes the EOI inside > ipi() : > > Test suite: vmx_sipi_signal_test > Unhandled exception 13 #GP at ip 0000000000417eba > error_code=0000 rflags=00010002 cs=00000008 > rax=0000000000000000 rcx=000000000000080b rdx=0000000000000000 > rbx=0000000000000000 > rbp=000000000053a238 rsi=0000000000000000 rdi=000000000000000b > r8=000000000000000a r9=00000000000003f8 r10=000000000000000d > r11=0000000000000000 > r12=000000000040c7a5 r13=0000000000000000 r14=0000000000000000 > r15=0000000000000000 > cr0=0000000080000011 cr2=0000000000000000 cr3=000000000041f000 > cr4=0000000000000020 > cr8=0000000000000000 > STACK: @417eba 417f36 417481 417383 > > I did not dig much deeper. Could it be that there is some confusion between > xapic/x2apic ? Thanks, Nadav. I cannot reproduce the #GP issue on my bare metal machine. And I am a little bit confused, there is no EOI MSR write in this test suite, how the #GP comes out... Could you provide more info for me to reproduce the issue? Best Regard Yadong
> On Oct 11, 2020, at 6:19 PM, Qi, Yadong <yadong.qi@intel.com> wrote: > >> On my bare-metal machine, I get a #GP on the WRMSR that writes the EOI inside >> ipi() : >> >> Test suite: vmx_sipi_signal_test >> Unhandled exception 13 #GP at ip 0000000000417eba >> error_code=0000 rflags=00010002 cs=00000008 >> rax=0000000000000000 rcx=000000000000080b rdx=0000000000000000 >> rbx=0000000000000000 >> rbp=000000000053a238 rsi=0000000000000000 rdi=000000000000000b >> r8=000000000000000a r9=00000000000003f8 r10=000000000000000d >> r11=0000000000000000 >> r12=000000000040c7a5 r13=0000000000000000 r14=0000000000000000 >> r15=0000000000000000 >> cr0=0000000080000011 cr2=0000000000000000 cr3=000000000041f000 >> cr4=0000000000000020 >> cr8=0000000000000000 >> STACK: @417eba 417f36 417481 417383 >> >> I did not dig much deeper. Could it be that there is some confusion between >> xapic/x2apic ? > > Thanks, Nadav. > I cannot reproduce the #GP issue on my bare metal machine. > And I am a little bit confused, there is no EOI MSR write in this test suite, > how the #GP comes out... > Could you provide more info for me to reproduce the issue? We might have different definitions for “bare-metal” :) I meant that I ran it directly on the machine without KVM. See [1]. You do need some access serial console through the iDRAC/ilo/etc.. Anyhow, I figured out that you forgot to setup CR3 on the AP. Doing something like: + on_cpu(1, update_cr3, (void *)read_cr3()); /* start AP */ on_cpu_async(1, sipi_test_ap_thread, NULL); Solves the problem. You may want to do it in a slightly cleaner way, or extract update_cr3() to one of the libs to avoid further code duplication. Regards, Nadav [1] https://patchwork.kernel.org/patch/11053903/
> -----Original Message----- > From: Nadav Amit <nadav.amit@gmail.com> > Sent: Monday, October 12, 2020 2:37 PM > To: Qi, Yadong <yadong.qi@intel.com> > Cc: kvm@vger.kernel.org; pbonzini@redhat.com > Subject: Re: [kvm-unit-tests PATCH] x86: vmx: Add test for SIPI signal processing > > > On Oct 11, 2020, at 6:19 PM, Qi, Yadong <yadong.qi@intel.com> wrote: > > > >> On my bare-metal machine, I get a #GP on the WRMSR that writes the > >> EOI inside > >> ipi() : > >> > >> Test suite: vmx_sipi_signal_test > >> Unhandled exception 13 #GP at ip 0000000000417eba > >> error_code=0000 rflags=00010002 cs=00000008 > >> rax=0000000000000000 rcx=000000000000080b rdx=0000000000000000 > >> rbx=0000000000000000 > >> rbp=000000000053a238 rsi=0000000000000000 rdi=000000000000000b > >> r8=000000000000000a r9=00000000000003f8 r10=000000000000000d > >> r11=0000000000000000 > >> r12=000000000040c7a5 r13=0000000000000000 r14=0000000000000000 > >> r15=0000000000000000 > >> cr0=0000000080000011 cr2=0000000000000000 cr3=000000000041f000 > >> cr4=0000000000000020 > >> cr8=0000000000000000 > >> STACK: @417eba 417f36 417481 417383 > >> > >> I did not dig much deeper. Could it be that there is some confusion > >> between xapic/x2apic ? > > > > Thanks, Nadav. > > I cannot reproduce the #GP issue on my bare metal machine. > > And I am a little bit confused, there is no EOI MSR write in this test > > suite, how the #GP comes out... > > Could you provide more info for me to reproduce the issue? > > We might have different definitions for “bare-metal” :) > > I meant that I ran it directly on the machine without KVM. See [1]. You do need > some access serial console through the iDRAC/ilo/etc.. Oh, I see. Thank you for clarifying it. > > Anyhow, I figured out that you forgot to setup CR3 on the AP. > > Doing something like: > > + on_cpu(1, update_cr3, (void *)read_cr3()); > > /* start AP */ > on_cpu_async(1, sipi_test_ap_thread, NULL); > > > Solves the problem. You may want to do it in a slightly cleaner way, or extract > update_cr3() to one of the libs to avoid further code duplication. Thanks very much for figuring out the issue. Will update the patch in next version. Best Regard Yadong > > Regards, > Nadav > > > [1] https://patchwork.kernel.org/patch/11053903/
diff --git a/lib/x86/msr.h b/lib/x86/msr.h index 6ef5502..29e3947 100644 --- a/lib/x86/msr.h +++ b/lib/x86/msr.h @@ -421,6 +421,7 @@ #define MSR_IA32_VMX_TRUE_ENTRY 0x00000490 /* MSR_IA32_VMX_MISC bits */ +#define MSR_IA32_VMX_MISC_ACTIVITY_WAIT_SIPI (1ULL << 8) #define MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS (1ULL << 29) #define MSR_IA32_TSCDEADLINE 0x000006e0 diff --git a/x86/unittests.cfg b/x86/unittests.cfg index 3a79151..3e14a65 100644 --- a/x86/unittests.cfg +++ b/x86/unittests.cfg @@ -293,6 +293,14 @@ arch = x86_64 groups = vmx timeout = 10 +[vmx_sipi_signal_test] +file = vmx.flat +smp = 2 +extra_params = -cpu host,+vmx -m 2048 -append vmx_sipi_signal_test +arch = x86_64 +groups = vmx +timeout = 10 + [vmx_apic_passthrough_tpr_threshold_test] file = vmx.flat extra_params = -cpu host,+vmx -m 2048 -append vmx_apic_passthrough_tpr_threshold_test diff --git a/x86/vmx.c b/x86/vmx.c index 07415b4..e3a3fbf 100644 --- a/x86/vmx.c +++ b/x86/vmx.c @@ -1369,7 +1369,7 @@ static void init_vmcs_guest(void) vmcs_write(GUEST_INTR_STATE, 0); } -static int init_vmcs(struct vmcs **vmcs) +int init_vmcs(struct vmcs **vmcs) { *vmcs = alloc_page(); (*vmcs)->hdr.revision_id = basic.revision; diff --git a/x86/vmx.h b/x86/vmx.h index d1c2436..9b17074 100644 --- a/x86/vmx.h +++ b/x86/vmx.h @@ -697,6 +697,8 @@ enum vm_entry_failure_code { #define ACTV_ACTIVE 0 #define ACTV_HLT 1 +#define ACTV_SHUTDOWN 2 +#define ACTV_WAIT_SIPI 3 /* * VMCS field encoding: @@ -856,6 +858,7 @@ static inline bool invvpid(unsigned long type, u64 vpid, u64 gla) void enable_vmx(void); void init_vmx(u64 *vmxon_region); +int init_vmcs(struct vmcs **vmcs); const char *exit_reason_description(u64 reason); void print_vmexit_info(union exit_reason exit_reason); diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index 22f0c7b..45b0f80 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -9608,6 +9608,139 @@ static void vmx_init_signal_test(void) */ } +#define SIPI_SIGNAL_TEST_DELAY 100000000ULL + +static void vmx_sipi_test_guest(void) +{ + if (apic_id() == 0) { + /* wait AP enter guest with activity=WAIT_SIPI */ + while (vmx_get_test_stage() != 1) + ; + delay(SIPI_SIGNAL_TEST_DELAY); + + /* First SIPI signal */ + apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_STARTUP | APIC_INT_ASSERT, id_map[1]); + report(1, "BSP(L2): Send first SIPI to cpu[%d]", id_map[1]); + + /* wait AP enter guest */ + while (vmx_get_test_stage() != 2) + ; + delay(SIPI_SIGNAL_TEST_DELAY); + + /* Second SIPI signal should be ignored since AP is not in WAIT_SIPI state */ + apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_STARTUP | APIC_INT_ASSERT, id_map[1]); + report(1, "BSP(L2): Send second SIPI to cpu[%d]", id_map[1]); + + /* Delay a while to check whether second SIPI would cause VMExit */ + delay(SIPI_SIGNAL_TEST_DELAY); + + /* Test is done, notify AP to exit test */ + vmx_set_test_stage(3); + + /* wait AP exit non-root mode */ + while (vmx_get_test_stage() != 5) + ; + } else { + /* wait BSP notify test is done */ + while (vmx_get_test_stage() != 3) + ; + + /* AP exit guest */ + vmx_set_test_stage(4); + } +} + +static void sipi_test_ap_thread(void *data) +{ + struct vmcs *ap_vmcs; + u64 *ap_vmxon_region; + void *ap_stack, *ap_syscall_stack; + u64 cpu_ctrl_0 = CPU_SECONDARY; + u64 cpu_ctrl_1 = 0; + + /* Enter VMX operation (i.e. exec VMXON) */ + ap_vmxon_region = alloc_page(); + enable_vmx(); + init_vmx(ap_vmxon_region); + _vmx_on(ap_vmxon_region); + init_vmcs(&ap_vmcs); + make_vmcs_current(ap_vmcs); + + /* Set stack for AP */ + ap_stack = alloc_page(); + ap_syscall_stack = alloc_page(); + vmcs_write(GUEST_RSP, (u64)(ap_stack + PAGE_SIZE - 1)); + vmcs_write(GUEST_SYSENTER_ESP, (u64)(ap_syscall_stack + PAGE_SIZE - 1)); + + /* passthrough lapic to L2 */ + disable_intercept_for_x2apic_msrs(); + vmcs_write(CPU_EXEC_CTRL0, vmcs_read(CPU_EXEC_CTRL0) | cpu_ctrl_0); + vmcs_write(CPU_EXEC_CTRL1, vmcs_read(CPU_EXEC_CTRL1) | cpu_ctrl_1); + + /* Set guest activity state to wait-for-SIPI state */ + vmcs_write(GUEST_ACTV_STATE, ACTV_WAIT_SIPI); + + vmx_set_test_stage(1); + + /* AP enter guest */ + enter_guest(); + + if (vmcs_read(EXI_REASON) == VMX_SIPI) { + report(1, "AP: Handle SIPI VMExit"); + vmcs_write(GUEST_ACTV_STATE, ACTV_ACTIVE); + vmx_set_test_stage(2); + } else { + report(0, "AP: Unexpected VMExit, reason=%ld", vmcs_read(EXI_REASON)); + vmx_off(); + return; + } + + /* AP enter guest */ + enter_guest(); + + report(vmcs_read(EXI_REASON) != VMX_SIPI, + "AP: should no SIPI VMExit since activity is not in WAIT_SIPI state"); + + /* notify BSP that AP is already exit from non-root mode */ + vmx_set_test_stage(5); + + /* Leave VMX operation */ + vmx_off(); +} + +static void vmx_sipi_signal_test(void) +{ + if (!(rdmsr(MSR_IA32_VMX_MISC) & MSR_IA32_VMX_MISC_ACTIVITY_WAIT_SIPI)) { + printf("\tACTIVITY_WAIT_SIPI state is not supported.\n"); + return; + } + + if (cpu_count() < 2) { + report_skip(__func__); + return; + } + + u64 cpu_ctrl_0 = CPU_SECONDARY; + u64 cpu_ctrl_1 = 0; + + /* passthrough lapic */ + disable_intercept_for_x2apic_msrs(); + vmcs_write(PIN_CONTROLS, vmcs_read(PIN_CONTROLS) & ~PIN_EXTINT); + vmcs_write(CPU_EXEC_CTRL0, vmcs_read(CPU_EXEC_CTRL0) | cpu_ctrl_0); + vmcs_write(CPU_EXEC_CTRL1, vmcs_read(CPU_EXEC_CTRL1) | cpu_ctrl_1); + + test_set_guest(vmx_sipi_test_guest); + + /* start AP */ + on_cpu_async(1, sipi_test_ap_thread, NULL); + + vmx_set_test_stage(0); + + /* BSP enter guest */ + enter_guest(); +} + + enum vmcs_access { ACCESS_VMREAD, ACCESS_VMWRITE, @@ -10244,6 +10377,7 @@ struct vmx_test vmx_tests[] = { TEST(vmx_apic_passthrough_thread_test), TEST(vmx_apic_passthrough_tpr_threshold_test), TEST(vmx_init_signal_test), + TEST(vmx_sipi_signal_test), /* VMCS Shadowing tests */ TEST(vmx_vmcs_shadow_test), /* Regression tests */