diff mbox

[23/24] KVM: x86 emulator: introduce pio in string read ahead.

Message ID 1268143762-4000-24-git-send-email-gleb@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Gleb Natapov March 9, 2010, 2:09 p.m. UTC
None
diff mbox

Patch

diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index f74b4ad..da7a711 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -150,6 +150,12 @@  struct fetch_cache {
 	unsigned long end;
 };
 
+struct read_cache {
+	u8 data[1024];
+	unsigned long pos;
+	unsigned long end;
+};
+
 struct decode_cache {
 	u8 twobyte;
 	u8 b;
@@ -177,6 +183,7 @@  struct decode_cache {
 	void *modrm_ptr;
 	unsigned long modrm_val;
 	struct fetch_cache fetch;
+	struct read_cache io_read;
 };
 
 struct x86_emulate_ctxt {
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 76ed77d..987be2a 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1222,6 +1222,28 @@  done:
 	return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0;
 }
 
+static int pio_in_emulated(struct x86_emulate_ctxt *ctxt,
+			   struct x86_emulate_ops *ops,
+			   unsigned int size, unsigned short port,
+			   void *dest, unsigned int count)
+{
+	struct read_cache *mc = &ctxt->decode.io_read;
+
+	if (mc->pos == mc->end) { /* refill pio read ahead */
+		unsigned int n = sizeof(mc->data) / size;
+		n = min(n, count);
+		mc->pos = mc->end = 0;
+		if (!ops->pio_in_emulated(size, port, mc->data, n,
+					  ctxt->vcpu))
+			return 0;
+		mc->end = n * size;
+	}
+
+	memcpy(dest, mc->data + mc->pos, size);
+	mc->pos += size;
+	return 1;
+}
+
 static u32 desc_limit_scaled(struct desc_struct *desc)
 {
 	u32 limit = get_desc_limit(desc);
@@ -2601,8 +2623,11 @@  special_insn:
 			kvm_inject_gp(ctxt->vcpu, 0);
 			goto done;
 		}
-		if (!ops->pio_in_emulated(c->dst.bytes, c->regs[VCPU_REGS_RDX],
-					  &c->dst.val, 1, ctxt->vcpu))
+		if (c->rep_prefix)
+			ctxt->restart = true;
+		if (!pio_in_emulated(ctxt, ops, c->dst.bytes,
+				     c->regs[VCPU_REGS_RDX], &c->dst.val,
+				     c->rep_prefix ? c->regs[VCPU_REGS_RCX] : 1))
 			goto done; /* IO is needed, skip writeback */
 
 		register_address_increment(c, &c->regs[VCPU_REGS_RDI],
@@ -2908,8 +2933,9 @@  special_insn:
 			goto done;
 		}
 		if (io_dir_in)
-			ops->pio_in_emulated((c->d & ByteOp) ? 1 : c->op_bytes,
-					     port, &c->dst.val, 1, ctxt->vcpu);
+			pio_in_emulated(ctxt, ops,
+					(c->d & ByteOp) ? 1 : c->op_bytes,
+					port, &c->dst.val, 1);
 		else
 			ops->pio_out_emulated((c->d & ByteOp) ? 1 : c->op_bytes,
 					      port, &c->regs[VCPU_REGS_RAX], 1,