From: Takuya Yoshikawa <yoshikawa.takuya@xxxxxxxxxxxxx> 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@xxxxxxxxxxxxx> Cc: Takuya Yoshikawa <takuya.yoshikawa@xxxxxxxxx> --- 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 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html