From: Arthur Chunqi Li <yzt356@gmail.com>
To: kvm@vger.kernel.org
Cc: gleb@redhat.com, pbonzini@redhat.com, jan.kiszka@web.de,
Arthur Chunqi Li <yzt356@gmail.com>
Subject: [PATCH v4 2/3] kvm-unit-tests: Add a func to run instruction in emulator
Date: Thu, 20 Jun 2013 22:36:08 +0800 [thread overview]
Message-ID: <1371738969-26658-2-git-send-email-yzt356@gmail.com> (raw)
In-Reply-To: <1371738969-26658-1-git-send-email-yzt356@gmail.com>
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.
Signed-off-by: Arthur Chunqi Li <yzt356@gmail.com>
---
x86/emulator.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 95 insertions(+)
diff --git a/x86/emulator.c b/x86/emulator.c
index 96576e5..876ee5a 100644
--- a/x86/emulator.c
+++ b/x86/emulator.c
@@ -11,6 +11,20 @@ int fails, tests;
static int exceptions;
+struct regs {
+ u64 rax, rbx, rcx, rdx;
+ u64 rsi, rdi, rsp, rbp;
+ u64 r8, r9, r10, r11;
+ u64 r12, r13, r14, r15;
+ u64 rip, rflags;
+};
+struct regs inregs, outregs, save;
+
+struct insn_desc {
+ u64 ptr;
+ size_t len;
+};
+
void report(const char *name, int result)
{
++tests;
@@ -685,6 +699,87 @@ static void test_shld_shrd(u32 *mem)
report("shrd (cl)", *mem == ((0x12345678 >> 3) | (5u << 29)));
}
+#define INSN_XCHG_ALL \
+ "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 %rsp, 48+save \n\t" \
+ "xchg %rbp, 56+save \n\t" \
+ "xchg %r8, 64+save \n\t" \
+ "xchg %r9, 72+save \n\t" \
+ "xchg %r10, 80+save \n\t" \
+ "xchg %r11, 88+save \n\t" \
+ "xchg %r12, 96+save \n\t" \
+ "xchg %r13, 104+save \n\t" \
+ "xchg %r14, 112+save \n\t" \
+ "xchg %r15, 120+save \n\t"
+
+asm(
+ ".align 4096\n\t"
+ "insn_page:\n\t"
+ "ret\n\t"
+ "pushf\n\t"
+ "push 136+save \n\t"
+ "popf \n\t"
+ INSN_XCHG_ALL
+ "test_insn:\n\t"
+ "in (%dx),%al\n\t"
+ ".skip 31, 0x90\n\t"
+ "test_insn_end:\n\t"
+ INSN_XCHG_ALL
+ "pushf \n\t"
+ "pop 136+save \n\t"
+ "popf \n\t"
+ "ret \n\t"
+ "insn_page_end:\n\t"
+ ".align 4096\n\t"
+);
+
+#define MK_INSN(name, str) \
+ asm ( \
+ ".pushsection .data.insn \n\t" \
+ "insn_" #name ": \n\t" \
+ ".quad 1001f, 1002f - 1001f \n\t" \
+ ".popsection \n\t" \
+ ".pushsection .text.insn, \"ax\" \n\t" \
+ "1001: \n\t" \
+ "insn_code_" #name ": " str " \n\t" \
+ "1002: \n\t" \
+ ".popsection" \
+ ); \
+ extern struct insn_desc insn_##name;
+
+static void trap_emulator(uint64_t *mem, void *alt_insn_page,
+ struct insn_desc *alt_insn)
+{
+ ulong *cr3 = (ulong *)read_cr3();
+ void *insn_ram;
+ extern u8 insn_page[], test_insn[];
+
+ insn_ram = vmap(virt_to_phys(insn_page), 4096);
+ memcpy(alt_insn_page, insn_page, 4096);
+ memcpy(alt_insn_page + (test_insn - insn_page),
+ (void *)(alt_insn->ptr), alt_insn->len);
+ 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("call *%0": : "r"(insn_ram+1));
+
+ outregs = save;
+}
+
static void advance_rip_by_3_and_note_exception(struct ex_regs *regs)
{
++exceptions;
--
1.7.9.5
next prev parent reply other threads:[~2013-06-20 14:36 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-20 14:36 [PATCH v4 1/3] kvm-unit-tests: Add memcpy to lib/string.c Arthur Chunqi Li
2013-06-20 14:36 ` Arthur Chunqi Li [this message]
2013-06-20 14:36 ` [PATCH v4 3/3] kvm-unit-tests: Change two cases to use trap_emulator Arthur Chunqi Li
2013-06-21 15:01 ` [PATCH v4 1/3] kvm-unit-tests: Add memcpy to lib/string.c Paolo Bonzini
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=1371738969-26658-2-git-send-email-yzt356@gmail.com \
--to=yzt356@gmail.com \
--cc=gleb@redhat.com \
--cc=jan.kiszka@web.de \
--cc=kvm@vger.kernel.org \
--cc=pbonzini@redhat.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox