From: Takuya Yoshikawa <yoshikawa.takuya@xxxxxxxxxxxxx> Although ModRM byte is read for group decoding, it is soon pushed back to make decode_modrm() fetch it later. We should consistently read it, only once, in decode_opcode() instead. Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@xxxxxxxxxxxxx> Cc: Takuya Yoshikawa <takuya.yoshikawa@xxxxxxxxx> --- arch/x86/kvm/emulate.c | 19 ++++++++++++------- 1 files changed, 12 insertions(+), 7 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index e87570e..8729773 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -972,7 +972,6 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt, ctxt->modrm_rm = base_reg = (ctxt->rex_prefix & 1) << 3; /* REG.B */ } - ctxt->modrm = insn_fetch(u8, ctxt); ctxt->modrm_mod |= (ctxt->modrm & 0xc0) >> 6; ctxt->modrm_reg |= (ctxt->modrm & 0x38) >> 3; ctxt->modrm_rm |= (ctxt->modrm & 0x07); @@ -3969,6 +3968,7 @@ done: * @ctxt: emulation context * * Decodes opcode bytes and reads opcode from table. + * The ModRM byte, if exists, is also fetched into ctxt->modrm. * * Returns X86EMUL_CONTINUE on success. */ @@ -3977,6 +3977,8 @@ static int decode_opcode(struct x86_emulate_ctxt *ctxt) int rc = X86EMUL_CONTINUE; int goffset, simd_prefix; struct opcode opcode; + bool modrm_fetched = false; + u64 gtype; /* Two-byte opcode? */ if (ctxt->b == 0x0f) { @@ -3988,17 +3990,18 @@ static int decode_opcode(struct x86_emulate_ctxt *ctxt) ctxt->d = opcode.flags; - while (ctxt->d & GroupMask) { - switch (ctxt->d & GroupMask) { - case Group: + while ((gtype = ctxt->d & GroupMask)) { + if (!modrm_fetched && gtype != Prefix) { ctxt->modrm = insn_fetch(u8, ctxt); - --ctxt->_eip; + modrm_fetched = true; + } + + switch (gtype) { + case Group: goffset = (ctxt->modrm >> 3) & 7; opcode = opcode.u.group[goffset]; break; case GroupDual: - ctxt->modrm = insn_fetch(u8, ctxt); - --ctxt->_eip; goffset = (ctxt->modrm >> 3) & 7; if ((ctxt->modrm >> 6) == 3) opcode = opcode.u.gdual->mod3[goffset]; @@ -4039,6 +4042,8 @@ static int decode_opcode(struct x86_emulate_ctxt *ctxt) ctxt->check_perm = opcode.check_perm; ctxt->intercept = opcode.intercept; + if (!modrm_fetched && (ctxt->d & ModRM)) + ctxt->modrm = insn_fetch(u8, ctxt); done: return rc; } -- 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