[PATCH 2/4] KVM: x86 emulator: Make prefix decoding a separate function

Takuya Yoshikawa
2012-04-23T15:34:37Z

From: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>

Instruction decoding can be split into separate parts, and this is the
first one which treats the instruction prefixes.

Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Cc: Takuya Yoshikawa <takuya.yoshikawa@gmail.com>
---
arch/x86/kvm/emulate.c | 58 +++++++++++++++++++++++++++++++----------------
1 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 5a49290..b22238b 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -3874,22 +3874,21 @@ done:
return rc;
}

-int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
+/**
+ * decode_prefixes - decode instruction prefixes
+ * @ctxt: emulation context
+ *
+ * Fetches instruction prefixes and sets some ctxt fields based on them.
+ * The byte next to the last prefix is also fetched into ctxt->b.
+ *
+ * Returns X86EMUL_CONTINUE on success.
+ */
+static int decode_prefixes(struct x86_emulate_ctxt *ctxt)
{
int rc = X86EMUL_CONTINUE;
- int mode = ctxt->mode;
- int def_op_bytes, def_ad_bytes, goffset, simd_prefix;
- struct opcode opcode;
+ int def_op_bytes, def_ad_bytes;

- ctxt->memop.type = OP_NONE;
- ctxt->memopp = NULL;
- ctxt->_eip = ctxt->eip;
- ctxt->fetch.start = ctxt->_eip;
- ctxt->fetch.end = ctxt->fetch.start + insn_len;
- if (insn_len > 0)
- memcpy(ctxt->fetch.data, insn, insn_len);
-
- switch (mode) {
+ switch (ctxt->mode) {
case X86EMUL_MODE_REAL:
case X86EMUL_MODE_VM86:
case X86EMUL_MODE_PROT16:
@@ -3905,7 +3904,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
break;
#endif
default:
- return EMULATION_FAILED;
+ return X86EMUL_UNHANDLEABLE;
}

ctxt->op_bytes = def_op_bytes;
@@ -3920,7 +3919,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
ctxt->op_bytes = def_op_bytes ^ 6;
break;
case 0x67: /* address-size override */
- if (mode == X86EMUL_MODE_PROT64)
+ if (ctxt->mode == X86EMUL_MODE_PROT64)
/* switch between 4/8 bytes */
ctxt->ad_bytes = def_ad_bytes ^ 12;
else
@@ -3938,7 +3937,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
set_seg_override(ctxt, ctxt->b & 7);
break;
case 0x40 ... 0x4f: /* REX */
- if (mode != X86EMUL_MODE_PROT64)
+ if (ctxt->mode != X86EMUL_MODE_PROT64)
goto done_prefixes;
ctxt->rex_prefix = ctxt->b;
continue;
@@ -3954,15 +3953,34 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
}

/* Any legacy prefix after a REX prefix nullifies its effect. */
-
ctxt->rex_prefix = 0;
}

done_prefixes:
-
/* REX prefix. */
if (ctxt->rex_prefix & 8)
ctxt->op_bytes = 8; /* REX.W */
+done:
+ return rc;
+}
+
+int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
+{
+ int rc = X86EMUL_CONTINUE;
+ int goffset, simd_prefix;
+ struct opcode opcode;
+
+ ctxt->memop.type = OP_NONE;
+ ctxt->memopp = NULL;
+ ctxt->_eip = ctxt->eip;
+ ctxt->fetch.start = ctxt->_eip;
+ ctxt->fetch.end = ctxt->fetch.start + insn_len;
+ if (insn_len > 0)
+ memcpy(ctxt->fetch.data, insn, insn_len);
+
+ rc = decode_prefixes(ctxt);
+ if (rc != X86EMUL_CONTINUE)
+ goto done;

/* Opcode byte(s). */
opcode = opcode_table[ctxt->b];
@@ -4025,11 +4043,11 @@ done_prefixes:
if (!(ctxt->d & VendorSpecific) && ctxt->only_vendor_specific_insn)
return EMULATION_FAILED;

- if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack))
+ if (ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack))
ctxt->op_bytes = 8;

if (ctxt->d & Op3264) {
- if (mode == X86EMUL_MODE_PROT64)
+ if (ctxt->mode == X86EMUL_MODE_PROT64)
ctxt->op_bytes = 8;
else
ctxt->op_bytes = 4;
--
1.7.5.4