aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/kvm/x86_emulate.c38
-rw-r--r--drivers/kvm/x86_emulate.h7
2 files changed, 43 insertions, 2 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 8e2162fc6f70..6e7f774d1751 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -414,8 +414,7 @@ static u16 twobyte_table[256] = {
414/* Fetch next part of the instruction being emulated. */ 414/* Fetch next part of the instruction being emulated. */
415#define insn_fetch(_type, _size, _eip) \ 415#define insn_fetch(_type, _size, _eip) \
416({ unsigned long _x; \ 416({ unsigned long _x; \
417 rc = ops->read_std((unsigned long)(_eip) + ctxt->cs_base, &_x, \ 417 rc = do_insn_fetch(ctxt, ops, (_eip), &_x, (_size)); \
418 (_size), ctxt->vcpu); \
419 if (rc != 0) \ 418 if (rc != 0) \
420 goto done; \ 419 goto done; \
421 (_eip) += (_size); \ 420 (_eip) += (_size); \
@@ -446,6 +445,41 @@ static u16 twobyte_table[256] = {
446 register_address_increment(c->eip, rel); \ 445 register_address_increment(c->eip, rel); \
447 } while (0) 446 } while (0)
448 447
448static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt,
449 struct x86_emulate_ops *ops,
450 unsigned long linear, u8 *dest)
451{
452 struct fetch_cache *fc = &ctxt->decode.fetch;
453 int rc;
454 int size;
455
456 if (linear < fc->start || linear >= fc->end) {
457 size = min(15UL, PAGE_SIZE - offset_in_page(linear));
458 rc = ops->read_std(linear, fc->data, size, ctxt->vcpu);
459 if (rc)
460 return rc;
461 fc->start = linear;
462 fc->end = linear + size;
463 }
464 *dest = fc->data[linear - fc->start];
465 return 0;
466}
467
468static int do_insn_fetch(struct x86_emulate_ctxt *ctxt,
469 struct x86_emulate_ops *ops,
470 unsigned long eip, void *dest, unsigned size)
471{
472 int rc = 0;
473
474 eip += ctxt->cs_base;
475 while (size--) {
476 rc = do_fetch_insn_byte(ctxt, ops, eip++, dest++);
477 if (rc)
478 return rc;
479 }
480 return 0;
481}
482
449/* 483/*
450 * Given the 'reg' portion of a ModRM byte, and a register block, return a 484 * Given the 'reg' portion of a ModRM byte, and a register block, return a
451 * pointer into the block that addresses the relevant register. 485 * pointer into the block that addresses the relevant register.
diff --git a/drivers/kvm/x86_emulate.h b/drivers/kvm/x86_emulate.h
index a62bf14bbf89..4603b2bf3488 100644
--- a/drivers/kvm/x86_emulate.h
+++ b/drivers/kvm/x86_emulate.h
@@ -108,6 +108,12 @@ struct operand {
108 unsigned long val, orig_val, *ptr; 108 unsigned long val, orig_val, *ptr;
109}; 109};
110 110
111struct fetch_cache {
112 u8 data[15];
113 unsigned long start;
114 unsigned long end;
115};
116
111struct decode_cache { 117struct decode_cache {
112 u8 twobyte; 118 u8 twobyte;
113 u8 b; 119 u8 b;
@@ -130,6 +136,7 @@ struct decode_cache {
130 u8 use_modrm_ea; 136 u8 use_modrm_ea;
131 unsigned long modrm_ea; 137 unsigned long modrm_ea;
132 unsigned long modrm_val; 138 unsigned long modrm_val;
139 struct fetch_cache fetch;
133}; 140};
134 141
135struct x86_emulate_ctxt { 142struct x86_emulate_ctxt {