On 11/04/20 02:24, Krish Sadhukhan wrote: > > On 4/9/20 2:43 AM, Paolo Bonzini wrote: >> 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@xxxxxxxxxx> >> --- >> x86/svm.h | 7 +++++ >> x86/svm_tests.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 77 insertions(+) >> >> diff --git a/x86/svm.h b/x86/svm.h >> index 645deb7..bb5c552 100644 >> --- a/x86/svm.h >> +++ b/x86/svm.h >> @@ -324,6 +324,13 @@ struct __attribute__ ((__packed__)) vmcb { >> #define SVM_CR0_SELECTIVE_MASK (X86_CR0_TS | X86_CR0_MP) >> +#define SVM_EVENT_INJ_HWINT (0 << 8) >> +#define SVM_EVENT_INJ_NMI (2 << 8) >> +#define SVM_EVENT_INJ_EXC (3 << 8) >> +#define SVM_EVENT_INJ_SWINT (4 << 8) >> +#define SVM_EVENT_INJ_ERRCODE (1 << 11) >> +#define SVM_EVENT_INJ_VALID (1 << 31) > > > I see existing #defines in svm.h: > > #define SVM_EVTINJ_TYPE_INTR (0 << SVM_EVTINJ_TYPE_SHIFT) > #define SVM_EVTINJ_TYPE_NMI (2 << SVM_EVTINJ_TYPE_SHIFT) > #define SVM_EVTINJ_TYPE_EXEPT (3 << SVM_EVTINJ_TYPE_SHIFT) > #define SVM_EVTINJ_TYPE_SOFT (4 << SVM_EVTINJ_TYPE_SHIFT) > #define SVM_EVTINJ_VALID (1 << 31) > #define SVM_EVTINJ_VALID_ERR (1 << 11) Indeed. I queued the patch with these defines instead. Paolo >> + >> #define MSR_BITMAP_SIZE 8192 >> struct svm_test { >> diff --git a/x86/svm_tests.c b/x86/svm_tests.c >> index 16b9dfd..6292e68 100644 >> --- a/x86/svm_tests.c >> +++ b/x86/svm_tests.c >> @@ -1340,6 +1340,73 @@ static bool interrupt_check(struct svm_test *test) >> return get_test_stage(test) == 5; >> } >> +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_EVENT_INJ_EXC | >> SVM_EVENT_INJ_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_EVENT_INJ_EXC | >> SVM_EVENT_INJ_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_EVENT_INJ_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 } >> /* >> @@ -1446,6 +1513,9 @@ struct svm_test svm_tests[] = { >> { "interrupt", default_supported, interrupt_prepare, >> default_prepare_gif_clear, interrupt_test, >> interrupt_finished, interrupt_check }, >> + { "exc_inject", default_supported, exc_inject_prepare, >> + default_prepare_gif_clear, exc_inject_test, >> + exc_inject_finished, exc_inject_check }, >> TEST(svm_guest_state_test), >> { NULL, NULL, NULL, NULL, NULL, NULL, NULL } >> }; >