From: Takuya Yoshikawa <yoshikawa.takuya@xxxxxxxxxxxxx> This is the second part of the instruction decoding which treats the opcode. Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@xxxxxxxxxxxxx> Cc: Takuya Yoshikawa <takuya.yoshikawa@xxxxxxxxx> --- arch/x86/kvm/emulate.c | 66 +++++++++++++++++++++++++++++++---------------- 1 files changed, 43 insertions(+), 23 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index b22238b..e87570e 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -3964,32 +3964,28 @@ done: return rc; } -int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) +/** + * decode_opcode - decode opcode + * @ctxt: emulation context + * + * Decodes opcode bytes and reads opcode from table. + * + * Returns X86EMUL_CONTINUE on success. + */ +static int decode_opcode(struct x86_emulate_ctxt *ctxt) { 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]; /* Two-byte opcode? */ if (ctxt->b == 0x0f) { ctxt->twobyte = 1; ctxt->b = insn_fetch(u8, ctxt); opcode = twobyte_table[ctxt->b]; - } + } else + opcode = opcode_table[ctxt->b]; + ctxt->d = opcode.flags; while (ctxt->d & GroupMask) { @@ -4015,7 +4011,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) break; case Prefix: if (ctxt->rep_prefix && ctxt->op_prefix) - return EMULATION_FAILED; + return X86EMUL_UNHANDLEABLE; simd_prefix = ctxt->rep_prefix | ctxt->op_prefix; switch (simd_prefix) { case 0x00: opcode = opcode.u.gprefix->pfx_no; break; @@ -4025,23 +4021,47 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) } break; default: - return EMULATION_FAILED; + return X86EMUL_UNHANDLEABLE; } ctxt->d &= ~(u64)GroupMask; ctxt->d |= opcode.flags; } + /* Unrecognised? */ + if (ctxt->d == 0 || (ctxt->d & Undefined)) + return X86EMUL_UNHANDLEABLE; + + if (!(ctxt->d & VendorSpecific) && ctxt->only_vendor_specific_insn) + return X86EMUL_UNHANDLEABLE; + ctxt->execute = opcode.u.execute; ctxt->check_perm = opcode.check_perm; ctxt->intercept = opcode.intercept; - /* Unrecognised? */ - if (ctxt->d == 0 || (ctxt->d & Undefined)) - return EMULATION_FAILED; +done: + return rc; +} - if (!(ctxt->d & VendorSpecific) && ctxt->only_vendor_specific_insn) - return EMULATION_FAILED; +int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) +{ + int rc = X86EMUL_CONTINUE; + + 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; + + rc = decode_opcode(ctxt); + if (rc != X86EMUL_CONTINUE) + goto done; if (ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack)) ctxt->op_bytes = 8; -- 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