Skip to content
Snippets Groups Projects
Commit 719d5a9b authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

KVM: x86: ensure emulator fetches do not span multiple pages


When the CS base is not page-aligned, the linear address of the code could
get close to the page boundary (e.g. 0x...ffe) even if the EIP value is
not.  So we need to first linearize the address, and only then compute
the number of valid bytes that can be fetched.

This happens relatively often when executing real mode code.

Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 17052f16
No related branches found
No related tags found
No related merge requests found
...@@ -711,14 +711,18 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt, ...@@ -711,14 +711,18 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
static int __do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size) static int __do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
{ {
int rc; int rc;
int size; unsigned size;
unsigned long linear; unsigned long linear;
int cur_size = ctxt->fetch.end - ctxt->fetch.data; int cur_size = ctxt->fetch.end - ctxt->fetch.data;
struct segmented_address addr = { .seg = VCPU_SREG_CS, struct segmented_address addr = { .seg = VCPU_SREG_CS,
.ea = ctxt->eip + cur_size }; .ea = ctxt->eip + cur_size };
size = min(15UL ^ cur_size, size = 15UL ^ cur_size;
PAGE_SIZE - offset_in_page(addr.ea)); rc = __linearize(ctxt, addr, size, false, true, &linear);
if (unlikely(rc != X86EMUL_CONTINUE))
return rc;
size = min_t(unsigned, size, PAGE_SIZE - offset_in_page(linear));
/* /*
* One instruction can only straddle two pages, * One instruction can only straddle two pages,
...@@ -728,9 +732,6 @@ static int __do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size) ...@@ -728,9 +732,6 @@ static int __do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
*/ */
if (unlikely(size < op_size)) if (unlikely(size < op_size))
return X86EMUL_UNHANDLEABLE; return X86EMUL_UNHANDLEABLE;
rc = __linearize(ctxt, addr, size, false, true, &linear);
if (unlikely(rc != X86EMUL_CONTINUE))
return rc;
rc = ctxt->ops->fetch(ctxt, linear, ctxt->fetch.end, rc = ctxt->ops->fetch(ctxt, linear, ctxt->fetch.end,
size, &ctxt->exception); size, &ctxt->exception);
if (unlikely(rc != X86EMUL_CONTINUE)) if (unlikely(rc != X86EMUL_CONTINUE))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment