diff options
-rw-r--r-- | drivers/kvm/x86_emulate.c | 38 | ||||
-rw-r--r-- | drivers/kvm/x86_emulate.h | 7 |
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 | ||
448 | static 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 | |||
468 | static 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 | ||
111 | struct fetch_cache { | ||
112 | u8 data[15]; | ||
113 | unsigned long start; | ||
114 | unsigned long end; | ||
115 | }; | ||
116 | |||
111 | struct decode_cache { | 117 | struct 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 | ||
135 | struct x86_emulate_ctxt { | 142 | struct x86_emulate_ctxt { |