Re: [kvm-unit-tests PATCH v4 1/2] nSVM: Add helper to report fatal errors in guest

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

 



On 05.04.23 22:51, Sean Christopherson wrote:
> Add a helper macro to dedup nSVM test code that handles fatal errors
> by reporting the failure, setting the test stage to a magic number, and
> invoking VMMCALL to bail to the host and terminate.
> 
> Note, the V_TPR fails if report() is invoked.  Punt on the issue for
> now as most users already report only failures, but leave a TODO for
> future developers.
> 
> Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
> ---
>  x86/svm_tests.c | 127 ++++++++++++++++--------------------------------
>  1 file changed, 42 insertions(+), 85 deletions(-)
> 
> diff --git a/x86/svm_tests.c b/x86/svm_tests.c
> index 27ce47b4..e87db3fa 100644
> --- a/x86/svm_tests.c
> +++ b/x86/svm_tests.c
> @@ -947,6 +947,21 @@ static bool lat_svm_insn_check(struct svm_test *test)
>  	return true;
>  }
>  
> +/*
> + * Report failures from SVM guest code, and on failure, set the stage to -1 and
> + * do VMMCALL to terminate the test (host side must treat -1 as "finished").
> + * TODO: fix the tests that don't play nice with a straight report, e.g. the
> + * V_TPR test fails if report() is invoked.
> + */
> +#define report_svm_guest(cond, test, fmt, args...)	\
> +do {							\
> +	if (!(cond)) {					\

> +		report_fail("why didn't my format '" fmt "' format?", ##args);\
                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Debug artifact? Should probably be this instead (making use of C99):

   #define report_svm_guest(cond, test, fmt,...)	\
   do {							\
    	if (!(cond)) {					\
   		report_fail((fmt), ##__VA_ARGS__);	\
   		set_test_stage((test), -1);		\
   		vmmcall();				\
   	}						\
   } while (0)

> +		set_test_stage(test, -1);		\
> +		vmmcall();				\
> +	}						\
> +} while (0)
> +
>  bool pending_event_ipi_fired;
>  bool pending_event_guest_run;
>  
> @@ -1049,22 +1064,16 @@ static void pending_event_cli_prepare_gif_clear(struct svm_test *test)
>  
>  static void pending_event_cli_test(struct svm_test *test)
>  {
> -	if (pending_event_ipi_fired == true) {
> -		set_test_stage(test, -1);
> -		report_fail("Interrupt preceeded guest");
> -		vmmcall();
> -	}
> +	report_svm_guest(!pending_event_ipi_fired, test,
> +			 "IRQ should NOT be delivered while IRQs disabled");
>  
>  	/* VINTR_MASKING is zero.  This should cause the IPI to fire.  */
>  	irq_enable();
>  	asm volatile ("nop");
>  	irq_disable();
>  
> -	if (pending_event_ipi_fired != true) {
> -		set_test_stage(test, -1);
> -		report_fail("Interrupt not triggered by guest");
> -	}
> -
> +	report_svm_guest(pending_event_ipi_fired, test,
> +			 "IRQ should be delivered after enabling IRQs");
>  	vmmcall();
>  
>  	/*
> @@ -1079,11 +1088,9 @@ static void pending_event_cli_test(struct svm_test *test)
>  
>  static bool pending_event_cli_finished(struct svm_test *test)
>  {
> -	if ( vmcb->control.exit_code != SVM_EXIT_VMMCALL) {
> -		report_fail("VM_EXIT return to host is not EXIT_VMMCALL exit reason 0x%x",
> -			    vmcb->control.exit_code);
> -		return true;
> -	}
> +	report_svm_guest(vmcb->control.exit_code == SVM_EXIT_VMMCALL, test,
> +			 "Wanted VMMCALL VM-Exit, got ext reason 0x%x",
> +			 vmcb->control.exit_code);
>  
>  	switch (get_test_stage(test)) {
>  	case 0:
> @@ -1158,12 +1165,8 @@ static void interrupt_test(struct svm_test *test)
>  	for (loops = 0; loops < 10000000 && !timer_fired; loops++)
>  		asm volatile ("nop");
>  
> -	report(timer_fired, "direct interrupt while running guest");
> -
> -	if (!timer_fired) {
> -		set_test_stage(test, -1);
> -		vmmcall();
> -	}
> +	report_svm_guest(timer_fired, test,
> +			 "direct interrupt while running guest");
>  
>  	apic_write(APIC_TMICT, 0);
>  	irq_disable();
> @@ -1174,12 +1177,8 @@ static void interrupt_test(struct svm_test *test)
>  	for (loops = 0; loops < 10000000 && !timer_fired; loops++)
>  		asm volatile ("nop");
>  
> -	report(timer_fired, "intercepted interrupt while running guest");
> -
> -	if (!timer_fired) {
> -		set_test_stage(test, -1);
> -		vmmcall();
> -	}
> +	report_svm_guest(timer_fired, test,
> +			 "intercepted interrupt while running guest");
>  
>  	irq_enable();
>  	apic_write(APIC_TMICT, 0);
> @@ -1190,13 +1189,8 @@ static void interrupt_test(struct svm_test *test)
>  	apic_write(APIC_TMICT, 1000000);
>  	safe_halt();
>  
> -	report(rdtsc() - start > 10000 && timer_fired,
> -	       "direct interrupt + hlt");
> -
> -	if (!timer_fired) {
> -		set_test_stage(test, -1);
> -		vmmcall();
> -	}
> +	report_svm_guest(timer_fired, test, "direct interrupt + hlt");
> +	report(rdtsc() - start > 10000, "IRQ arrived after expected delay");
>  
>  	apic_write(APIC_TMICT, 0);
>  	irq_disable();
> @@ -1207,13 +1201,8 @@ static void interrupt_test(struct svm_test *test)
>  	apic_write(APIC_TMICT, 1000000);
>  	asm volatile ("hlt");
>  
> -	report(rdtsc() - start > 10000 && timer_fired,
> -	       "intercepted interrupt + hlt");
> -
> -	if (!timer_fired) {
> -		set_test_stage(test, -1);
> -		vmmcall();
> -	}
> +	report_svm_guest(timer_fired, test, "intercepted interrupt + hlt");
> +	report(rdtsc() - start > 10000, "IRQ arrived after expected delay");
>  
>  	apic_write(APIC_TMICT, 0);
>  	irq_disable();
> @@ -1287,10 +1276,7 @@ static void nmi_test(struct svm_test *test)
>  {
>  	apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, 0);
>  
> -	report(nmi_fired, "direct NMI while running guest");
> -
> -	if (!nmi_fired)
> -		set_test_stage(test, -1);
> +	report_svm_guest(nmi_fired, test, "direct NMI while running guest");
>  
>  	vmmcall();
>  
> @@ -1298,11 +1284,7 @@ static void nmi_test(struct svm_test *test)
>  
>  	apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, 0);
>  
> -	if (!nmi_fired) {
> -		report(nmi_fired, "intercepted pending NMI not dispatched");
> -		set_test_stage(test, -1);
> -	}
> -
> +	report_svm_guest(nmi_fired, test, "intercepted pending NMI delivered to guest");
>  }
>  
>  static bool nmi_finished(struct svm_test *test)
> @@ -1379,11 +1361,8 @@ static void nmi_hlt_test(struct svm_test *test)
>  
>  	asm volatile ("hlt");
>  
> -	report((rdtsc() - start > NMI_DELAY) && nmi_fired,
> -	       "direct NMI + hlt");
> -
> -	if (!nmi_fired)
> -		set_test_stage(test, -1);
> +	report_svm_guest(nmi_fired, test, "direct NMI + hlt");
> +	report(rdtsc() - start > NMI_DELAY, "direct NMI after expected delay");
>  
>  	nmi_fired = false;
>  
> @@ -1395,14 +1374,8 @@ static void nmi_hlt_test(struct svm_test *test)
>  
>  	asm volatile ("hlt");
>  
> -	report((rdtsc() - start > NMI_DELAY) && nmi_fired,
> -	       "intercepted NMI + hlt");
> -
> -	if (!nmi_fired) {
> -		report(nmi_fired, "intercepted pending NMI not dispatched");
> -		set_test_stage(test, -1);
> -		vmmcall();
> -	}
> +	report_svm_guest(nmi_fired, test, "intercepted NMI + hlt");
> +	report(rdtsc() - start > NMI_DELAY, "intercepted NMI after expected delay");
>  
>  	set_test_stage(test, 3);
>  }
> @@ -1534,37 +1507,23 @@ static void virq_inject_prepare(struct svm_test *test)
>  
>  static void virq_inject_test(struct svm_test *test)
>  {
> -	if (virq_fired) {
> -		report_fail("virtual interrupt fired before L2 sti");
> -		set_test_stage(test, -1);
> -		vmmcall();
> -	}
> +	report_svm_guest(!virq_fired, test, "virtual IRQ blocked after L2 cli");
>  
>  	irq_enable();
>  	asm volatile ("nop");
>  	irq_disable();
>  
> -	if (!virq_fired) {
> -		report_fail("virtual interrupt not fired after L2 sti");
> -		set_test_stage(test, -1);
> -	}
> +	report_svm_guest(virq_fired, test, "virtual IRQ fired after L2 sti");
>  
>  	vmmcall();
>  
> -	if (virq_fired) {
> -		report_fail("virtual interrupt fired before L2 sti after VINTR intercept");
> -		set_test_stage(test, -1);
> -		vmmcall();
> -	}
> +	report_svm_guest(!virq_fired, test, "intercepted VINTR blocked after L2 cli");
>  
>  	irq_enable();
>  	asm volatile ("nop");
>  	irq_disable();
>  
> -	if (!virq_fired) {
> -		report_fail("virtual interrupt not fired after return from VINTR intercept");
> -		set_test_stage(test, -1);
> -	}
> +	report_svm_guest(virq_fired, test, "intercepted VINTR fired after L2 sti");
>  
>  	vmmcall();
>  
> @@ -1572,10 +1531,8 @@ static void virq_inject_test(struct svm_test *test)
>  	asm volatile ("nop");
>  	irq_disable();
>  
> -	if (virq_fired) {
> -		report_fail("virtual interrupt fired when V_IRQ_PRIO less than V_TPR");
> -		set_test_stage(test, -1);
> -	}
> +	report_svm_guest(!virq_fired, test,
> +			  "virtual IRQ blocked V_IRQ_PRIO less than V_TPR");
>  
>  	vmmcall();
>  	vmmcall();



[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