All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jan Kiszka <jan.kiszka@web.de>
To: Arthur Chunqi Li <yzt356@gmail.com>
Cc: kvm@vger.kernel.org, gleb@redhat.com, pbonzini@redhat.com
Subject: Re: [PATCH 2/4] kvm-unit-tests: VMX: Add test cases for CR0/4 shadowing
Date: Thu, 15 Aug 2013 09:30:06 +0200	[thread overview]
Message-ID: <520C837E.7030407@web.de> (raw)
In-Reply-To: <1376409368-7016-3-git-send-email-yzt356@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 8260 bytes --]

On 2013-08-13 17:56, Arthur Chunqi Li wrote:
> Add testing for CR0/4 shadowing.

A few sentences on the test strategy would be good.

> 
> Signed-off-by: Arthur Chunqi Li <yzt356@gmail.com>
> ---
>  lib/x86/vm.h    |    4 +
>  x86/vmx_tests.c |  218 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 222 insertions(+)
> 
> diff --git a/lib/x86/vm.h b/lib/x86/vm.h
> index eff6f72..6e0ce2b 100644
> --- a/lib/x86/vm.h
> +++ b/lib/x86/vm.h
> @@ -17,9 +17,13 @@
>  #define PTE_ADDR    (0xffffffffff000ull)
>  
>  #define X86_CR0_PE      0x00000001
> +#define X86_CR0_MP      0x00000002
> +#define X86_CR0_TS      0x00000008
>  #define X86_CR0_WP      0x00010000
>  #define X86_CR0_PG      0x80000000
>  #define X86_CR4_VMXE   0x00000001
> +#define X86_CR4_TSD     0x00000004
> +#define X86_CR4_DE      0x00000008
>  #define X86_CR4_PSE     0x00000010
>  #define X86_CR4_PAE     0x00000020
>  #define X86_CR4_PCIDE  0x00020000
> diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
> index 61b0cef..44be3f4 100644
> --- a/x86/vmx_tests.c
> +++ b/x86/vmx_tests.c
> @@ -5,12 +5,18 @@
>  
>  u64 ia32_pat;
>  u64 ia32_efer;
> +u32 stage;
>  
>  static inline void vmcall()
>  {
>  	asm volatile("vmcall");
>  }
>  
> +static inline void set_stage(u32 s)
> +{
> +	asm volatile("mov %0, stage\n\t"::"r"(s):"memory", "cc");
> +}
> +

Why do we need "state = s" as assembler instruction?

