Re: [PATCH kvm-unit-tests] svm: add a test for exception injection

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 }
>>   };
> 




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux