aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2010-04-28 12:15:22 -0400
committerAvi Kivity <avi@redhat.com>2010-08-01 03:35:28 -0400
commit9de41573675cbace09b02ef386f3e9c8739d495c (patch)
treee13a6a4b2326103472f7f18b6fd8c855f5ffdacf /arch/x86
parent1c11e713576edf33b95669be9c2dc0ff1e0c90d3 (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.h1
-rw-r--r--arch/x86/kvm/emulate.c56
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
191struct x86_emulate_ctxt { 192struct 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
1266static 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
1266static int pio_in_emulated(struct x86_emulate_ctxt *ctxt, 1293static 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);