All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: Arthur Chunqi Li <yzt356@gmail.com>
Cc: kvm@vger.kernel.org, jan.kiszka@web.de, gleb@redhat.com
Subject: Re: [PATCH v2] kvm-unit-tests: VMX: Test suite for preemption timer
Date: Mon, 09 Sep 2013 15:59:27 +0200	[thread overview]
Message-ID: <522DD43F.5010407@redhat.com> (raw)
In-Reply-To: <1378433506-18401-1-git-send-email-yzt356@gmail.com>

Il 06/09/2013 04:11, Arthur Chunqi Li ha scritto:
> Test cases for preemption timer in nested VMX. Two aspects are tested:
> 1. Save preemption timer on VMEXIT if relevant bit set in EXIT_CONTROL
> 2. Test a relevant bug of KVM. The bug will not save preemption timer
> value if exit L2->L0 for some reason and enter L0->L2. Thus preemption
> timer will never trigger if the value is large enough.
> 3. Some other aspects are tested, e.g. preempt without save, preempt
> when value is 0.
> 
> Signed-off-by: Arthur Chunqi Li <yzt356@gmail.com>
> ---
> ChangeLog to v1:
> 1. Add test of EXI_SAVE_PREEMPT enable and PIN_PREEMPT disable
> 2. Add test of PIN_PREEMPT enable and EXI_SAVE_PREEMPT enable/disable
> 3. Add test of preemption value is 0

The patch looks good, however we have now 3 series that are conflicting
(basic tests, EPT, preemption timer).

I ordered them and pushed them to "vmx" branch of kvm-unit-tests.git.
Can you send them as a single series from now on?

Thanks,

Paolo

>  x86/vmx.h       |    3 +
>  x86/vmx_tests.c |  175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 178 insertions(+)
> 
> diff --git a/x86/vmx.h b/x86/vmx.h
> index 28595d8..ebc8cfd 100644
> --- a/x86/vmx.h
> +++ b/x86/vmx.h
> @@ -210,6 +210,7 @@ enum Encoding {
>  	GUEST_ACTV_STATE	= 0x4826ul,
>  	GUEST_SMBASE		= 0x4828ul,
>  	GUEST_SYSENTER_CS	= 0x482aul,
> +	PREEMPT_TIMER_VALUE	= 0x482eul,
>  
>  	/* 32-Bit Host State Fields */
>  	HOST_SYSENTER_CS	= 0x4c00ul,
> @@ -331,6 +332,7 @@ enum Ctrl_exi {
>  	EXI_LOAD_PERF		= 1UL << 12,
>  	EXI_INTA                = 1UL << 15,
>  	EXI_LOAD_EFER           = 1UL << 21,
> +	EXI_SAVE_PREEMPT	= 1UL << 22,
>  };
>  
>  enum Ctrl_ent {
> @@ -342,6 +344,7 @@ enum Ctrl_pin {
>  	PIN_EXTINT              = 1ul << 0,
>  	PIN_NMI                 = 1ul << 3,
>  	PIN_VIRT_NMI            = 1ul << 5,
> +	PIN_PREEMPT		= 1ul << 6,
>  };
>  
>  enum Ctrl0 {
> diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
> index c1b39f4..2e32031 100644
> --- a/x86/vmx_tests.c
> +++ b/x86/vmx_tests.c
> @@ -1,4 +1,30 @@
>  #include "vmx.h"
> +#include "msr.h"
> +#include "processor.h"
> +
> +volatile u32 stage;
> +
> +static inline void vmcall()
> +{
> +	asm volatile("vmcall");
> +}
> + 
> +static inline void set_stage(u32 s)
> +{
> +	barrier();
> +	stage = s;
> +	barrier();
> +}
> +
> +static inline u32 get_stage()
> +{
> +	u32 s;
> +
> +	barrier();
> +	s = stage;
> +	barrier();
> +	return s;
> +}
>  
>  void basic_init()
>  {
> @@ -76,6 +102,153 @@ int vmenter_exit_handler()
>  	return VMX_TEST_VMEXIT;
>  }
>  
> +u32 preempt_scale;
> +volatile unsigned long long tsc_val;
> +volatile u32 preempt_val;
> +
> +void preemption_timer_init()
> +{
> +	u32 ctrl_exit;
> +
> +	// Enable EXI_SAVE_PREEMPT with PIN_PREEMPT dieabled
> +	ctrl_exit = (vmcs_read(EXI_CONTROLS) |
> +			EXI_SAVE_PREEMPT) & ctrl_exit_rev.clr;
> +	vmcs_write(EXI_CONTROLS, ctrl_exit);
> +	preempt_val = 10000000;
> +	vmcs_write(PREEMPT_TIMER_VALUE, preempt_val);
> +	set_stage(0);
> +	preempt_scale = rdmsr(MSR_IA32_VMX_MISC) & 0x1F;
> +}
> +
> +void preemption_timer_main()
> +{
> +	int i, j;
> +
> +	if (!(ctrl_pin_rev.clr & PIN_PREEMPT)) {
> +		printf("\tPreemption timer is not supported\n");
> +		return;
> +	}
> +	if (!(ctrl_exit_rev.clr & EXI_SAVE_PREEMPT))
> +		printf("\tSave preemption value is not supported\n");
> +	else {
> +		// Test EXI_SAVE_PREEMPT enable and PIN_PREEMPT disable
> +		set_stage(0);
> +		// Consume enough time to let L2->L0->L2 occurs
> +		for(i = 0; i < 100000; i++)
> +			for (j = 0; j < 10000; j++);
> +		vmcall();
> +		// Test PIN_PREEMPT enable and EXI_SAVE_PREEMPT enable/disable
> +		set_stage(1);
> +		vmcall();
> +		// Test both enable
> +		if (get_stage() == 2)
> +			vmcall();
> +	}
> +	// Test the bug of reseting preempt value when L2->L0->L2
> +	set_stage(3);
> +	vmcall();
> +	tsc_val = rdtsc();
> +	while (1) {
> +		if (((rdtsc() - tsc_val) >> preempt_scale)
> +				> 10 * preempt_val) {
> +			report("Preemption timer timeout", 0);
> +			break;
> +		}
> +		if (get_stage() == 4)
> +			break;
> +	}
> +	// Test preempt val is 0
> +	set_stage(4);
> +	report("Preemption timer, val=0", 0);
> +}
> +
> +int preemption_timer_exit_handler()
> +{
> +	u64 guest_rip;
> +	ulong reason;
> +	u32 insn_len;
> +	u32 ctrl_exit;
> +	u32 ctrl_pin;
> +
> +	guest_rip = vmcs_read(GUEST_RIP);
> +	reason = vmcs_read(EXI_REASON) & 0xff;
> +	insn_len = vmcs_read(EXI_INST_LEN);
> +	switch (reason) {
> +	case VMX_PREEMPT:
> +		switch (get_stage()) {
> +		case 3:
> +			if (((rdtsc() - tsc_val) >> preempt_scale) < preempt_val)
> +				report("Preemption timer timeout", 0);
> +			else
> +				report("Preemption timer timeout", 1);
> +			set_stage(get_stage() + 1);
> +			break;
> +		case 4:
> +			if (vmcs_read(PREEMPT_TIMER_VALUE) == 0)
> +				report("Preemption timer, val=0", 1);
> +			else
> +				report("Preemption timer, val=0", 0);
> +			return VMX_TEST_VMEXIT;
> +		}
> +		return VMX_TEST_RESUME;
> +	case VMX_VMCALL:
> +		switch (get_stage()) {
> +		case 0:
> +			if (vmcs_read(PREEMPT_TIMER_VALUE) != preempt_val)
> +				report("Preemption timer off", 0);
> +			else
> +				report("Preemption timer off", 1);
> +			// Enable PIN_PREEMPT and disable EXI_SAVE_PREEMPT
> +			ctrl_pin = (vmcs_read(PIN_CONTROLS) | PIN_PREEMPT) &
> +					ctrl_pin_rev.clr;
> +			vmcs_write(PIN_CONTROLS, ctrl_pin);
> +			ctrl_exit = (vmcs_read(EXI_CONTROLS) &
> +					~EXI_SAVE_PREEMPT) & ctrl_exit_rev.clr;
> +			vmcs_write(EXI_CONTROLS, ctrl_exit);
> +			vmcs_write(PREEMPT_TIMER_VALUE, preempt_val);
> +			break;
> +		case 1:
> +			if (vmcs_read(PREEMPT_TIMER_VALUE) != preempt_val)
> +				report("Save preemption value", 0);
> +			else {
> +				set_stage(get_stage() + 1);
> +				// Enable EXI_SAVE_PREEMPT with PIN_PREEMPT
> +				// already enabled
> +				ctrl_exit = (vmcs_read(EXI_CONTROLS) |
> +					EXI_SAVE_PREEMPT) & ctrl_exit_rev.clr;
> +				vmcs_write(EXI_CONTROLS, ctrl_exit);
> +			}
> +			vmcs_write(PREEMPT_TIMER_VALUE, preempt_val);
> +			break;
> +		case 2:
> +			if (vmcs_read(PREEMPT_TIMER_VALUE) >= preempt_val)
> +				report("Save preemption value", 0);
> +			else
> +				report("Save preemption value", 1);
> +			break;
> +		case 3:
> +			vmcs_write(PREEMPT_TIMER_VALUE, preempt_val);
> +			ctrl_pin = (vmcs_read(PIN_CONTROLS) | PIN_PREEMPT) &
> +					ctrl_pin_rev.clr;
> +			vmcs_write(PIN_CONTROLS, ctrl_pin);
> +			ctrl_exit = (vmcs_read(EXI_CONTROLS) |
> +					EXI_SAVE_PREEMPT) & ctrl_exit_rev.clr;
> +			vmcs_write(EXI_CONTROLS, ctrl_exit);
> +			break;
> +		default:
> +			printf("Invalid stage.\n");
> +			print_vmexit_info();
> +			return VMX_TEST_VMEXIT;
> +		}
> +		vmcs_write(GUEST_RIP, guest_rip + insn_len);
> +		return VMX_TEST_RESUME;
> +	default:
> +		printf("Unknown exit reason, %d\n", reason);
> +		print_vmexit_info();
> +	}
> +	return VMX_TEST_VMEXIT;
> +}
> +
>  /* name/init/guest_main/exit_handler/syscall_handler/guest_regs
>     basic_* just implement some basic functions */
>  struct vmx_test vmx_tests[] = {
> @@ -83,5 +256,7 @@ struct vmx_test vmx_tests[] = {
>  		basic_syscall_handler, {0} },
>  	{ "vmenter", basic_init, vmenter_main, vmenter_exit_handler,
>  		basic_syscall_handler, {0} },
> +	{ "preemption timer", preemption_timer_init, preemption_timer_main,
> +		preemption_timer_exit_handler, basic_syscall_handler, {0} },
>  	{ NULL, NULL, NULL, NULL, NULL, {0} },
>  };
> 


      reply	other threads:[~2013-09-09 13:59 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-09-06  2:11 [PATCH v2] kvm-unit-tests: VMX: Test suite for preemption timer Arthur Chunqi Li
2013-09-09 13:59 ` Paolo Bonzini [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=522DD43F.5010407@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=gleb@redhat.com \
    --cc=jan.kiszka@web.de \
    --cc=kvm@vger.kernel.org \
    --cc=yzt356@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.