Skip to content

Commit 2fb53ad

Browse files
committed
KVM: x86 emulator: Don't overwrite decode cache
Currently if we an instruction spans a page boundary, when we fetch the second half we overwrite the first half. This prevents us from tracing the full instruction opcodes. Fix by appending the second half to the first. Signed-off-by: Avi Kivity <[email protected]> Signed-off-by: Marcelo Tosatti <[email protected]>
1 parent 4496f97 commit 2fb53ad

File tree

1 file changed

+10
-9
lines changed

1 file changed

+10
-9
lines changed

arch/x86/kvm/emulate.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -646,21 +646,22 @@ static unsigned long ss_base(struct x86_emulate_ctxt *ctxt)
646646

647647
static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt,
648648
struct x86_emulate_ops *ops,
649-
unsigned long linear, u8 *dest)
649+
unsigned long eip, u8 *dest)
650650
{
651651
struct fetch_cache *fc = &ctxt->decode.fetch;
652652
int rc;
653-
int size;
653+
int size, cur_size;
654654

655-
if (linear < fc->start || linear >= fc->end) {
656-
size = min(15UL, PAGE_SIZE - offset_in_page(linear));
657-
rc = ops->fetch(linear, fc->data, size, ctxt->vcpu, NULL);
655+
if (eip == fc->end) {
656+
cur_size = fc->end - fc->start;
657+
size = min(15UL - cur_size, PAGE_SIZE - offset_in_page(eip));
658+
rc = ops->fetch(ctxt->cs_base + eip, fc->data + cur_size,
659+
size, ctxt->vcpu, NULL);
658660
if (rc != X86EMUL_CONTINUE)
659661
return rc;
660-
fc->start = linear;
661-
fc->end = linear + size;
662+
fc->end += size;
662663
}
663-
*dest = fc->data[linear - fc->start];
664+
*dest = fc->data[eip - fc->start];
664665
return X86EMUL_CONTINUE;
665666
}
666667

@@ -673,7 +674,6 @@ static int do_insn_fetch(struct x86_emulate_ctxt *ctxt,
673674
/* x86 instructions are limited to 15 bytes. */
674675
if (eip + size - ctxt->eip > 15)
675676
return X86EMUL_UNHANDLEABLE;
676-
eip += ctxt->cs_base;
677677
while (size--) {
678678
rc = do_fetch_insn_byte(ctxt, ops, eip++, dest++);
679679
if (rc != X86EMUL_CONTINUE)
@@ -935,6 +935,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
935935
/* Shadow copy of register state. Committed on successful emulation. */
936936
memset(c, 0, sizeof(struct decode_cache));
937937
c->eip = ctxt->eip;
938+
c->fetch.start = c->fetch.end = c->eip;
938939
ctxt->cs_base = seg_base(ctxt, VCPU_SREG_CS);
939940
memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
940941

0 commit comments

Comments
 (0)