[PATCH 03/40] KVM: x86 emulator: add support for group decoding



Certain x86 instructions use bits 3:5 of the byte following the opcode as an
opcode extension, with the decode sometimes depending on bits 6:7 as well.
Add support for this in the main decoding table rather than an ad-hock
adaptation per opcode.

Signed-off-by: Avi Kivity <avi@xxxxxxxxxxxx>
---
arch/x86/kvm/x86_emulate.c | 33 +++++++++++++++++++++++++++------
1 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c
index 7958600..46ecf34 100644
--- a/arch/x86/kvm/x86_emulate.c
+++ b/arch/x86/kvm/x86_emulate.c
@@ -65,6 +65,9 @@
#define MemAbs (1<<9) /* Memory operand is absolute displacement */
#define String (1<<10) /* String instruction (rep capable) */
#define Stack (1<<11) /* Stack instruction (push/pop) */
+#define Group (1<<14) /* Bits 3:5 of modrm byte extend opcode */
+#define GroupDual (1<<15) /* Alternate decoding of mod == 3 */
+#define GroupMask 0xff /* Group number stored in bits 0:7 */

static u16 opcode_table[256] = {
/* 0x00 - 0x07 */
@@ -229,6 +232,12 @@ static u16 twobyte_table[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

+static u16 group_table[] = {
+};
+
+static u16 group2_table[] = {
+};
+
/* EFLAGS bit definitions. */
#define EFLG_OF (1<<11)
#define EFLG_DF (1<<10)
@@ -763,7 +772,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
struct decode_cache *c = &ctxt->decode;
int rc = 0;
int mode = ctxt->mode;
- int def_op_bytes, def_ad_bytes;
+ int def_op_bytes, def_ad_bytes, group;

/* Shadow copy of register state. Committed on successful emulation. */

@@ -864,12 +873,24 @@ done_prefixes:
c->b = insn_fetch(u8, 1, c->eip);
c->d = twobyte_table[c->b];
}
+ }

- /* Unrecognised? */
- if (c->d == 0) {
- DPRINTF("Cannot emulate %02x\n", c->b);
- return -1;
- }
+ if (c->d & Group) {
+ group = c->d & GroupMask;
+ c->modrm = insn_fetch(u8, 1, c->eip);
+ --c->eip;
+
+ group = (group << 3) + ((c->modrm >> 3) & 7);
+ if ((c->d & GroupDual) && (c->modrm >> 6) == 3)
+ c->d = group2_table[group];
+ else
+ c->d = group_table[group];
+ }
+
+ /* Unrecognised? */
+ if (c->d == 0) {
+ DPRINTF("Cannot emulate %02x\n", c->b);
+ return -1;
}

if (mode == X86EMUL_MODE_PROT64 && (c->d & Stack))
--
1.5.4.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



Relevant Pages

  • Re: [PATCH -tip 3/6 V4.1] x86: instruction decorder API
    ... can decode all x86 instructions into prefix, opcode, modrm, sib, ... is this meant to be able to decode userspace code or just kernel ... kernel, such as ENTER.) ... you have a bunch of magic opcode constants all over the place. ...
    (Linux-Kernel)
  • Re: [PATCH -tip 3/6 V4.1] x86: instruction decorder API
    ... can decode all x86 instructions into prefix, opcode, modrm, sib, ... is this meant to be able to decode userspace code or just kernel ... kernel, such as ENTER.) ... you have a bunch of magic opcode constants all over the place. ...
    (Linux-Kernel)
  • Re: [PATCH -tip 3/6 V4.1] x86: instruction decorder API
    ... can decode all x86 instructions into prefix, opcode, modrm, sib, ... is this meant to be able to decode userspace code or just kernel code? ... If not, why are you including the 32-bit decoder in a 64-bit kernel ... you're already not dealing with all existing three-byte opcode spaces, nor with DREX or VEX encodings for upcoming processors. ...
    (Linux-Kernel)
  • Re: Template bits for faster decode
    ... offsets internal to the preceding instruction can be flushed. ... Assuming we do not parallel decode anything with a legacy prefix, ... However for x64 we should assume almost everything has a rex prefix ... so the opcode is position 2 or 3 or 4. ...
    (comp.arch)