Message ID | 20221020152404.283980-9-mlevitsk@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | kvm-unit-tests: set of fixes and new tests | expand |
On Thu, 2022-10-20 at 18:23 +0300, Maxim Levitsky wrote: > Test that if L2 triggers a shutdown, this VM exits to L1 > and doesn't crash the host. > > Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> > --- > x86/svm_tests.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 51 insertions(+) > > diff --git a/x86/svm_tests.c b/x86/svm_tests.c > index 19b35e95..2c29c2b0 100644 > --- a/x86/svm_tests.c > +++ b/x86/svm_tests.c > @@ -10,6 +10,7 @@ > #include "isr.h" > #include "apic.h" > #include "delay.h" > +#include "vmalloc.h" > > #define SVM_EXIT_MAX_DR_INTERCEPT 0x3f > > @@ -3270,6 +3271,55 @@ static void svm_intr_intercept_mix_smi(void) > svm_intr_intercept_mix_run_guest(NULL, SVM_EXIT_SMI); > } > > + > +static void shutdown_intercept_test_guest(struct svm_test *test) > +{ > + asm volatile ("int3"); > + report_fail("should not reach here\n"); > + > +} > + > +static void shutdown_intercept_test_guest2(struct svm_test *test) > +{ > + asm volatile ("ud2"); > + report_fail("should not reach here\n"); > + > +} > + > +static void svm_shutdown_intercept_test(void) > +{ > + void* unmapped_address = alloc_vpage(); > + > + /* > + * Test that shutdown vm exit doesn't crash L0 > + * > + * Test both native and emulated triple fault > + * (due to exception merging) > + */ > + > + > + /* > + * This will usually cause native SVM_EXIT_SHUTDOWN > + * (KVM usually doesn't intercept #PF) > + * */ > + test_set_guest(shutdown_intercept_test_guest); > + vmcb->save.idtr.base = (u64)unmapped_address; > + vmcb->control.intercept |= (1ULL << INTERCEPT_SHUTDOWN); > + svm_vmrun(); > + report (vmcb->control.exit_code == SVM_EXIT_SHUTDOWN, "shutdown (BP->PF->DF->TRIPLE_FAULT) test passed"); > + > + /* > + * This will usually cause emulated SVM_EXIT_SHUTDOWN > + * (KVM usually intercepts #UD) > + */ > + test_set_guest(shutdown_intercept_test_guest2); > + vmcb_ident(vmcb); > + vmcb->save.idtr.limit = 0; > + vmcb->control.intercept |= (1ULL << INTERCEPT_SHUTDOWN); > + svm_vmrun(); > + report (vmcb->control.exit_code == SVM_EXIT_SHUTDOWN, "shutdown (UD->DF->TRIPLE_FAULT) test passed"); > +} > + > struct svm_test svm_tests[] = { > { "null", default_supported, default_prepare, > default_prepare_gif_clear, null_test, > @@ -3382,6 +3432,7 @@ struct svm_test svm_tests[] = { > TEST(svm_intr_intercept_mix_smi), > TEST(svm_tsc_scale_test), > TEST(pause_filter_test), > + TEST(svm_shutdown_intercept_test), > { NULL, NULL, NULL, NULL, NULL, NULL, NULL } > }; > Note that on unpatched KVM, this test will cause a kernel panic on the host if run. I sent a patch today with a fix for this. Best regards, MaxiM Levitsky
On Thu, Oct 20, 2022, Maxim Levitsky wrote: > On Thu, 2022-10-20 at 18:23 +0300, Maxim Levitsky wrote: > > +static void svm_shutdown_intercept_test(void) > > +{ > > + void* unmapped_address = alloc_vpage(); > > + > > + /* > > + * Test that shutdown vm exit doesn't crash L0 > > + * > > + * Test both native and emulated triple fault > > + * (due to exception merging) > > + */ > > + > > + > > + /* > > + * This will usually cause native SVM_EXIT_SHUTDOWN > > + * (KVM usually doesn't intercept #PF) > > + * */ > > + test_set_guest(shutdown_intercept_test_guest); > > + vmcb->save.idtr.base = (u64)unmapped_address; > > + vmcb->control.intercept |= (1ULL << INTERCEPT_SHUTDOWN); > > + svm_vmrun(); > > + report (vmcb->control.exit_code == SVM_EXIT_SHUTDOWN, "shutdown (BP->PF->DF->TRIPLE_FAULT) test passed"); > > + > > + /* > > + * This will usually cause emulated SVM_EXIT_SHUTDOWN > > + * (KVM usually intercepts #UD) > > + */ > > + test_set_guest(shutdown_intercept_test_guest2); > > + vmcb_ident(vmcb); > > + vmcb->save.idtr.limit = 0; > > + vmcb->control.intercept |= (1ULL << INTERCEPT_SHUTDOWN); > > + svm_vmrun(); > > + report (vmcb->control.exit_code == SVM_EXIT_SHUTDOWN, "shutdown (UD->DF->TRIPLE_FAULT) test passed"); > > +} > > + > > struct svm_test svm_tests[] = { > > { "null", default_supported, default_prepare, > > default_prepare_gif_clear, null_test, > > @@ -3382,6 +3432,7 @@ struct svm_test svm_tests[] = { > > TEST(svm_intr_intercept_mix_smi), > > TEST(svm_tsc_scale_test), > > TEST(pause_filter_test), > > + TEST(svm_shutdown_intercept_test), > > { NULL, NULL, NULL, NULL, NULL, NULL, NULL } > > }; > > Note that on unpatched KVM, this test will cause a kernel panic on the host > if run. > > I sent a patch today with a fix for this. I'm confused. The KVM patches address a bug where KVM screws up if the SHUTDOWN (or INIT) is _not_ intercepted by L1, but the test here does intercept SHUTDOWN. Are there more bugs lurking in KVM, or am I missing something?
On Thu, 2022-10-20 at 19:06 +0000, Sean Christopherson wrote: > On Thu, Oct 20, 2022, Maxim Levitsky wrote: > > On Thu, 2022-10-20 at 18:23 +0300, Maxim Levitsky wrote: > > > +static void svm_shutdown_intercept_test(void) > > > +{ > > > + void* unmapped_address = alloc_vpage(); > > > + > > > + /* > > > + * Test that shutdown vm exit doesn't crash L0 > > > + * > > > + * Test both native and emulated triple fault > > > + * (due to exception merging) > > > + */ > > > + > > > + > > > + /* > > > + * This will usually cause native SVM_EXIT_SHUTDOWN > > > + * (KVM usually doesn't intercept #PF) > > > + * */ > > > + test_set_guest(shutdown_intercept_test_guest); > > > + vmcb->save.idtr.base = (u64)unmapped_address; > > > + vmcb->control.intercept |= (1ULL << INTERCEPT_SHUTDOWN); > > > + svm_vmrun(); > > > + report (vmcb->control.exit_code == SVM_EXIT_SHUTDOWN, "shutdown (BP->PF->DF->TRIPLE_FAULT) test passed"); > > > + > > > + /* > > > + * This will usually cause emulated SVM_EXIT_SHUTDOWN > > > + * (KVM usually intercepts #UD) > > > + */ > > > + test_set_guest(shutdown_intercept_test_guest2); > > > + vmcb_ident(vmcb); > > > + vmcb->save.idtr.limit = 0; > > > + vmcb->control.intercept |= (1ULL << INTERCEPT_SHUTDOWN); > > > + svm_vmrun(); > > > + report (vmcb->control.exit_code == SVM_EXIT_SHUTDOWN, "shutdown (UD->DF->TRIPLE_FAULT) test passed"); > > > +} > > > + > > > struct svm_test svm_tests[] = { > > > { "null", default_supported, default_prepare, > > > default_prepare_gif_clear, null_test, > > > @@ -3382,6 +3432,7 @@ struct svm_test svm_tests[] = { > > > TEST(svm_intr_intercept_mix_smi), > > > TEST(svm_tsc_scale_test), > > > TEST(pause_filter_test), > > > + TEST(svm_shutdown_intercept_test), > > > { NULL, NULL, NULL, NULL, NULL, NULL, NULL } > > > }; > > > > Note that on unpatched KVM, this test will cause a kernel panic on the host > > if run. > > > > I sent a patch today with a fix for this. > > I'm confused. The KVM patches address a bug where KVM screws up if the SHUTDOWN > (or INIT) is _not_ intercepted by L1, but the test here does intercept SHUTDOWN. > Are there more bugs lurking in KVM, or am I missing something? Yes you don't miss anything - it was a last minute change that I forgot about: If you let shutdown to not be intercepted, and even if KVM works correclty, it will still kill qemu, and thus not run other subtests of this test. The test will still 'pass' silently, something that should be IMHO fixed, the test runner should check the exit status of qemu or in some other way detect that qemu got shutdown instead of returning normally. I decided to make this test in selftests, which also has a bonus of not crashing the host kernel, since the selftest will come after the fix. And the above test checks it the other way around which is still a good test IMHO (I do need to update the commit message though). Best regards, Maxim Levitsky. >
diff --git a/x86/svm_tests.c b/x86/svm_tests.c index 19b35e95..2c29c2b0 100644 --- a/x86/svm_tests.c +++ b/x86/svm_tests.c @@ -10,6 +10,7 @@ #include "isr.h" #include "apic.h" #include "delay.h" +#include "vmalloc.h" #define SVM_EXIT_MAX_DR_INTERCEPT 0x3f @@ -3270,6 +3271,55 @@ static void svm_intr_intercept_mix_smi(void) svm_intr_intercept_mix_run_guest(NULL, SVM_EXIT_SMI); } + +static void shutdown_intercept_test_guest(struct svm_test *test) +{ + asm volatile ("int3"); + report_fail("should not reach here\n"); + +} + +static void shutdown_intercept_test_guest2(struct svm_test *test) +{ + asm volatile ("ud2"); + report_fail("should not reach here\n"); + +} + +static void svm_shutdown_intercept_test(void) +{ + void* unmapped_address = alloc_vpage(); + + /* + * Test that shutdown vm exit doesn't crash L0 + * + * Test both native and emulated triple fault + * (due to exception merging) + */ + + + /* + * This will usually cause native SVM_EXIT_SHUTDOWN + * (KVM usually doesn't intercept #PF) + * */ + test_set_guest(shutdown_intercept_test_guest); + vmcb->save.idtr.base = (u64)unmapped_address; + vmcb->control.intercept |= (1ULL << INTERCEPT_SHUTDOWN); + svm_vmrun(); + report (vmcb->control.exit_code == SVM_EXIT_SHUTDOWN, "shutdown (BP->PF->DF->TRIPLE_FAULT) test passed"); + + /* + * This will usually cause emulated SVM_EXIT_SHUTDOWN + * (KVM usually intercepts #UD) + */ + test_set_guest(shutdown_intercept_test_guest2); + vmcb_ident(vmcb); + vmcb->save.idtr.limit = 0; + vmcb->control.intercept |= (1ULL << INTERCEPT_SHUTDOWN); + svm_vmrun(); + report (vmcb->control.exit_code == SVM_EXIT_SHUTDOWN, "shutdown (UD->DF->TRIPLE_FAULT) test passed"); +} + struct svm_test svm_tests[] = { { "null", default_supported, default_prepare, default_prepare_gif_clear, null_test, @@ -3382,6 +3432,7 @@ struct svm_test svm_tests[] = { TEST(svm_intr_intercept_mix_smi), TEST(svm_tsc_scale_test), TEST(pause_filter_test), + TEST(svm_shutdown_intercept_test), { NULL, NULL, NULL, NULL, NULL, NULL, NULL } };
Test that if L2 triggers a shutdown, this VM exits to L1 and doesn't crash the host. Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> --- x86/svm_tests.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)