All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gleb Natapov <gleb@redhat.com>
To: Arthur Chunqi Li <yzt356@gmail.com>
Cc: kvm@vger.kernel.org, pbonzini@redhat.com
Subject: Re: [PATCH 1/2] kvm-unit-tests: Add a func to run instruction in emulator
Date: Mon, 10 Jun 2013 20:36:55 +0300	[thread overview]
Message-ID: <20130610173654.GM29022@redhat.com> (raw)
In-Reply-To: <1370871513-31815-1-git-send-email-yzt356@gmail.com>

On Mon, Jun 10, 2013 at 09:38:32PM +0800, Arthur Chunqi Li wrote:
> Add a function trap_emulator to run an instruction in emulator.
> Set inregs first (%rax is invalid because it is used as return
> address), put instruction codec in alt_insn and call func with
> alt_insn_length. Get results in outregs.
> 
That's far from what I meant :( As I said before inregs/outregs should
contain r[0-7] too so you cannot use then as tmp vars to save %rbp/%rsp.
My ideas is that the code to save/restore register (all the xchg
instructions) should be part of the code in insn_page/alt_insn_page.
Instead of call in the middle just put trapping instruction there on
insn_page (in  (%dx),%al is a good one) padded with nops to the max
instruction length. alt_insn_page will have an instruction we want to
test at the same offset. This way you can call insn_page freely since
stack register during entry and return are unchanged, all the register
are saved and restored by the code on insn_page itself.

