diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2020-04-09 05:42:52 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2020-04-15 10:56:00 -0400 |
commit | 4b4fb247215957fe57a9ebd04bc4e73e1d0ade33 (patch) | |
tree | 983ff3e54ef6db4bd62efdc47b0e69e670e6c5e0 | |
parent | 9da1f4d89d16a6049f7f2ac941c1101f2a34a5b9 (diff) | |
download | kvm-unit-tests-4b4fb247215957fe57a9ebd04bc4e73e1d0ade33.tar.gz |
svm: add a test for exception injection
Cover VMRUN's testing whether EVENTINJ.TYPE = 3 (exception) has been specified with
a vector that does not correspond to an exception.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | x86/svm_tests.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/x86/svm_tests.c b/x86/svm_tests.c index 2ec7275..b4ba999 100644 --- a/x86/svm_tests.c +++ b/x86/svm_tests.c @@ -1519,6 +1519,73 @@ static bool nmi_hlt_check(struct svm_test *test) return get_test_stage(test) == 3; } +static volatile int count_exc = 0; + +static void my_isr(struct ex_regs *r) +{ + count_exc++; +} + +static void exc_inject_prepare(struct svm_test *test) +{ + handle_exception(DE_VECTOR, my_isr); + handle_exception(NMI_VECTOR, my_isr); +} + + +static void exc_inject_test(struct svm_test *test) +{ + asm volatile ("vmmcall\n\tvmmcall\n\t"); +} + +static bool exc_inject_finished(struct svm_test *test) +{ + vmcb->save.rip += 3; + + switch (get_test_stage(test)) { + case 0: + if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { + report(false, "VMEXIT not due to vmmcall. Exit reason 0x%x", + vmcb->control.exit_code); + return true; + } + vmcb->control.event_inj = NMI_VECTOR | SVM_EVTINJ_TYPE_EXEPT | SVM_EVTINJ_VALID; + break; + + case 1: + if (vmcb->control.exit_code != SVM_EXIT_ERR) { + report(false, "VMEXIT not due to error. Exit reason 0x%x", + vmcb->control.exit_code); + return true; + } + report(count_exc == 0, "exception with vector 2 not injected"); + vmcb->control.event_inj = DE_VECTOR | SVM_EVTINJ_TYPE_EXEPT | SVM_EVTINJ_VALID; + break; + + case 2: + if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) { + report(false, "VMEXIT not due to vmmcall. Exit reason 0x%x", + vmcb->control.exit_code); + return true; + } + report(count_exc == 1, "divide overflow exception injected"); + report(!(vmcb->control.event_inj & SVM_EVTINJ_VALID), "eventinj.VALID cleared"); + break; + + default: + return true; + } + + inc_test_stage(test); + + return get_test_stage(test) == 3; +} + +static bool exc_inject_check(struct svm_test *test) +{ + return count_exc == 1 && get_test_stage(test) == 3; +} + #define TEST(name) { #name, .v2 = name } /* @@ -1615,6 +1682,9 @@ struct svm_test svm_tests[] = { { "latency_svm_insn", default_supported, lat_svm_insn_prepare, default_prepare_gif_clear, null_test, lat_svm_insn_finished, lat_svm_insn_check }, + { "exc_inject", default_supported, exc_inject_prepare, + default_prepare_gif_clear, exc_inject_test, + exc_inject_finished, exc_inject_check }, { "pending_event", default_supported, pending_event_prepare, default_prepare_gif_clear, pending_event_test, pending_event_finished, pending_event_check }, |