KVM: x86 emulator: allow storing emulator execution function in decode tables
authorAvi Kivity <avi@redhat.com>
Thu, 29 Jul 2010 12:11:51 +0000 (15:11 +0300)
committerAvi Kivity <avi@redhat.com>
Sun, 24 Oct 2010 08:50:22 +0000 (10:50 +0200)
Instead of looking up the opcode twice (once for decode flags, once for
the big execution switch) look up both flags and function in the decode tables.

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
arch/x86/include/asm/kvm_emulate.h
arch/x86/kvm/emulate.c

index 9ddfa5ed22891d2be7303c53676d031268efb354..0f901c16cf1c03ce969529b1759fcc070c809723 100644 (file)
@@ -190,6 +190,7 @@ struct decode_cache {
        bool has_seg_override;
        u8 seg_override;
        unsigned int d;
+       int (*execute)(struct x86_emulate_ctxt *ctxt);
        unsigned long regs[NR_VCPU_REGS];
        unsigned long eip;
        /* modrm */
index 3689f34a303a583ed2b3a02284df6aa133bbecb3..799e895fb08e72dbd333c717d50e95c96e08dd68 100644 (file)
 struct opcode {
        u32 flags;
        union {
+               int (*execute)(struct x86_emulate_ctxt *ctxt);
                struct opcode *group;
                struct group_dual *gdual;
        } u;
@@ -120,6 +121,7 @@ struct group_dual {
 #define N    D(0)
 #define G(_f, _g) { .flags = ((_f) | Group), .u.group = (_g) }
 #define GD(_f, _g) { .flags = ((_f) | Group | GroupDual), .u.gdual = (_g) }
+#define I(_f, _e) { .flags = (_f), .u.execute = (_e) }
 
 static struct opcode group1[] = {
        X7(D(Lock)), N
@@ -349,6 +351,7 @@ static struct opcode twobyte_table[256] = {
 #undef N
 #undef G
 #undef GD
+#undef I
 
 /* EFLAGS bit definitions. */
 #define EFLG_ID (1<<21)
@@ -1070,6 +1073,8 @@ done_prefixes:
                c->d |= opcode.flags;
        }
 
+       c->execute = opcode.u.execute;
+
        /* Unrecognised? */
        if (c->d == 0 || (c->d & Undefined)) {
                DPRINTF("Cannot emulate %02x\n", c->b);
@@ -2705,6 +2710,13 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
 
 special_insn:
 
+       if (c->execute) {
+               rc = c->execute(ctxt);
+               if (rc != X86EMUL_CONTINUE)
+                       goto done;
+               goto writeback;
+       }
+
        if (c->twobyte)
                goto twobyte_insn;