>  void basic_init()
>  {
>  }
> @@ -257,6 +263,216 @@ static int test_ctrl_efer_exit_handler()
>  	return VMX_TEST_VMEXIT;
>  }
>  
> +u32 guest_cr0, guest_cr4;
> +
> +static void cr_shadowing_main()
> +{
> +	u32 cr0, cr4, tmp;
> +
> +	// Test read through
> +	set_stage(0);
> +	guest_cr0 = read_cr0();
> +	if (stage == 1)
> +		report("Read through CR0", 0);
> +	else
> +		vmcall();
> +	set_stage(1);
> +	guest_cr4 = read_cr4();
> +	if (stage == 2)
> +		report("Read through CR4", 0);
> +	else
> +		vmcall();
> +	// Test write through
> +	guest_cr0 = guest_cr0 ^ (X86_CR0_TS | X86_CR0_MP);
> +	guest_cr4 = guest_cr4 ^ (X86_CR4_TSD | X86_CR4_DE);
> +	set_stage(2);
> +	write_cr0(guest_cr0);
> +	if (stage == 3)
> +		report("Write throuth CR0", 0);
> +	else
> +		vmcall();
> +	set_stage(3);
> +	write_cr4(guest_cr4);
> +	if (stage == 4)
> +		report("Write through CR4", 0);
> +	else
> +		vmcall();
> +	// Test read shadow
> +	set_stage(4);
> +	vmcall();
> +	cr0 = read_cr0();
> +	if (stage != 5) {
> +		if (cr0 == guest_cr0)
> +			report("Read shadowing CR0", 1);
> +		else
> +			report("Read shadowing CR0", 0);
> +	}
> +	set_stage(5);
> +	cr4 = read_cr4();
> +	if (stage != 6) {
> +		if (cr4 == guest_cr4)
> +			report("Read shadowing CR4", 1);
> +		else
> +			report("Read shadowing CR4", 0);
> +	}
> +	// Test write shadow (same value with shadow)
> +	set_stage(6);
> +	write_cr0(guest_cr0);
> +	if (stage == 7)
> +		report("Write shadowing CR0 (same value with shadow)", 0);
> +	else
> +		vmcall();
> +	set_stage(7);
> +	write_cr4(guest_cr4);
> +	if (stage == 8)
> +		report("Write shadowing CR4 (same value with shadow)", 0);
> +	else
> +		vmcall();
> +	// Test write shadow (different value)
> +	set_stage(8);
> +	tmp = guest_cr0 ^ X86_CR0_TS;
> +	asm volatile("mov %0, %%rsi\n\t"
> +		"mov %%rsi, %%cr0\n\t"
> +		::"m"(tmp)
> +		:"rsi", "memory", "cc");
> +	if (stage != 9)
> +		report("Write shadowing different X86_CR0_TS", 0);
> +	else
> +		report("Write shadowing different X86_CR0_TS", 1);
> +	set_stage(9);
> +	tmp = guest_cr0 ^ X86_CR0_MP;
> +	asm volatile("mov %0, %%rsi\n\t"
> +		"mov %%rsi, %%cr0\n\t"
> +		::"m"(tmp)
> +		:"rsi", "memory", "cc");
> +	if (stage != 10)
> +		report("Write shadowing different X86_CR0_MP", 0);
> +	else
> +		report("Write shadowing different X86_CR0_MP", 1);
> +	set_stage(10);
> +	tmp = guest_cr4 ^ X86_CR4_TSD;
> +	asm volatile("mov %0, %%rsi\n\t"
> +		"mov %%rsi, %%cr4\n\t"
> +		::"m"(tmp)
> +		:"rsi", "memory", "cc");
> +	if (stage != 11)
> +		report("Write shadowing different X86_CR4_TSD", 0);
> +	else
> +		report("Write shadowing different X86_CR4_TSD", 1);
> +	set_stage(11);
> +	tmp = guest_cr4 ^ X86_CR4_DE;
> +	asm volatile("mov %0, %%rsi\n\t"
> +		"mov %%rsi, %%cr4\n\t"
> +		::"m"(tmp)
> +		:"rsi", "memory", "cc");
> +	if (stage != 12)
> +		report("Write shadowing different X86_CR4_DE", 0);
> +	else
> +		report("Write shadowing different X86_CR4_DE", 1);
> +}
> +
> +static int cr_shadowing_exit_handler()
> +{
> +	u64 guest_rip;
> +	ulong reason;
> +	u32 insn_len;
> +	u32 exit_qual;
> +
> +	guest_rip = vmcs_read(GUEST_RIP);
> +	reason = vmcs_read(EXI_REASON) & 0xff;
> +	insn_len = vmcs_read(EXI_INST_LEN);
> +	exit_qual = vmcs_read(EXI_QUALIFICATION);
> +	switch (reason) {
> +	case VMX_VMCALL:
> +		switch (stage) {
> +		case 0:
> +			if (guest_cr0 == vmcs_read(GUEST_CR0))
> +				report("Read through CR0", 1);
> +			else
> +				report("Read through CR0", 0);
> +			break;
> +		case 1:
> +			if (guest_cr4 == vmcs_read(GUEST_CR4))
> +				report("Read through CR4", 1);
> +			else
> +				report("Read through CR4", 0);
> +			break;
> +		case 2:
> +			if (guest_cr0 == vmcs_read(GUEST_CR0))
> +				report("Write through CR0", 1);
> +			else
> +				report("Write through CR0", 0);
> +			break;
> +		case 3:
> +			if (guest_cr4 == vmcs_read(GUEST_CR4))
> +				report("Write through CR4", 1);
> +			else
> +				report("Write through CR4", 0);
> +			break;
> +		case 4:
> +			guest_cr0 = vmcs_read(GUEST_CR0) ^ (X86_CR0_TS | X86_CR0_MP);
> +			guest_cr4 = vmcs_read(GUEST_CR4) ^ (X86_CR4_TSD | X86_CR4_DE);
> +			vmcs_write(CR0_MASK, X86_CR0_TS | X86_CR0_MP);
> +			vmcs_write(CR0_READ_SHADOW, guest_cr0 & (X86_CR0_TS | X86_CR0_MP));
> +			vmcs_write(CR4_MASK, X86_CR4_TSD | X86_CR4_DE);
> +			vmcs_write(CR4_READ_SHADOW, guest_cr4 & (X86_CR4_TSD | X86_CR4_DE));
> +			break;
> +		case 6:
> +			if (guest_cr0 == (vmcs_read(GUEST_CR0) ^ (X86_CR0_TS | X86_CR0_MP)))
> +				report("Write shadowing CR0 (same value)", 1);
> +			else
> +				report("Write shadowing CR0 (same value)", 0);
> +			break;
> +		case 7:
> +			if (guest_cr4 == (vmcs_read(GUEST_CR4) ^ (X86_CR4_TSD | X86_CR4_DE)))
> +				report("Write shadowing CR4 (same value)", 1);
> +			else
> +				report("Write shadowing CR4 (same value)", 0);
> +			break;
> +		default:

report("something went wrong", 0); ???

> +			break;
> +		}
> +		vmcs_write(GUEST_RIP, guest_rip + insn_len);
> +		return VMX_TEST_RESUME;
> +	case VMX_CR:
> +		switch (stage) {
> +		case 4:
> +			report("Read shadowing CR0", 0);
> +			set_stage(stage + 1);
> +			break;
> +		case 5:
> +			report("Read shadowing CR4", 0);
> +			set_stage(stage + 1);
> +			break;
> +		case 6:
> +			report("Write shadowing CR0 (same value)", 0);
> +			set_stage(stage + 1);
> +			break;
> +		case 7:
> +			report("Write shadowing CR4 (same value)", 0);
> +			set_stage(stage + 1);
> +			break;
> +		case 8:
> +		case 9:
> +			if (exit_qual == 0x600)
> +				set_stage(stage + 1);

What is this qualification about? Yes, ESI to CR0, but that takes a
manual to find out. And what if exit_qual is something else? Is that a
test error?

> +			break;
> +		case 10:
> +		case 11:
> +			if (exit_qual == 0x604)
> +				set_stage(stage + 1);

Same as above.

> +		default:

...?

> +			break;
> +		}
> +		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[] = {
> @@ -268,5 +484,7 @@ struct vmx_test vmx_tests[] = {
>  		test_ctrl_pat_exit_handler, basic_syscall_handler, {0} },
>  	{ "control field EFER", test_ctrl_efer_init, test_ctrl_efer_main,
>  		test_ctrl_efer_exit_handler, basic_syscall_handler, {0} },
> +	{ "CR shadowing", basic_init, cr_shadowing_main,
> +		cr_shadowing_exit_handler, basic_syscall_handler, {0} },
>  	{ NULL, NULL, NULL, NULL, NULL, {0} },
>  };
> 

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 263 bytes --]

  reply	other threads:[~2013-08-15  7:30 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-13 15:56 [PATCH 0/4] kvm-unit-tests: Add a series of test cases Arthur Chunqi Li
2013-08-13 15:56 ` [PATCH 1/4] kvm-unit-tests: VMX: Add test cases for PAT and EFER Arthur Chunqi Li
2013-08-15  7:17   ` Jan Kiszka
2013-08-15  7:41     ` Arthur Chunqi Li
2013-08-15  7:48       ` Jan Kiszka
2013-08-15  8:05         ` Arthur Chunqi Li
2013-08-15  8:09           ` Jan Kiszka
2013-08-13 15:56 ` [PATCH 2/4] kvm-unit-tests: VMX: Add test cases for CR0/4 shadowing Arthur Chunqi Li
2013-08-15  7:30   ` Jan Kiszka [this message]
2013-08-15  7:40     ` Arthur Chunqi Li
2013-08-15  7:47       ` Jan Kiszka
2013-08-15  7:59         ` Arthur Chunqi Li
2013-08-15  8:07           ` Jan Kiszka
2013-08-18 14:07           ` Paolo Bonzini
2013-08-18 14:32             ` Gmail
2013-08-13 15:56 ` [PATCH 3/4] kvm-unit-tests: VMX: Add test cases for I/O bitmaps Arthur Chunqi Li
2013-08-15  7:40   ` Jan Kiszka
2013-08-15  7:51     ` Arthur Chunqi Li
2013-08-15  7:58       ` Jan Kiszka
2013-08-15  8:09         ` Arthur Chunqi Li
2013-08-15  8:13           ` Jan Kiszka
2013-08-15  8:20             ` Arthur Chunqi Li
2013-08-15  8:23               ` Jan Kiszka
2013-08-15 10:43                 ` Arthur Chunqi Li
2013-08-13 15:56 ` [PATCH 4/4] kvm-unit-tests: VMX: Add test cases for instruction interception Arthur Chunqi Li
2013-08-15  8:06   ` Jan Kiszka
2013-08-15  8:16     ` Arthur Chunqi Li
2013-08-15  8:20       ` Jan Kiszka
2013-08-15  8:35         ` Arthur Chunqi Li
2013-08-15  8:40           ` Jan Kiszka
2013-08-15  8:48             ` Arthur Chunqi Li
2013-08-15  9:15               ` Jan Kiszka

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=520C837E.7030407@web.de \
    --to=jan.kiszka@web.de \
    --cc=gleb@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --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.