KVM: x86 emulator: allow storing emulator execution function in decode tables
[firefly-linux-kernel-4.4.55.git] / arch / x86 / kvm / emulate.c
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;