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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



To optimize "rep ins" instruction do IO in big chunks ahead of time
instead of doing it only when required during instruction emulation.

Signed-off-by: Gleb Natapov <gleb@xxxxxxxxxx>
---
 arch/x86/include/asm/kvm_emulate.h |    7 +++++++
 arch/x86/kvm/emulate.c             |   34 ++++++++++++++++++++++++++++++----
 2 files changed, 37 insertions(+), 4 deletions(-)

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,
-- 
1.6.5

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux