diff options
author | Gleb Natapov <gleb@redhat.com> | 2010-04-28 12:15:22 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-08-01 03:35:28 -0400 |
commit | 9de41573675cbace09b02ef386f3e9c8739d495c (patch) | |
tree | e13a6a4b2326103472f7f18b6fd8c855f5ffdacf /arch/x86 | |
parent | 1c11e713576edf33b95669be9c2dc0ff1e0c90d3 (diff) |
KVM: x86 emulator: introduce read cache
Introduce read cache which is needed for instruction that require more
then one exit to userspace. After returning from userspace the instruction
will be re-executed with cached read value.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/kvm_emulate.h | 1 | ||||
-rw-r--r-- | arch/x86/kvm/emulate.c | 56 |
2 files changed, 43 insertions, 14 deletions
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index 0b2729bf2070..288cbedcab1c 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h | |||
@@ -186,6 +186,7 @@ struct decode_cache { | |||
186 | unsigned long modrm_val; | 186 | unsigned long modrm_val; |
187 | struct fetch_cache fetch; | 187 | struct fetch_cache fetch; |
188 | struct read_cache io_read; | 188 | struct read_cache io_read; |
189 | struct read_cache mem_read; | ||
189 | }; | 190 | }; |
190 | 191 | ||
191 | struct x86_emulate_ctxt { | 192 | struct x86_emulate_ctxt { |
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 5ac0bb465ed6..776874b8e50e 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -1263,6 +1263,33 @@ done: | |||
1263 | return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; | 1263 | return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; |
1264 | } | 1264 | } |
1265 | 1265 | ||
1266 | static int read_emulated(struct x86_emulate_ctxt *ctxt, | ||
1267 | struct x86_emulate_ops *ops, | ||
1268 | unsigned long addr, void *dest, unsigned size) | ||
1269 | { | ||
1270 | int rc; | ||
1271 | struct read_cache *mc = &ctxt->decode.mem_read; | ||
1272 | |||
1273 | while (size) { | ||
1274 | int n = min(size, 8u); | ||
1275 | size -= n; | ||
1276 | if (mc->pos < mc->end) | ||
1277 | goto read_cached; | ||
1278 | |||
1279 | rc = ops->read_emulated(addr, mc->data + mc->end, n, ctxt->vcpu); | ||
1280 | if (rc != X86EMUL_CONTINUE) | ||
1281 | return rc; | ||
1282 | mc->end += n; | ||
1283 | |||
1284 | read_cached: | ||
1285 | memcpy(dest, mc->data + mc->pos, n); | ||
1286 | mc->pos += n; | ||
1287 | dest += n; | ||
1288 | addr += n; | ||
1289 | } | ||
1290 | return X86EMUL_CONTINUE; | ||
1291 | } | ||
1292 | |||
1266 | static int pio_in_emulated(struct x86_emulate_ctxt *ctxt, | 1293 | static int pio_in_emulated(struct x86_emulate_ctxt *ctxt, |
1267 | struct x86_emulate_ops *ops, | 1294 | struct x86_emulate_ops *ops, |
1268 | unsigned int size, unsigned short port, | 1295 | unsigned int size, unsigned short port, |
@@ -1504,9 +1531,9 @@ static int emulate_pop(struct x86_emulate_ctxt *ctxt, | |||
1504 | struct decode_cache *c = &ctxt->decode; | 1531 | struct decode_cache *c = &ctxt->decode; |
1505 | int rc; | 1532 | int rc; |
1506 | 1533 | ||
1507 | rc = ops->read_emulated(register_address(c, ss_base(ctxt), | 1534 | rc = read_emulated(ctxt, ops, register_address(c, ss_base(ctxt), |
1508 | c->regs[VCPU_REGS_RSP]), | 1535 | c->regs[VCPU_REGS_RSP]), |
1509 | dest, len, ctxt->vcpu); | 1536 | dest, len); |
1510 | if (rc != X86EMUL_CONTINUE) | 1537 | if (rc != X86EMUL_CONTINUE) |
1511 | return rc; | 1538 | return rc; |
1512 | 1539 | ||
@@ -2475,6 +2502,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
2475 | int saved_dst_type = c->dst.type; | 2502 | int saved_dst_type = c->dst.type; |
2476 | 2503 | ||
2477 | ctxt->interruptibility = 0; | 2504 | ctxt->interruptibility = 0; |
2505 | ctxt->decode.mem_read.pos = 0; | ||
2478 | 2506 | ||
2479 | /* Shadow copy of register state. Committed on successful emulation. | 2507 | /* Shadow copy of register state. Committed on successful emulation. |
2480 | * NOTE: we can copy them from vcpu as x86_decode_insn() doesn't | 2508 | * NOTE: we can copy them from vcpu as x86_decode_insn() doesn't |
@@ -2529,20 +2557,16 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
2529 | } | 2557 | } |
2530 | 2558 | ||
2531 | if (c->src.type == OP_MEM) { | 2559 | if (c->src.type == OP_MEM) { |
2532 | rc = ops->read_emulated((unsigned long)c->src.ptr, | 2560 | rc = read_emulated(ctxt, ops, (unsigned long)c->src.ptr, |
2533 | &c->src.val, | 2561 | &c->src.val, c->src.bytes); |
2534 | c->src.bytes, | ||
2535 | ctxt->vcpu); | ||
2536 | if (rc != X86EMUL_CONTINUE) | 2562 | if (rc != X86EMUL_CONTINUE) |
2537 | goto done; | 2563 | goto done; |
2538 | c->src.orig_val = c->src.val; | 2564 | c->src.orig_val = c->src.val; |
2539 | } | 2565 | } |
2540 | 2566 | ||
2541 | if (c->src2.type == OP_MEM) { | 2567 | if (c->src2.type == OP_MEM) { |
2542 | rc = ops->read_emulated((unsigned long)c->src2.ptr, | 2568 | rc = read_emulated(ctxt, ops, (unsigned long)c->src2.ptr, |
2543 | &c->src2.val, | 2569 | &c->src2.val, c->src2.bytes); |
2544 | c->src2.bytes, | ||
2545 | ctxt->vcpu); | ||
2546 | if (rc != X86EMUL_CONTINUE) | 2570 | if (rc != X86EMUL_CONTINUE) |
2547 | goto done; | 2571 | goto done; |
2548 | } | 2572 | } |
@@ -2553,8 +2577,8 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
2553 | 2577 | ||
2554 | if ((c->dst.type == OP_MEM) && !(c->d & Mov)) { | 2578 | if ((c->dst.type == OP_MEM) && !(c->d & Mov)) { |
2555 | /* optimisation - avoid slow emulated read if Mov */ | 2579 | /* optimisation - avoid slow emulated read if Mov */ |
2556 | rc = ops->read_emulated((unsigned long)c->dst.ptr, &c->dst.val, | 2580 | rc = read_emulated(ctxt, ops, (unsigned long)c->dst.ptr, |
2557 | c->dst.bytes, ctxt->vcpu); | 2581 | &c->dst.val, c->dst.bytes); |
2558 | if (rc != X86EMUL_CONTINUE) | 2582 | if (rc != X86EMUL_CONTINUE) |
2559 | goto done; | 2583 | goto done; |
2560 | } | 2584 | } |
@@ -2981,7 +3005,11 @@ writeback: | |||
2981 | (rc->end != 0 && rc->end == rc->pos)) | 3005 | (rc->end != 0 && rc->end == rc->pos)) |
2982 | ctxt->restart = false; | 3006 | ctxt->restart = false; |
2983 | } | 3007 | } |
2984 | 3008 | /* | |
3009 | * reset read cache here in case string instruction is restared | ||
3010 | * without decoding | ||
3011 | */ | ||
3012 | ctxt->decode.mem_read.end = 0; | ||
2985 | /* Commit shadow register state. */ | 3013 | /* Commit shadow register state. */ |
2986 | memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs); | 3014 | memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs); |
2987 | kvm_rip_write(ctxt->vcpu, c->eip); | 3015 | kvm_rip_write(ctxt->vcpu, c->eip); |