> Signed-off-by: Arthur Chunqi Li <yzt356@gmail.com>
> ---
>  x86/emulator.c |  106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 106 insertions(+)
> 
> diff --git a/x86/emulator.c b/x86/emulator.c
> index 96576e5..a1bd92e 100644
> --- a/x86/emulator.c
> +++ b/x86/emulator.c
> @@ -11,6 +11,13 @@ int fails, tests;
>  
>  static int exceptions;
>  
> +struct regs {
> +	u64 rax, rbx, rcx, rdx;
> +	u64 rsi, rdi, rsp, rbp;
> +	u64 rip, rflags;
> +};
> +static struct regs inregs, outregs;
> +
>  void report(const char *name, int result)
>  {
>  	++tests;
> @@ -685,6 +692,105 @@ static void test_shld_shrd(u32 *mem)
>      report("shrd (cl)", *mem == ((0x12345678 >> 3) | (5u << 29)));
>  }
>  
> +static void trap_emulator(uint64_t *mem, uint8_t *insn_page,
> +			     uint8_t *alt_insn_page, void *insn_ram,
> +			     uint8_t* alt_insn, int alt_insn_length, int reserve_stack)
> +{
> +	ulong *cr3 = (ulong *)read_cr3();
> +	int i;
> +	static struct regs save;
> +
> +	// Pad with RET instructions
> +	memset(insn_page, 0x90, 4096);
> +	memset(alt_insn_page, 0x90, 4096);
> +
> +	asm volatile(
> +		"movw $1, %0\n\t"
> +		: : "m"(mem)
> +		: "memory"
> +		);
> +	// Place a trapping instruction in the page to trigger a VMEXIT
> +	insn_page[0] = 0xc3; // ret
> +	if (!reserve_stack)
> +	{
> +		insn_page[1] = 0x49; // xchg   %rsp,%r9
> +		insn_page[2] = 0x87;
> +		insn_page[3] = 0xe1;
> +		insn_page[4] = 0x49; // xchg   %rbp,%r10
> +		insn_page[5] = 0x87;
> +		insn_page[6] = 0xea;
> +	}
> +	//in  (%dx),%al, may change in the future
> +	insn_page[7] = 0xec;
> +
> +	// Place the instruction we want the hypervisor to see in the alternate page
> +	for (i=7; i<alt_insn_length+7; i++)
> +		alt_insn_page[i] = alt_insn[i-7];
> +
> +	if (!reserve_stack)
> +	{
> +		insn_page[i+0] = 0x49; // xchg   %rsp,%r9
> +		insn_page[i+1] = 0x87;
> +		insn_page[i+2] = 0xe1;
> +		insn_page[i+3] = 0x49; // xchg   %rbp,%r10
> +		insn_page[i+4] = 0x87;
> +		insn_page[i+5] = 0xea;
> +	}
> +	else
> +	{
> +		insn_page[i+0] = 0x49; // mov   %rsp,%r9
> +		insn_page[i+1] = 0x89;
> +		insn_page[i+2] = 0xe1;
> +		insn_page[i+3] = 0x49; // mov   %rbp,%r10
> +		insn_page[i+4] = 0x89;
> +		insn_page[i+5] = 0xea;
> +	}
> +	insn_page[i+6] = 0xc3; // ret
> +
> +	save = inregs;
> +	
> +	// Load the code TLB with insn_page, but point the page tables at
> +	// alt_insn_page (and keep the data TLB clear, for AMD decode assist).
> +	// This will make the CPU trap on the insn_page instruction but the
> +	// hypervisor will see alt_insn_page.
> +	install_page(cr3, virt_to_phys(insn_page), insn_ram);
> +	invlpg(insn_ram);
> +	// Load code TLB
> +	asm volatile("call *%0" : : "r"(insn_ram));
> +	install_page(cr3, virt_to_phys(alt_insn_page), insn_ram);
> +	// Trap, let hypervisor emulate at alt_insn_page
> +	asm volatile(
> +		"push 72+%[save]; popf\n\t"
> +		"mov %2, %%r8\n\t"
> +		"xchg %%rax, 0+%[save] \n\t"
> +		"xchg %%rbx, 8+%[save] \n\t"
> +		"xchg %%rcx, 16+%[save] \n\t"
> +		"xchg %%rdx, 24+%[save] \n\t"
> +		"xchg %%rsi, 32+%[save] \n\t"
> +		"xchg %%rdi, 40+%[save] \n\t"
> +		"xchg %%r9, 48+%[save]\n\t"
> +		"xchg %%r10, 56+%[save]\n\t"
> +
> +		"call *%1\n\t"
> +
> +		"xchg %%rax, 0+%[save] \n\t"
> +		"xchg %%rbx, 8+%[save] \n\t"
> +		"xchg %%rcx, 16+%[save] \n\t"
> +		"xchg %%rdx, 24+%[save] \n\t"
> +		"xchg %%rsi, 32+%[save] \n\t"
> +		"xchg %%rdi, 40+%[save] \n\t"
> +		"xchg %%r9, 48+%[save] \n\t"
> +		"xchg %%r10, 56+%[save] \n\t"
> +		/* Save RFLAGS in outregs*/
> +		"pushf \n\t"
> +		"pop 72+%[save] \n\t"
> +		: [save]"+m"(save)
> +		: "r"(insn_ram+1), "r"(mem)
> +		: "memory", "cc", "r8", "r9", "r10"
> +		);
> +	outregs = save;
> +}
> +
>  static void advance_rip_by_3_and_note_exception(struct ex_regs *regs)
>  {
>      ++exceptions;
> -- 
> 1.7.9.5

--
			Gleb.

  parent reply	other threads:[~2013-06-10 17:36 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-06-10 13:38 [PATCH 1/2] kvm-unit-tests: Add a func to run instruction in emulator Arthur Chunqi Li
2013-06-10 13:38 ` [PATCH 2/2] kvm-unit-tests: Change two cases to use trap_emulator Arthur Chunqi Li
2013-06-10 17:36 ` Gleb Natapov [this message]
  -- strict thread matches above, loose matches on Subject: below --
2013-06-20 10:45 [PATCH 1/2] kvm-unit-tests: Add a func to run instruction in emulator Arthur Chunqi Li
2013-06-20 10:47 ` Jan Kiszka
2013-06-20 12:32 ` Gleb Natapov
2013-06-19 15:00 Arthur Chunqi Li
2013-06-19 15:07 ` 李春奇 <Arthur Chunqi Li>
2013-06-19 16:03   ` Gleb Natapov
2013-06-19 17:48     ` Gmail
2013-06-20  5:42       ` Gleb Natapov
2013-06-20  8:29     ` Paolo Bonzini
2013-06-20  8:31       ` Gleb Natapov
2013-06-20  8:48 ` Gleb Natapov
2013-06-20  8:58   ` Gmail
2013-06-13 15:16 Arthur Chunqi Li
2013-06-07  2:31 Arthur Chunqi Li
2013-06-09 11:07 ` Gleb Natapov
2013-06-09 12:44   ` 李春奇 <Arthur Chunqi Li>
2013-06-09 12:49     ` Gleb Natapov
2013-06-09 12:56       ` 李春奇 <Arthur Chunqi Li>
2013-06-09 12:58         ` Gleb Natapov
2013-06-09 13:22       ` 李春奇 <Arthur Chunqi Li>
2013-06-09 14:09         ` Gleb Natapov
2013-06-09 15:23           ` 李春奇 <Arthur Chunqi Li>
2013-06-09 16:00             ` Gleb Natapov
2013-06-09 17:09               ` 李春奇 <Arthur Chunqi Li>
2013-06-09 17:13                 ` Gleb Natapov
2013-06-09 17:28                   ` 李春奇 <Arthur Chunqi Li>
2013-06-09 17:39                     ` Gleb Natapov
2013-06-06 15:24 Arthur Chunqi Li
2013-06-07  2:14 ` 李春奇 <Arthur Chunqi Li>
2013-06-12 20:50 ` Paolo Bonzini
2013-06-13  4:50   ` 李春奇 <Arthur Chunqi Li>
2013-06-13  9:30     ` 李春奇 <Arthur Chunqi Li>
2013-06-13 13:12       ` Paolo Bonzini
2013-06-18 12:45       ` Gleb Natapov
2013-06-18 13:40         ` 李春奇 <Arthur Chunqi Li>
2013-06-18 14:28         ` 李春奇 <Arthur Chunqi Li>
2013-06-18 15:47           ` Gleb Natapov
2013-06-18 15:56             ` 李春奇 <Arthur Chunqi Li>
2013-06-18 16:09               ` Gleb Natapov
2013-06-18 16:14                 ` 李春奇 <Arthur Chunqi Li>
2013-06-18 16:44                   ` Gleb Natapov
2013-06-19  1:26                     ` 李春奇 <Arthur Chunqi Li>
2013-06-19  9:31                       ` Gleb Natapov
2013-06-19 12:18                         ` 李春奇 <Arthur Chunqi Li>
2013-06-19 12:26                           ` Gleb Natapov
2013-06-19 12:30                             ` 李春奇 <Arthur Chunqi Li>
2013-06-19 12:32                               ` Gleb Natapov
2013-06-19 14:01                                 ` 李春奇 <Arthur Chunqi Li>
2013-06-19 14:13                                   ` Gleb Natapov
2013-06-19 14:20                                     ` 李春奇 <Arthur Chunqi Li>

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=20130610173654.GM29022@redhat.com \
    --to=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.