public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* PATCH 0/5] Consolidate the insb/outsb emulation into x86_emulate.c
@ 2007-08-01  9:05 Laurent Vivier
       [not found] ` <46B04CCA.2010503-6ktuUTfB/bM@public.gmane.org>
  0 siblings, 1 reply; 10+ messages in thread
From: Laurent Vivier @ 2007-08-01  9:05 UTC (permalink / raw)
  To: kvm-devel


[-- Attachment #1.1: Type: text/plain, Size: 1441 bytes --]

[PATCH 0/5] Consolidate the insb/outsb emulation into x86_emulate.c

From the TODO, this serie of patches consolidates the insb/outsb emulation into
x86_emulate.c.

The prefix decoding part is extracted from x86_emulate_memop() and a function
called x86_decode_prefix() is created.
Then, in vmx.c, handle_io() calls x86_decode_prefix() instead of get_io_count();
in svm.c, io_interception() calls x86_decode_prefix() instead of io_address()
and io_get_override().

*** WARNING: the SVM part has not been tested because I don't have any AMD
system. ***

[PATCH 1/5] x86_ctxt_segment_array: to be able to extract easily prefix decoding
from x86_emulate_memop(), change ctxt.*_base to an array ctxt.base[X86EMUL_BASE_*]

[PATCH 2/5] x86_prefix: to be able to extract easily prefix decoding from
x86_emulate_memop(), group all prefix decoding results in a structure, called
x86_prefix.

[PATCH 3/5] x86_decode_prefix: extract prefix decoding part from
x86_emulate_memop() to x86_decode_prefix().

[PATCH 4/5] vmx-decode_prefix: vmx.c uses x86_decode_prefix() instead of
get_io_count().

[PATCH 5/5] svm-decode_prefix: svm.c uses x86_decode_prefix() instead of
io_address() and io_get_override().

*** WARNING: the SVM part has not been tested because I don't have any AMD
system. ***

-- 
------------- Laurent.Vivier-6ktuUTfB/bM@public.gmane.org  --------------
          "Software is hard" - Donald Knuth


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 315 bytes --]

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

[-- Attachment #3: Type: text/plain, Size: 186 bytes --]

_______________________________________________
kvm-devel mailing list
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/kvm-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/5] change ctxt.*_base to an array ctxt.base[X86EMUL_BASE_*]
       [not found] ` <46B04CCA.2010503-6ktuUTfB/bM@public.gmane.org>
@ 2007-08-01  9:09   ` Laurent Vivier
       [not found]     ` <46B04DD6.7010702-6ktuUTfB/bM@public.gmane.org>
  0 siblings, 1 reply; 10+ messages in thread
From: Laurent Vivier @ 2007-08-01  9:09 UTC (permalink / raw)
  To: kvm-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 334 bytes --]

To be able to extract easily prefix decoding from x86_emulate_memop(), change
ctxt.*_base to an array ctxt.base[X86EMUL_BASE_*]

Signed-off-by: Laurent Vivier <Laurent.Vivier-6ktuUTfB/bM@public.gmane.org>
-- 
------------- Laurent.Vivier-6ktuUTfB/bM@public.gmane.org  --------------
          "Software is hard" - Donald Knuth

[-- Attachment #1.1.2: x86_ctxt_segment_array --]
[-- Type: text/plain, Size: 7271 bytes --]

Index: kvm/drivers/kvm/kvm_main.c
===================================================================
--- kvm.orig/drivers/kvm/kvm_main.c	2007-07-31 15:09:01.000000000 +0200
+++ kvm/drivers/kvm/kvm_main.c	2007-07-31 15:12:47.000000000 +0200
@@ -1236,19 +1236,25 @@
 		? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
 
 	if (emulate_ctxt.mode == X86EMUL_MODE_PROT64) {
-		emulate_ctxt.cs_base = 0;
-		emulate_ctxt.ds_base = 0;
-		emulate_ctxt.es_base = 0;
-		emulate_ctxt.ss_base = 0;
+		emulate_ctxt.base[X86EMUL_BASE_CS] = 0;
+		emulate_ctxt.base[X86EMUL_BASE_DS] = 0;
+		emulate_ctxt.base[X86EMUL_BASE_ES] = 0;
+		emulate_ctxt.base[X86EMUL_BASE_SS] = 0;
 	} else {
-		emulate_ctxt.cs_base = get_segment_base(vcpu, VCPU_SREG_CS);
-		emulate_ctxt.ds_base = get_segment_base(vcpu, VCPU_SREG_DS);
-		emulate_ctxt.es_base = get_segment_base(vcpu, VCPU_SREG_ES);
-		emulate_ctxt.ss_base = get_segment_base(vcpu, VCPU_SREG_SS);
+		emulate_ctxt.base[X86EMUL_BASE_CS] =
+					get_segment_base(vcpu, VCPU_SREG_CS);
+		emulate_ctxt.base[X86EMUL_BASE_DS] =
+					get_segment_base(vcpu, VCPU_SREG_DS);
+		emulate_ctxt.base[X86EMUL_BASE_ES] =
+					get_segment_base(vcpu, VCPU_SREG_ES);
+		emulate_ctxt.base[X86EMUL_BASE_SS] =
+					get_segment_base(vcpu, VCPU_SREG_SS);
 	}
 
-	emulate_ctxt.gs_base = get_segment_base(vcpu, VCPU_SREG_GS);
-	emulate_ctxt.fs_base = get_segment_base(vcpu, VCPU_SREG_FS);
+	emulate_ctxt.base[X86EMUL_BASE_GS] =
+					get_segment_base(vcpu, VCPU_SREG_GS);
+	emulate_ctxt.base[X86EMUL_BASE_FS] =
+					get_segment_base(vcpu, VCPU_SREG_FS);
 
 	vcpu->mmio_is_write = 0;
 	r = x86_emulate_memop(&emulate_ctxt, &emulate_ops);
Index: kvm/drivers/kvm/x86_emulate.c
===================================================================
--- kvm.orig/drivers/kvm/x86_emulate.c	2007-07-31 15:09:01.000000000 +0200
+++ kvm/drivers/kvm/x86_emulate.c	2007-07-31 17:01:52.000000000 +0200
@@ -419,7 +419,8 @@
 /* Fetch next part of the instruction being emulated. */
 #define insn_fetch(_type, _size, _eip)                                  \
 ({	unsigned long _x;						\
-	rc = ops->read_std((unsigned long)(_eip) + ctxt->cs_base, &_x,	\
+	rc = ops->read_std((unsigned long)(_eip) + 			\
+			   ctxt->base[X86EMUL_BASE_CS], &_x,		\
                                                   (_size), ctxt->vcpu); \
 	if ( rc != 0 )							\
 		goto done;						\
@@ -484,7 +485,7 @@
 	unsigned d;
 	u8 b, sib, twobyte = 0, rex_prefix = 0;
 	u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
-	unsigned long *override_base = NULL;
+	int override_base = -1;
 	unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i;
 	int rc = 0;
 	struct operand src, dst;
@@ -533,22 +534,22 @@
 				ad_bytes ^= 6;	/* switch between 2/4 bytes */
 			break;
 		case 0x2e:	/* CS override */
-			override_base = &ctxt->cs_base;
+			override_base = X86EMUL_BASE_CS;
 			break;
 		case 0x3e:	/* DS override */
-			override_base = &ctxt->ds_base;
+			override_base = X86EMUL_BASE_DS;
 			break;
 		case 0x26:	/* ES override */
-			override_base = &ctxt->es_base;
+			override_base = X86EMUL_BASE_ES;
 			break;
 		case 0x64:	/* FS override */
-			override_base = &ctxt->fs_base;
+			override_base = X86EMUL_BASE_FS;
 			break;
 		case 0x65:	/* GS override */
-			override_base = &ctxt->gs_base;
+			override_base = X86EMUL_BASE_GS;
 			break;
 		case 0x36:	/* SS override */
-			override_base = &ctxt->ss_base;
+			override_base = X86EMUL_BASE_SS;
 			break;
 		case 0xf0:	/* LOCK */
 			lock_prefix = 1;
@@ -654,8 +655,8 @@
 			}
 			if (modrm_rm == 2 || modrm_rm == 3 ||
 			    (modrm_rm == 6 && modrm_mod != 0))
-				if (!override_base)
-					override_base = &ctxt->ss_base;
+				if (override_base == -1)
+					override_base = X86EMUL_BASE_SS;
 			modrm_ea = (u16)modrm_ea;
 		} else {
 			/* 32/64-bit ModR/M decode. */
@@ -708,15 +709,15 @@
 				break;
 			}
 		}
-		if (!override_base)
-			override_base = &ctxt->ds_base;
+		if (override_base == -1)
+			override_base = X86EMUL_BASE_DS;
 		if (mode == X86EMUL_MODE_PROT64 &&
-		    override_base != &ctxt->fs_base &&
-		    override_base != &ctxt->gs_base)
-			override_base = NULL;
+		    override_base != X86EMUL_BASE_FS &&
+		    override_base != X86EMUL_BASE_GS)
+			override_base = -1;
 
-		if (override_base)
-			modrm_ea += *override_base;
+		if (override_base != -1)
+			modrm_ea += ctxt->base[override_base];
 
 		if (rip_relative) {
 			modrm_ea += _eip;
@@ -963,8 +964,9 @@
 		/* 64-bit mode: POP always pops a 64-bit operand. */
 		if (mode == X86EMUL_MODE_PROT64)
 			dst.bytes = 8;
-		if ((rc = ops->read_std(register_address(ctxt->ss_base,
-							 _regs[VCPU_REGS_RSP]),
+		if ((rc = ops->read_std(
+				register_address(ctxt->base[X86EMUL_BASE_SS],
+					_regs[VCPU_REGS_RSP]),
 					&dst.val, dst.bytes, ctxt->vcpu)) != 0)
 			goto done;
 		register_address_increment(_regs[VCPU_REGS_RSP], dst.bytes);
@@ -1056,8 +1058,8 @@
 			register_address_increment(_regs[VCPU_REGS_RSP],
 						   -dst.bytes);
 			if ((rc = ops->write_std(
-				     register_address(ctxt->ss_base,
-						      _regs[VCPU_REGS_RSP]),
+				register_address(ctxt->base[X86EMUL_BASE_SS],
+						 _regs[VCPU_REGS_RSP]),
 				     &dst.val, dst.bytes, ctxt->vcpu)) != 0)
 				goto done;
 			no_wb = 1;
@@ -1128,10 +1130,12 @@
 	case 0xa4 ... 0xa5:	/* movs */
 		dst.type = OP_MEM;
 		dst.bytes = (d & ByteOp) ? 1 : op_bytes;
-		dst.ptr = (unsigned long *)register_address(ctxt->es_base,
+		dst.ptr = (unsigned long *)register_address(
+						ctxt->base[X86EMUL_BASE_ES],
 							_regs[VCPU_REGS_RDI]);
 		if ((rc = ops->read_emulated(register_address(
-		      override_base ? *override_base : ctxt->ds_base,
+		      (override_base != -1) ?
+		      	ctxt->base[override_base] : ctxt->base[X86EMUL_BASE_DS],
 		      _regs[VCPU_REGS_RSI]), &dst.val, dst.bytes, ctxt->vcpu)) != 0)
 			goto done;
 		register_address_increment(_regs[VCPU_REGS_RSI],
@@ -1173,7 +1177,8 @@
 		dst.ptr = (unsigned long *)&_regs[b & 0x7];
 
 pop_instruction:
-		if ((rc = ops->read_std(register_address(ctxt->ss_base,
+		if ((rc = ops->read_std(
+			register_address(ctxt->base[X86EMUL_BASE_SS],
 			_regs[VCPU_REGS_RSP]), dst.ptr, op_bytes, ctxt->vcpu))
 			!= 0)
 			goto done;
Index: kvm/drivers/kvm/x86_emulate.h
===================================================================
--- kvm.orig/drivers/kvm/x86_emulate.h	2007-07-31 15:09:01.000000000 +0200
+++ kvm/drivers/kvm/x86_emulate.h	2007-07-31 17:00:22.000000000 +0200
@@ -112,6 +112,16 @@
 
 };
 
+enum {
+	X86EMUL_BASE_CS,
+	X86EMUL_BASE_DS,
+	X86EMUL_BASE_ES,
+	X86EMUL_BASE_SS,
+	X86EMUL_BASE_GS,
+	X86EMUL_BASE_FS,
+	X86EMUL_BASE_SIZE
+};
+
 struct x86_emulate_ctxt {
 	/* Register state before/after emulation. */
 	struct kvm_vcpu *vcpu;
@@ -122,13 +132,7 @@
 
 	/* Emulated execution mode, represented by an X86EMUL_MODE value. */
 	int mode;
-
-	unsigned long cs_base;
-	unsigned long ds_base;
-	unsigned long es_base;
-	unsigned long ss_base;
-	unsigned long gs_base;
-	unsigned long fs_base;
+	unsigned long base[X86EMUL_BASE_SIZE];
 };
 
 /* Execution mode, passed to the emulator. */

[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 315 bytes --]

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

[-- Attachment #3: Type: text/plain, Size: 186 bytes --]

_______________________________________________
kvm-devel mailing list
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/kvm-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 2/5] group all prefix decoding results in a structure called x86_prefix
       [not found]     ` <46B04DD6.7010702-6ktuUTfB/bM@public.gmane.org>
@ 2007-08-01  9:13       ` Laurent Vivier
       [not found]         ` <46B04EB9.5010103-6ktuUTfB/bM@public.gmane.org>
  0 siblings, 1 reply; 10+ messages in thread
From: Laurent Vivier @ 2007-08-01  9:13 UTC (permalink / raw)
  To: kvm-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 345 bytes --]

To be able to extract easily prefix decoding from x86_emulate_memop(), group all
prefix decoding results in a structure called x86_prefix.

Signed-off-by: Laurent Vivier <Laurent.Vivier-6ktuUTfB/bM@public.gmane.org>
-- 
------------- Laurent.Vivier-6ktuUTfB/bM@public.gmane.org  --------------
          "Software is hard" - Donald Knuth

[-- Attachment #1.1.2: x86_prefix --]
[-- Type: text/plain, Size: 18464 bytes --]

Index: kvm/drivers/kvm/x86_emulate.h
===================================================================
--- kvm.orig/drivers/kvm/x86_emulate.h	2007-07-31 17:00:22.000000000 +0200
+++ kvm/drivers/kvm/x86_emulate.h	2007-07-31 17:03:26.000000000 +0200
@@ -141,6 +141,21 @@
 #define X86EMUL_MODE_PROT32   4	/* 32-bit protected mode. */
 #define X86EMUL_MODE_PROT64   8	/* 64-bit (long) mode.    */
 
+struct x86_prefix {
+	unsigned int op_bytes;
+	unsigned int ad_bytes;
+	int override_base;
+
+	u8 lock;	/* LOCK prefix */
+	u8 rep;		/* REP prefix */
+	u8 rex;		/* REX prefix */
+
+	int index_reg;
+	int base_reg;
+	u8 modrm_reg;
+	u8 modrm_rm;
+};
+
 /* Host execution mode. */
 #if defined(__i386__)
 #define X86EMUL_MODE_HOST X86EMUL_MODE_PROT32
Index: kvm/drivers/kvm/x86_emulate.c
===================================================================
--- kvm.orig/drivers/kvm/x86_emulate.c	2007-07-31 17:01:52.000000000 +0200
+++ kvm/drivers/kvm/x86_emulate.c	2007-07-31 17:07:30.000000000 +0200
@@ -430,18 +430,18 @@
 
 /* Access/update address held in a register, based on addressing mode. */
 #define register_address(base, reg)                                     \
-	((base) + ((ad_bytes == sizeof(unsigned long)) ? (reg) :	\
-		   ((reg) & ((1UL << (ad_bytes << 3)) - 1))))
+	((base) + ((prefix.ad_bytes == sizeof(unsigned long)) ? (reg) :	\
+		   ((reg) & ((1UL << (prefix.ad_bytes << 3)) - 1))))
 
 #define register_address_increment(reg, inc)                            \
 	do {								\
 		/* signed type ensures sign extension to long */        \
 		int _inc = (inc);					\
-		if ( ad_bytes == sizeof(unsigned long) )		\
+		if ( prefix.ad_bytes == sizeof(unsigned long) )		\
 			(reg) += _inc;					\
 		else							\
-			(reg) = ((reg) & ~((1UL << (ad_bytes << 3)) - 1)) | \
-			   (((reg) + _inc) & ((1UL << (ad_bytes << 3)) - 1)); \
+			(reg) = ((reg) & ~((1UL << (prefix.ad_bytes << 3)) - 1)) | \
+			   (((reg) + _inc) & ((1UL << (prefix.ad_bytes << 3)) - 1)); \
 	} while (0)
 
 /*
@@ -483,18 +483,18 @@
 x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 {
 	unsigned d;
-	u8 b, sib, twobyte = 0, rex_prefix = 0;
-	u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
-	int override_base = -1;
-	unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i;
+	u8 b, sib, twobyte = 0;
+	u8 modrm, modrm_mod = 0;
+	unsigned int i;
 	int rc = 0;
 	struct operand src, dst;
 	unsigned long cr2 = ctxt->cr2;
 	int mode = ctxt->mode;
 	unsigned long modrm_ea;
-	int use_modrm_ea, index_reg = 0, base_reg = 0, scale, rip_relative = 0;
+	int use_modrm_ea, scale, rip_relative = 0;
 	int no_wb = 0;
 	u64 msr_data;
+	struct x86_prefix prefix;
 
 	/* Shadow copy of register state. Committed on successful emulation. */
 	unsigned long _regs[NR_VCPU_REGS];
@@ -502,19 +502,21 @@
 	unsigned long modrm_val = 0;
 
 	memcpy(_regs, ctxt->vcpu->regs, sizeof _regs);
+	memset(&prefix, 0, sizeof(prefix));
+	prefix.override_base = -1;
 
 	switch (mode) {
 	case X86EMUL_MODE_REAL:
 	case X86EMUL_MODE_PROT16:
-		op_bytes = ad_bytes = 2;
+		prefix.op_bytes = prefix.ad_bytes = 2;
 		break;
 	case X86EMUL_MODE_PROT32:
-		op_bytes = ad_bytes = 4;
+		prefix.op_bytes = prefix.ad_bytes = 4;
 		break;
 #ifdef CONFIG_X86_64
 	case X86EMUL_MODE_PROT64:
-		op_bytes = 4;
-		ad_bytes = 8;
+		prefix.op_bytes = 4;
+		prefix.ad_bytes = 8;
 		break;
 #endif
 	default:
@@ -525,37 +527,37 @@
 	for (i = 0; i < 8; i++) {
 		switch (b = insn_fetch(u8, 1, _eip)) {
 		case 0x66:	/* operand-size override */
-			op_bytes ^= 6;	/* switch between 2/4 bytes */
+			prefix.op_bytes ^= 6;	/* switch between 2/4 bytes */
 			break;
 		case 0x67:	/* address-size override */
 			if (mode == X86EMUL_MODE_PROT64)
-				ad_bytes ^= 12;	/* switch between 4/8 bytes */
+				prefix.ad_bytes ^= 12;	/* switch between 4/8 bytes */
 			else
-				ad_bytes ^= 6;	/* switch between 2/4 bytes */
+				prefix.ad_bytes ^= 6;	/* switch between 2/4 bytes */
 			break;
 		case 0x2e:	/* CS override */
-			override_base = X86EMUL_BASE_CS;
+			prefix.override_base = X86EMUL_BASE_CS;
 			break;
 		case 0x3e:	/* DS override */
-			override_base = X86EMUL_BASE_DS;
+			prefix.override_base = X86EMUL_BASE_DS;
 			break;
 		case 0x26:	/* ES override */
-			override_base = X86EMUL_BASE_ES;
+			prefix.override_base = X86EMUL_BASE_ES;
 			break;
 		case 0x64:	/* FS override */
-			override_base = X86EMUL_BASE_FS;
+			prefix.override_base = X86EMUL_BASE_FS;
 			break;
 		case 0x65:	/* GS override */
-			override_base = X86EMUL_BASE_GS;
+			prefix.override_base = X86EMUL_BASE_GS;
 			break;
 		case 0x36:	/* SS override */
-			override_base = X86EMUL_BASE_SS;
+			prefix.override_base = X86EMUL_BASE_SS;
 			break;
 		case 0xf0:	/* LOCK */
-			lock_prefix = 1;
+			prefix.lock = 1;
 			break;
 		case 0xf3:	/* REP/REPE/REPZ */
-			rep_prefix = 1;
+			prefix.rep = 1;
 			break;
 		case 0xf2:	/* REPNE/REPNZ */
 			break;
@@ -568,12 +570,12 @@
 
 	/* REX prefix. */
 	if ((mode == X86EMUL_MODE_PROT64) && ((b & 0xf0) == 0x40)) {
-		rex_prefix = b;
+		prefix.rex = b;
 		if (b & 8)
-			op_bytes = 8;	/* REX.W */
-		modrm_reg = (b & 4) << 1;	/* REX.R */
-		index_reg = (b & 2) << 2; /* REX.X */
-		modrm_rm = base_reg = (b & 1) << 3; /* REG.B */
+			prefix.op_bytes = 8;	/* REX.W */
+		prefix.modrm_reg = (b & 4) << 1;	/* REX.R */
+		prefix.index_reg = (b & 2) << 2; /* REX.X */
+		prefix.modrm_rm = prefix.base_reg = (b & 1) << 3; /* REG.B */
 		b = insn_fetch(u8, 1, _eip);
 	}
 
@@ -596,18 +598,18 @@
 	if (d & ModRM) {
 		modrm = insn_fetch(u8, 1, _eip);
 		modrm_mod |= (modrm & 0xc0) >> 6;
-		modrm_reg |= (modrm & 0x38) >> 3;
-		modrm_rm |= (modrm & 0x07);
+		prefix.modrm_reg |= (modrm & 0x38) >> 3;
+		prefix.modrm_rm |= (modrm & 0x07);
 		modrm_ea = 0;
 		use_modrm_ea = 1;
 
 		if (modrm_mod == 3) {
 			modrm_val = *(unsigned long *)
-				decode_register(modrm_rm, _regs, d & ByteOp);
+				decode_register(prefix.modrm_rm, _regs, d & ByteOp);
 			goto modrm_done;
 		}
 
-		if (ad_bytes == 2) {
+		if (prefix.ad_bytes == 2) {
 			unsigned bx = _regs[VCPU_REGS_RBX];
 			unsigned bp = _regs[VCPU_REGS_RBP];
 			unsigned si = _regs[VCPU_REGS_RSI];
@@ -616,7 +618,7 @@
 			/* 16-bit ModR/M decode. */
 			switch (modrm_mod) {
 			case 0:
-				if (modrm_rm == 6)
+				if (prefix.modrm_rm == 6)
 					modrm_ea += insn_fetch(u16, 2, _eip);
 				break;
 			case 1:
@@ -626,7 +628,7 @@
 				modrm_ea += insn_fetch(u16, 2, _eip);
 				break;
 			}
-			switch (modrm_rm) {
+			switch (prefix.modrm_rm) {
 			case 0:
 				modrm_ea += bx + si;
 				break;
@@ -653,52 +655,52 @@
 				modrm_ea += bx;
 				break;
 			}
-			if (modrm_rm == 2 || modrm_rm == 3 ||
-			    (modrm_rm == 6 && modrm_mod != 0))
-				if (override_base == -1)
-					override_base = X86EMUL_BASE_SS;
+			if (prefix.modrm_rm == 2 || prefix.modrm_rm == 3 ||
+			    (prefix.modrm_rm == 6 && modrm_mod != 0))
+				if (prefix.override_base == -1)
+					prefix.override_base = X86EMUL_BASE_SS;
 			modrm_ea = (u16)modrm_ea;
 		} else {
 			/* 32/64-bit ModR/M decode. */
-			switch (modrm_rm) {
+			switch (prefix.modrm_rm) {
 			case 4:
 			case 12:
 				sib = insn_fetch(u8, 1, _eip);
-				index_reg |= (sib >> 3) & 7;
-				base_reg |= sib & 7;
+				prefix.index_reg |= (sib >> 3) & 7;
+				prefix.base_reg |= sib & 7;
 				scale = sib >> 6;
 
-				switch (base_reg) {
+				switch (prefix.base_reg) {
 				case 5:
 					if (modrm_mod != 0)
-						modrm_ea += _regs[base_reg];
+						modrm_ea += _regs[prefix.base_reg];
 					else
 						modrm_ea += insn_fetch(s32, 4, _eip);
 					break;
 				default:
-					modrm_ea += _regs[base_reg];
+					modrm_ea += _regs[prefix.base_reg];
 				}
-				switch (index_reg) {
+				switch (prefix.index_reg) {
 				case 4:
 					break;
 				default:
-					modrm_ea += _regs[index_reg] << scale;
+					modrm_ea += _regs[prefix.index_reg] << scale;
 
 				}
 				break;
 			case 5:
 				if (modrm_mod != 0)
-					modrm_ea += _regs[modrm_rm];
+					modrm_ea += _regs[prefix.modrm_rm];
 				else if (mode == X86EMUL_MODE_PROT64)
 					rip_relative = 1;
 				break;
 			default:
-				modrm_ea += _regs[modrm_rm];
+				modrm_ea += _regs[prefix.modrm_rm];
 				break;
 			}
 			switch (modrm_mod) {
 			case 0:
-				if (modrm_rm == 5)
+				if (prefix.modrm_rm == 5)
 					modrm_ea += insn_fetch(s32, 4, _eip);
 				break;
 			case 1:
@@ -709,15 +711,15 @@
 				break;
 			}
 		}
-		if (override_base == -1)
-			override_base = X86EMUL_BASE_DS;
+		if (prefix.override_base == -1)
+			prefix.override_base = X86EMUL_BASE_DS;
 		if (mode == X86EMUL_MODE_PROT64 &&
-		    override_base != X86EMUL_BASE_FS &&
-		    override_base != X86EMUL_BASE_GS)
-			override_base = -1;
+		    prefix.override_base != X86EMUL_BASE_FS &&
+		    prefix.override_base != X86EMUL_BASE_GS)
+			prefix.override_base = -1;
 
-		if (override_base != -1)
-			modrm_ea += ctxt->base[override_base];
+		if (prefix.override_base != -1)
+			modrm_ea += ctxt->base[prefix.override_base];
 
 		if (rip_relative) {
 			modrm_ea += _eip;
@@ -729,13 +731,13 @@
 				if (d & ByteOp)
 					modrm_ea += 1;
 				else
-					if (op_bytes == 8)
+					if (prefix.op_bytes == 8)
 						modrm_ea += 4;
 					else
-						modrm_ea += op_bytes;
+						modrm_ea += prefix.op_bytes;
 			}
 		}
-		if (ad_bytes != 8)
+		if (prefix.ad_bytes != 8)
 			modrm_ea = (u32)modrm_ea;
 		cr2 = modrm_ea;
 	modrm_done:
@@ -752,13 +754,13 @@
 	case SrcReg:
 		src.type = OP_REG;
 		if (d & ByteOp) {
-			src.ptr = decode_register(modrm_reg, _regs,
-						  (rex_prefix == 0));
+			src.ptr = decode_register(prefix.modrm_reg, _regs,
+						  (prefix.rex == 0));
 			src.val = src.orig_val = *(u8 *) src.ptr;
 			src.bytes = 1;
 		} else {
-			src.ptr = decode_register(modrm_reg, _regs, 0);
-			switch ((src.bytes = op_bytes)) {
+			src.ptr = decode_register(prefix.modrm_reg, _regs, 0);
+			switch ((src.bytes = prefix.op_bytes)) {
 			case 2:
 				src.val = src.orig_val = *(u16 *) src.ptr;
 				break;
@@ -778,7 +780,7 @@
 		src.bytes = 4;
 		goto srcmem_common;
 	case SrcMem:
-		src.bytes = (d & ByteOp) ? 1 : op_bytes;
+		src.bytes = (d & ByteOp) ? 1 : prefix.op_bytes;
 	      srcmem_common:
 		src.type = OP_MEM;
 		src.ptr = (unsigned long *)cr2;
@@ -790,7 +792,7 @@
 	case SrcImm:
 		src.type = OP_IMM;
 		src.ptr = (unsigned long *)_eip;
-		src.bytes = (d & ByteOp) ? 1 : op_bytes;
+		src.bytes = (d & ByteOp) ? 1 : prefix.op_bytes;
 		if (src.bytes == 8)
 			src.bytes = 4;
 		/* NB. Immediates are sign-extended as necessary. */
@@ -823,13 +825,13 @@
 		dst.type = OP_REG;
 		if ((d & ByteOp)
 		    && !(twobyte && (b == 0xb6 || b == 0xb7))) {
-			dst.ptr = decode_register(modrm_reg, _regs,
-						  (rex_prefix == 0));
+			dst.ptr = decode_register(prefix.modrm_reg, _regs,
+						  (prefix.rex == 0));
 			dst.val = *(u8 *) dst.ptr;
 			dst.bytes = 1;
 		} else {
-			dst.ptr = decode_register(modrm_reg, _regs, 0);
-			switch ((dst.bytes = op_bytes)) {
+			dst.ptr = decode_register(prefix.modrm_reg, _regs, 0);
+			switch ((dst.bytes = prefix.op_bytes)) {
 			case 2:
 				dst.val = *(u16 *)dst.ptr;
 				break;
@@ -845,7 +847,7 @@
 	case DstMem:
 		dst.type = OP_MEM;
 		dst.ptr = (unsigned long *)cr2;
-		dst.bytes = (d & ByteOp) ? 1 : op_bytes;
+		dst.bytes = (d & ByteOp) ? 1 : prefix.op_bytes;
 		if (d & BitOp) {
 			unsigned long mask = ~(dst.bytes * 8 - 1);
 
@@ -901,7 +903,7 @@
 		dst.val = (s32) src.val;
 		break;
 	case 0x80 ... 0x83:	/* Grp1 */
-		switch (modrm_reg) {
+		switch (prefix.modrm_reg) {
 		case 0:
 			goto add;
 		case 1:
@@ -945,16 +947,16 @@
 		 * prefix.
 		 */
 		dst.val = src.val;
-		lock_prefix = 1;
+		prefix.lock = 1;
 		break;
 	case 0xa0 ... 0xa1:	/* mov */
 		dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX];
 		dst.val = src.val;
-		_eip += ad_bytes;	/* skip src displacement */
+		_eip += prefix.ad_bytes;	/* skip src displacement */
 		break;
 	case 0xa2 ... 0xa3:	/* mov */
 		dst.val = (unsigned long)_regs[VCPU_REGS_RAX];
-		_eip += ad_bytes;	/* skip dst displacement */
+		_eip += prefix.ad_bytes;	/* skip dst displacement */
 		break;
 	case 0x88 ... 0x8b:	/* mov */
 	case 0xc6 ... 0xc7:	/* mov (sole member of Grp11) */
@@ -973,7 +975,7 @@
 		break;
 	case 0xc0 ... 0xc1:
 	      grp2:		/* Grp2 */
-		switch (modrm_reg) {
+		switch (prefix.modrm_reg) {
 		case 0:	/* rol */
 			emulate_2op_SrcB("rol", src, dst, _eflags);
 			break;
@@ -1005,7 +1007,7 @@
 		src.val = _regs[VCPU_REGS_RCX];
 		goto grp2;
 	case 0xf6 ... 0xf7:	/* Grp3 */
-		switch (modrm_reg) {
+		switch (prefix.modrm_reg) {
 		case 0 ... 1:	/* test */
 			/*
 			 * Special case in Grp3: test has an immediate
@@ -1013,7 +1015,7 @@
 			 */
 			src.type = OP_IMM;
 			src.ptr = (unsigned long *)_eip;
-			src.bytes = (d & ByteOp) ? 1 : op_bytes;
+			src.bytes = (d & ByteOp) ? 1 : prefix.op_bytes;
 			if (src.bytes == 8)
 				src.bytes = 4;
 			switch (src.bytes) {
@@ -1039,7 +1041,7 @@
 		}
 		break;
 	case 0xfe ... 0xff:	/* Grp4/Grp5 */
-		switch (modrm_reg) {
+		switch (prefix.modrm_reg) {
 		case 0:	/* inc */
 			emulate_1op("inc", dst, _eflags);
 			break;
@@ -1091,7 +1093,7 @@
 			}
 			break;
 		case OP_MEM:
-			if (lock_prefix)
+			if (prefix.lock)
 				rc = ops->cmpxchg_emulated((unsigned long)dst.
 							   ptr, &dst.orig_val,
 							   &dst.val, dst.bytes,
@@ -1118,7 +1120,7 @@
 special_insn:
 	if (twobyte)
 		goto twobyte_special_insn;
-	if (rep_prefix) {
+	if (prefix.rep) {
 		if (_regs[VCPU_REGS_RCX] == 0) {
 			ctxt->vcpu->rip = _eip;
 			goto done;
@@ -1129,13 +1131,13 @@
 	switch (b) {
 	case 0xa4 ... 0xa5:	/* movs */
 		dst.type = OP_MEM;
-		dst.bytes = (d & ByteOp) ? 1 : op_bytes;
+		dst.bytes = (d & ByteOp) ? 1 : prefix.op_bytes;
 		dst.ptr = (unsigned long *)register_address(
 						ctxt->base[X86EMUL_BASE_ES],
 							_regs[VCPU_REGS_RDI]);
 		if ((rc = ops->read_emulated(register_address(
-		      (override_base != -1) ?
-		      	ctxt->base[override_base] : ctxt->base[X86EMUL_BASE_DS],
+		      (prefix.override_base != -1) ?
+		      	ctxt->base[prefix.override_base] : ctxt->base[X86EMUL_BASE_DS],
 		      _regs[VCPU_REGS_RSI]), &dst.val, dst.bytes, ctxt->vcpu)) != 0)
 			goto done;
 		register_address_increment(_regs[VCPU_REGS_RSI],
@@ -1148,7 +1150,7 @@
 		goto cannot_emulate;
 	case 0xaa ... 0xab:	/* stos */
 		dst.type = OP_MEM;
-		dst.bytes = (d & ByteOp) ? 1 : op_bytes;
+		dst.bytes = (d & ByteOp) ? 1 : prefix.op_bytes;
 		dst.ptr = (unsigned long *)cr2;
 		dst.val = _regs[VCPU_REGS_RAX];
 		register_address_increment(_regs[VCPU_REGS_RDI],
@@ -1156,7 +1158,7 @@
 		break;
 	case 0xac ... 0xad:	/* lods */
 		dst.type = OP_REG;
-		dst.bytes = (d & ByteOp) ? 1 : op_bytes;
+		dst.bytes = (d & ByteOp) ? 1 : prefix.op_bytes;
 		dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX];
 		if ((rc = ops->read_emulated(cr2, &dst.val, dst.bytes,
 					     ctxt->vcpu)) != 0)
@@ -1179,11 +1181,11 @@
 pop_instruction:
 		if ((rc = ops->read_std(
 			register_address(ctxt->base[X86EMUL_BASE_SS],
-			_regs[VCPU_REGS_RSP]), dst.ptr, op_bytes, ctxt->vcpu))
+			_regs[VCPU_REGS_RSP]), dst.ptr, prefix.op_bytes, ctxt->vcpu))
 			!= 0)
 			goto done;
 
-		register_address_increment(_regs[VCPU_REGS_RSP], op_bytes);
+		register_address_increment(_regs[VCPU_REGS_RSP], prefix.op_bytes);
 		no_wb = 1; /* Disable writeback. */
 		break;
 	}
@@ -1194,20 +1196,20 @@
 	case 0x01: /* lgdt, lidt, lmsw */
 		/* Disable writeback. */
 		no_wb = 1;
-		switch (modrm_reg) {
+		switch (prefix.modrm_reg) {
 			u16 size;
 			unsigned long address;
 
 		case 2: /* lgdt */
 			rc = read_descriptor(ctxt, ops, src.ptr,
-					     &size, &address, op_bytes);
+					     &size, &address, prefix.op_bytes);
 			if (rc)
 				goto done;
 			realmode_lgdt(ctxt->vcpu, size, address);
 			break;
 		case 3: /* lidt */
 			rc = read_descriptor(ctxt, ops, src.ptr,
-					     &size, &address, op_bytes);
+					     &size, &address, prefix.op_bytes);
 			if (rc)
 				goto done;
 			realmode_lidt(ctxt->vcpu, size, address);
@@ -1215,7 +1217,7 @@
 		case 4: /* smsw */
 			if (modrm_mod != 3)
 				goto cannot_emulate;
-			*(u16 *)&_regs[modrm_rm]
+			*(u16 *)&_regs[prefix.modrm_rm]
 				= realmode_get_cr(ctxt->vcpu, 0);
 			break;
 		case 6: /* lmsw */
@@ -1233,12 +1235,12 @@
 	case 0x21: /* mov from dr to reg */
 		if (modrm_mod != 3)
 			goto cannot_emulate;
-		rc = emulator_get_dr(ctxt, modrm_reg, &_regs[modrm_rm]);
+		rc = emulator_get_dr(ctxt, prefix.modrm_reg, &_regs[prefix.modrm_rm]);
 		break;
 	case 0x23: /* mov from reg to dr */
 		if (modrm_mod != 3)
 			goto cannot_emulate;
-		rc = emulator_set_dr(ctxt, modrm_reg, _regs[modrm_rm]);
+		rc = emulator_set_dr(ctxt, prefix.modrm_reg, _regs[prefix.modrm_rm]);
 		break;
 	case 0x40 ... 0x4f:	/* cmov */
 		dst.val = dst.orig_val = src.val;
@@ -1310,7 +1312,7 @@
 		emulate_2op_SrcV_nobyte("bts", src, dst, _eflags);
 		break;
 	case 0xb6 ... 0xb7:	/* movzx */
-		dst.bytes = op_bytes;
+		dst.bytes = prefix.op_bytes;
 		dst.val = (d & ByteOp) ? (u8) src.val : (u16) src.val;
 		break;
 	case 0xbb:
@@ -1319,7 +1321,7 @@
 		emulate_2op_SrcV_nobyte("btc", src, dst, _eflags);
 		break;
 	case 0xba:		/* Grp8 */
-		switch (modrm_reg & 3) {
+		switch (prefix.modrm_reg & 3) {
 		case 0:
 			goto bt;
 		case 1:
@@ -1331,7 +1333,7 @@
 		}
 		break;
 	case 0xbe ... 0xbf:	/* movsx */
-		dst.bytes = op_bytes;
+		dst.bytes = prefix.op_bytes;
 		dst.val = (d & ByteOp) ? (s8) src.val : (s16) src.val;
 		break;
 	}
@@ -1352,12 +1354,12 @@
 	case 0x20: /* mov cr, reg */
 		if (modrm_mod != 3)
 			goto cannot_emulate;
-		_regs[modrm_rm] = realmode_get_cr(ctxt->vcpu, modrm_reg);
+		_regs[prefix.modrm_rm] = realmode_get_cr(ctxt->vcpu, prefix.modrm_reg);
 		break;
 	case 0x22: /* mov reg, cr */
 		if (modrm_mod != 3)
 			goto cannot_emulate;
-		realmode_set_cr(ctxt->vcpu, modrm_reg, modrm_val, &_eflags);
+		realmode_set_cr(ctxt->vcpu, prefix.modrm_reg, modrm_val, &_eflags);
 		break;
 	case 0x30:
 		/* wrmsr */

[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 315 bytes --]

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

[-- Attachment #3: Type: text/plain, Size: 186 bytes --]

_______________________________________________
kvm-devel mailing list
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/kvm-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 3/5] extract prefix decoding part from x86_emulate_memop() to x86_decode_prefix()
       [not found]         ` <46B04EB9.5010103-6ktuUTfB/bM@public.gmane.org>
@ 2007-08-01  9:16           ` Laurent Vivier
       [not found]             ` <46B04F56.60607-6ktuUTfB/bM@public.gmane.org>
  0 siblings, 1 reply; 10+ messages in thread
From: Laurent Vivier @ 2007-08-01  9:16 UTC (permalink / raw)
  To: kvm-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 283 bytes --]

Extract prefix decoding part from x86_emulate_memop() to x86_decode_prefix().

Signed-off-by: Laurent Vivier <Laurent.Vivier-6ktuUTfB/bM@public.gmane.org>
-- 
------------- Laurent.Vivier-6ktuUTfB/bM@public.gmane.org  --------------
          "Software is hard" - Donald Knuth

[-- Attachment #1.1.2: x86_decode_prefix --]
[-- Type: text/plain, Size: 5811 bytes --]

Index: kvm/drivers/kvm/x86_emulate.c
===================================================================
--- kvm.orig/drivers/kvm/x86_emulate.c	2007-07-31 17:44:35.000000000 +0200
+++ kvm/drivers/kvm/x86_emulate.c	2007-07-31 18:23:39.000000000 +0200
@@ -480,43 +480,24 @@
 }
 
 int
-x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
+x86_decode_prefix(int mode, u8 *inst, struct x86_prefix *prefix)
 {
-	unsigned d;
-	u8 b, sib, twobyte = 0;
-	u8 modrm, modrm_mod = 0;
-	unsigned int i;
-	int rc = 0;
-	struct operand src, dst;
-	unsigned long cr2 = ctxt->cr2;
-	int mode = ctxt->mode;
-	unsigned long modrm_ea;
-	int use_modrm_ea, scale, rip_relative = 0;
-	int no_wb = 0;
-	u64 msr_data;
-	struct x86_prefix prefix;
-
-	/* Shadow copy of register state. Committed on successful emulation. */
-	unsigned long _regs[NR_VCPU_REGS];
-	unsigned long _eip = ctxt->vcpu->rip, _eflags = ctxt->eflags;
-	unsigned long modrm_val = 0;
-
-	memcpy(_regs, ctxt->vcpu->regs, sizeof _regs);
-	memset(&prefix, 0, sizeof(prefix));
-	prefix.override_base = -1;
+	unsigned int op_bytes, ad_bytes;
+	int i;
+	u8 b;
 
 	switch (mode) {
 	case X86EMUL_MODE_REAL:
 	case X86EMUL_MODE_PROT16:
-		prefix.op_bytes = prefix.ad_bytes = 2;
+		op_bytes = ad_bytes = 2;
 		break;
 	case X86EMUL_MODE_PROT32:
-		prefix.op_bytes = prefix.ad_bytes = 4;
+		op_bytes = ad_bytes = 4;
 		break;
 #ifdef CONFIG_X86_64
 	case X86EMUL_MODE_PROT64:
-		prefix.op_bytes = 4;
-		prefix.ad_bytes = 8;
+		op_bytes = 4;
+		ad_bytes = 8;
 		break;
 #endif
 	default:
@@ -525,39 +506,39 @@
 
 	/* Legacy prefixes. */
 	for (i = 0; i < 8; i++) {
-		switch (b = insn_fetch(u8, 1, _eip)) {
+		switch (b = inst[i]) {
 		case 0x66:	/* operand-size override */
-			prefix.op_bytes ^= 6;	/* switch between 2/4 bytes */
+			op_bytes ^= 6;	/* switch between 2/4 bytes */
 			break;
 		case 0x67:	/* address-size override */
 			if (mode == X86EMUL_MODE_PROT64)
-				prefix.ad_bytes ^= 12;	/* switch between 4/8 bytes */
+				ad_bytes ^= 12;	/* switch between 4/8 bytes */
 			else
-				prefix.ad_bytes ^= 6;	/* switch between 2/4 bytes */
+				ad_bytes ^= 6;	/* switch between 2/4 bytes */
 			break;
 		case 0x2e:	/* CS override */
-			prefix.override_base = X86EMUL_BASE_CS;
+			prefix->override_base = X86EMUL_BASE_CS;
 			break;
 		case 0x3e:	/* DS override */
-			prefix.override_base = X86EMUL_BASE_DS;
+			prefix->override_base = X86EMUL_BASE_DS;
 			break;
 		case 0x26:	/* ES override */
-			prefix.override_base = X86EMUL_BASE_ES;
+			prefix->override_base = X86EMUL_BASE_ES;
 			break;
 		case 0x64:	/* FS override */
-			prefix.override_base = X86EMUL_BASE_FS;
+			prefix->override_base = X86EMUL_BASE_FS;
 			break;
 		case 0x65:	/* GS override */
-			prefix.override_base = X86EMUL_BASE_GS;
+			prefix->override_base = X86EMUL_BASE_GS;
 			break;
 		case 0x36:	/* SS override */
-			prefix.override_base = X86EMUL_BASE_SS;
+			prefix->override_base = X86EMUL_BASE_SS;
 			break;
 		case 0xf0:	/* LOCK */
-			prefix.lock = 1;
+			prefix->lock = 1;
 			break;
 		case 0xf3:	/* REP/REPE/REPZ */
-			prefix.rep = 1;
+			prefix->rep = 1;
 			break;
 		case 0xf2:	/* REPNE/REPNZ */
 			break;
@@ -570,15 +551,62 @@
 
 	/* REX prefix. */
 	if ((mode == X86EMUL_MODE_PROT64) && ((b & 0xf0) == 0x40)) {
-		prefix.rex = b;
+		prefix->rex = b;
 		if (b & 8)
-			prefix.op_bytes = 8;	/* REX.W */
-		prefix.modrm_reg = (b & 4) << 1;	/* REX.R */
-		prefix.index_reg = (b & 2) << 2; /* REX.X */
-		prefix.modrm_rm = prefix.base_reg = (b & 1) << 3; /* REG.B */
-		b = insn_fetch(u8, 1, _eip);
+			op_bytes = 8;	/* REX.W */
+		prefix->modrm_reg = (b & 4) << 1;	/* REX.R */
+		prefix->index_reg = (b & 2) << 2; /* REX.X */
+		prefix->modrm_rm = prefix->base_reg = (b & 1) << 3; /* REG.B */
+		i++;
 	}
 
+	prefix->op_bytes = op_bytes;
+	prefix->ad_bytes = ad_bytes;
+
+	return i;
+}
+EXPORT_SYMBOL_GPL(x86_decode_prefix);
+
+int
+x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
+{
+	unsigned d;
+	u8 b, sib, twobyte = 0;
+	u8 modrm, modrm_mod = 0;
+	int rc = 0;
+	struct operand src, dst;
+	unsigned long cr2 = ctxt->cr2;
+	int mode = ctxt->mode;
+	unsigned long modrm_ea;
+	int use_modrm_ea, scale, rip_relative = 0;
+	int no_wb = 0;
+	u64 msr_data, inst;
+	struct x86_prefix prefix;
+	int count;
+
+	/* Shadow copy of register state. Committed on successful emulation. */
+	unsigned long _regs[NR_VCPU_REGS];
+	unsigned long _eip = ctxt->vcpu->rip, _eflags = ctxt->eflags;
+	unsigned long modrm_val = 0;
+
+	memcpy(_regs, ctxt->vcpu->regs, sizeof _regs);
+
+	/* decode prefixes */
+
+	rc = ops->read_std(_eip + ctxt->base[X86EMUL_BASE_CS],
+			   &inst, sizeof(inst), ctxt->vcpu);
+	if ( rc != 0 )
+		goto done;
+
+	memset(&prefix, 0, sizeof(prefix));
+	prefix.override_base = -1;
+
+	count = x86_decode_prefix(mode, (u8*)&inst, &prefix);
+	if (count == -1)
+		return -1;
+	_eip += count;
+	b = insn_fetch(u8, 1, _eip);
+
 	/* Opcode byte(s). */
 	d = opcode_table[b];
 	if (d == 0) {
Index: kvm/drivers/kvm/x86_emulate.h
===================================================================
--- kvm.orig/drivers/kvm/x86_emulate.h	2007-07-31 18:00:51.000000000 +0200
+++ kvm/drivers/kvm/x86_emulate.h	2007-07-31 18:01:53.000000000 +0200
@@ -164,6 +164,13 @@
 #endif
 
 /*
+ * x86_decode_prefix: Decode instruction prefixes
+ * Returns -1 on failure, 0 on success.
+ */
+int
+x86_decode_prefix(int mode, u8 *inst, struct x86_prefix *prefix);
+
+/*
  * x86_emulate_memop: Emulate an instruction that faulted attempting to
  *                    read/write a 'special' memory area.
  * Returns -1 on failure, 0 on success.

[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 315 bytes --]

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

[-- Attachment #3: Type: text/plain, Size: 186 bytes --]

_______________________________________________
kvm-devel mailing list
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/kvm-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 4/5] vmx.c uses x86_decode_prefix() instead of get_io_count().
       [not found]             ` <46B04F56.60607-6ktuUTfB/bM@public.gmane.org>
@ 2007-08-01  9:19               ` Laurent Vivier
       [not found]                 ` <46B0501C.6060409-6ktuUTfB/bM@public.gmane.org>
  0 siblings, 1 reply; 10+ messages in thread
From: Laurent Vivier @ 2007-08-01  9:19 UTC (permalink / raw)
  To: kvm-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 263 bytes --]

vmx.c uses x86_decode_prefix() instead of get_io_count().

Signed-off-by: Laurent Vivier <Laurent.Vivier-6ktuUTfB/bM@public.gmane.org>
-- 
------------- Laurent.Vivier-6ktuUTfB/bM@public.gmane.org  --------------
          "Software is hard" - Donald Knuth

[-- Attachment #1.1.2: vmx-decode_prefix --]
[-- Type: text/plain, Size: 2515 bytes --]

Index: kvm/drivers/kvm/vmx.c
===================================================================
--- kvm.orig/drivers/kvm/vmx.c	2007-08-01 10:37:40.000000000 +0200
+++ kvm/drivers/kvm/vmx.c	2007-08-01 10:40:04.000000000 +0200
@@ -1761,57 +1761,6 @@
 	return 0;
 }
 
-static int get_io_count(struct kvm_vcpu *vcpu, unsigned long *count)
-{
-	u64 inst;
-	gva_t rip;
-	int countr_size;
-	int i;
-
-	if ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_VM)) {
-		countr_size = 2;
-	} else {
-		u32 cs_ar = vmcs_read32(GUEST_CS_AR_BYTES);
-
-		countr_size = (cs_ar & AR_L_MASK) ? 8:
-			      (cs_ar & AR_DB_MASK) ? 4: 2;
-	}
-
-	rip =  vmcs_readl(GUEST_RIP);
-	if (countr_size != 8)
-		rip += vmcs_readl(GUEST_CS_BASE);
-
-	if (emulator_read_std(rip, &inst, sizeof(inst), vcpu) !=
-							X86EMUL_CONTINUE)
-		return 0;
-
-	for (i = 0; i < sizeof(inst); i++) {
-		switch (((u8*)&inst)[i]) {
-		case 0xf0:
-		case 0xf2:
-		case 0xf3:
-		case 0x2e:
-		case 0x36:
-		case 0x3e:
-		case 0x26:
-		case 0x64:
-		case 0x65:
-		case 0x66:
-			break;
-		case 0x67:
-			countr_size = (countr_size == 2) ? 4: (countr_size >> 1);
-		default:
-			goto done;
-		}
-	}
-	return 0;
-done:
-	countr_size *= 8;
-	*count = vcpu->regs[VCPU_REGS_RCX] & (~0ULL >> (64 - countr_size));
-	//printk("cx: %lx\n", vcpu->regs[VCPU_REGS_RCX]);
-	return 1;
-}
-
 static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
 	u64 exit_qualification;
@@ -1831,8 +1780,32 @@
 	port = exit_qualification >> 16;
 	address = 0;
 	if (string) {
-		if (rep && !get_io_count(vcpu, &count))
+		int mode;
+		u64 inst;
+		gva_t rip;
+		struct x86_prefix prefix;
+		u32 cs_ar = vmcs_read32(GUEST_CS_AR_BYTES);
+		unsigned long addr_mask;
+
+		mode = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_VM) ?
+				X86EMUL_MODE_REAL : (cs_ar & AR_L_MASK)
+				? X86EMUL_MODE_PROT64 : (cs_ar & AR_DB_MASK)
+				? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
+
+		rip = vmcs_readl(GUEST_RIP);
+		if (mode != X86EMUL_MODE_PROT64)
+			rip += vmcs_readl(GUEST_CS_BASE);
+		if (emulator_read_std(rip, &inst, sizeof(inst), vcpu)
+					!= X86EMUL_CONTINUE)
+			return 1;
+
+		if (x86_decode_prefix(mode, (u8*)&inst, &prefix) == -1)
 			return 1;
+
+		addr_mask = (~0ULL >> (64 - (prefix.ad_bytes <<3)));
+		if (rep)
+			count = vcpu->regs[VCPU_REGS_RCX] & addr_mask;
+
 		address = vmcs_readl(GUEST_LINEAR_ADDRESS);
 	}
 	return kvm_setup_pio(vcpu, kvm_run, in, size, count, string, down,

[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 315 bytes --]

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

[-- Attachment #3: Type: text/plain, Size: 186 bytes --]

_______________________________________________
kvm-devel mailing list
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/kvm-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 5/5] svm.c uses x86_decode_prefix() instead of io_address() and io_get_override().
       [not found]                 ` <46B0501C.6060409-6ktuUTfB/bM@public.gmane.org>
@ 2007-08-01  9:22                   ` Laurent Vivier
  2007-08-02  8:48                   ` [PATCH 4/5] vmx.c uses x86_decode_prefix() instead of get_io_count() Avi Kivity
  1 sibling, 0 replies; 10+ messages in thread
From: Laurent Vivier @ 2007-08-01  9:22 UTC (permalink / raw)
  To: kvm-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 374 bytes --]

svm.c uses x86_decode_prefix() instead of io_address() and io_get_override().

*** WARNING: the SVM part has not been tested because I don't have any AMD
system. ***

Signed-off-by: Laurent Vivier <Laurent.Vivier-6ktuUTfB/bM@public.gmane.org>
-- 
------------- Laurent.Vivier-6ktuUTfB/bM@public.gmane.org  --------------
          "Software is hard" - Donald Knuth

[-- Attachment #1.1.2: svm-decode_prefix --]
[-- Type: text/plain, Size: 6694 bytes --]

Index: kvm/drivers/kvm/svm.c
===================================================================
--- kvm.orig/drivers/kvm/svm.c	2007-08-01 10:10:24.000000000 +0200
+++ kvm/drivers/kvm/svm.c	2007-08-01 10:37:30.000000000 +0200
@@ -98,20 +98,6 @@
 	return svm_features & feat;
 }
 
-static unsigned get_addr_size(struct vcpu_svm *svm)
-{
-	struct vmcb_save_area *sa = &svm->vmcb->save;
-	u16 cs_attrib;
-
-	if (!(sa->cr0 & X86_CR0_PE) || (sa->rflags & X86_EFLAGS_VM))
-		return 2;
-
-	cs_attrib = sa->cs.attrib;
-
-	return (cs_attrib & SVM_SELECTOR_L_MASK) ? 8 :
-				(cs_attrib & SVM_SELECTOR_DB_MASK) ? 4 : 2;
-}
-
 static inline u8 pop_irq(struct kvm_vcpu *vcpu)
 {
 	int word_index = __ffs(vcpu->irq_summary);
@@ -996,112 +982,6 @@
 	return 0;
 }
 
-static int io_get_override(struct vcpu_svm *svm,
-			  struct vmcb_seg **seg,
-			  int *addr_override)
-{
-	u8 inst[MAX_INST_SIZE];
-	unsigned ins_length;
-	gva_t rip;
-	int i;
-
-	rip =  svm->vmcb->save.rip;
-	ins_length = svm->next_rip - rip;
-	rip += svm->vmcb->save.cs.base;
-
-	if (ins_length > MAX_INST_SIZE)
-		printk(KERN_DEBUG
-		       "%s: inst length err, cs base 0x%llx rip 0x%llx "
-		       "next rip 0x%llx ins_length %u\n",
-		       __FUNCTION__,
-		       svm->vmcb->save.cs.base,
-		       svm->vmcb->save.rip,
-		       svm->vmcb->control.exit_info_2,
-		       ins_length);
-
-	if (emulator_read_std(rip, inst, ins_length, &svm->vcpu)
-	    != X86EMUL_CONTINUE)
-		/* #PF */
-		return 0;
-
-	*addr_override = 0;
-	*seg = NULL;
-	for (i = 0; i < ins_length; i++)
-		switch (inst[i]) {
-		case 0xf0:
-		case 0xf2:
-		case 0xf3:
-		case 0x66:
-			continue;
-		case 0x67:
-			*addr_override = 1;
-			continue;
-		case 0x2e:
-			*seg = &svm->vmcb->save.cs;
-			continue;
-		case 0x36:
-			*seg = &svm->vmcb->save.ss;
-			continue;
-		case 0x3e:
-			*seg = &svm->vmcb->save.ds;
-			continue;
-		case 0x26:
-			*seg = &svm->vmcb->save.es;
-			continue;
-		case 0x64:
-			*seg = &svm->vmcb->save.fs;
-			continue;
-		case 0x65:
-			*seg = &svm->vmcb->save.gs;
-			continue;
-		default:
-			return 1;
-		}
-	printk(KERN_DEBUG "%s: unexpected\n", __FUNCTION__);
-	return 0;
-}
-
-static unsigned long io_address(struct vcpu_svm *svm, int ins, gva_t *address)
-{
-	unsigned long addr_mask;
-	unsigned long *reg;
-	struct vmcb_seg *seg;
-	int addr_override;
-	struct vmcb_save_area *save_area = &svm->vmcb->save;
-	u16 cs_attrib = save_area->cs.attrib;
-	unsigned addr_size = get_addr_size(svm);
-
-	if (!io_get_override(svm, &seg, &addr_override))
-		return 0;
-
-	if (addr_override)
-		addr_size = (addr_size == 2) ? 4: (addr_size >> 1);
-
-	if (ins) {
-		reg = &svm->vcpu.regs[VCPU_REGS_RDI];
-		seg = &svm->vmcb->save.es;
-	} else {
-		reg = &svm->vcpu.regs[VCPU_REGS_RSI];
-		seg = (seg) ? seg : &svm->vmcb->save.ds;
-	}
-
-	addr_mask = ~0ULL >> (64 - (addr_size * 8));
-
-	if ((cs_attrib & SVM_SELECTOR_L_MASK) &&
-	    !(svm->vmcb->save.rflags & X86_EFLAGS_VM)) {
-		*address = (*reg & addr_mask);
-		return addr_mask;
-	}
-
-	if (!(seg->attrib & SVM_SELECTOR_P_SHIFT)) {
-		svm_inject_gp(&svm->vcpu, 0);
-		return 0;
-	}
-
-	*address = (*reg & addr_mask) + seg->base;
-	return addr_mask;
-}
-
 static int io_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
 {
 	u32 io_info = svm->vmcb->control.exit_info_1; //address size bug?
@@ -1109,6 +989,7 @@
 	unsigned port;
 	unsigned long count;
 	gva_t address = 0;
+	struct vmcb_save_area *sa = &svm->vmcb->save;
 
 	++svm->vcpu.stat.io_exits;
 
@@ -1120,21 +1001,96 @@
 	string = (io_info & SVM_IOIO_STR_MASK) != 0;
 	rep = (io_info & SVM_IOIO_REP_MASK) != 0;
 	count = 1;
-	down = (svm->vmcb->save.rflags & X86_EFLAGS_DF) != 0;
+	down = (sa->rflags & X86_EFLAGS_DF) != 0;
 
 	if (string) {
-		unsigned addr_mask;
+		int mode;
+		u8 inst[MAX_INST_SIZE];
+		unsigned ins_length;
+		gva_t rip;
+		struct x86_prefix prefix;
+		u16 cs_ar = sa->cs.attrib;
+		unsigned long addr_mask;
+
+		mode = (!(sa->cr0 & X86_CR0_PE) ||
+			(sa->rflags & X86_EFLAGS_VM)) ?
+			X86EMUL_MODE_REAL :  (cs_ar & SVM_SELECTOR_L_MASK)
+			? X86EMUL_MODE_PROT64 : (cs_ar & SVM_SELECTOR_DB_MASK)
+			? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
+
+		rip =  svm->vmcb->save.rip;
+		ins_length = svm->vmcb->save.rip - rip;
+		if (mode != X86EMUL_MODE_PROT64)
+			rip += svm->vmcb->save.cs.base;
+
+		if (ins_length > MAX_INST_SIZE)
+			printk(KERN_DEBUG
+			       "%s: inst length err, cs base 0x%llx rip 0x%llx "
+			       "next rip 0x%llx ins_length %u\n",
+			       __FUNCTION__,
+			       svm->vmcb->save.cs.base,
+			       svm->vmcb->save.rip,
+			       svm->vmcb->control.exit_info_2,
+			       ins_length);
 
-		addr_mask = io_address(svm, in, &address);
-		if (!addr_mask) {
-			printk(KERN_DEBUG "%s: get io address failed\n",
-			       __FUNCTION__);
+		if (emulator_read_std(rip, inst, ins_length, &svm->vcpu)
+					!= X86EMUL_CONTINUE)
+			return 1;
+
+		prefix.override_base = -1;
+		if (x86_decode_prefix(mode, (u8*)&inst, &prefix) == -1)
 			return 1;
-		}
 
+		addr_mask = (~0ULL >> (64 - (prefix.ad_bytes <<3)));
 		if (rep)
 			count = svm->vcpu.regs[VCPU_REGS_RCX] & addr_mask;
+
+		if (in)
+			address = svm->vcpu.regs[VCPU_REGS_RDI];
+		else
+			address = svm->vcpu.regs[VCPU_REGS_RSI];
+
+		address &= addr_mask;
+
+		if (mode != X86EMUL_MODE_PROT64) {
+			struct vmcb_seg *seg;
+
+			if (in)
+				seg = &svm->vmcb->save.es;
+			else switch(prefix.override_base) {
+				case -1:
+				case X86EMUL_BASE_DS:
+					seg = &svm->vmcb->save.ds;
+					break;
+				case X86EMUL_BASE_CS:
+					seg = &svm->vmcb->save.cs;
+					break;
+				case X86EMUL_BASE_ES:
+					seg = &svm->vmcb->save.es;
+					break;
+				case X86EMUL_BASE_GS:
+					seg = &svm->vmcb->save.gs;
+					break;
+				case X86EMUL_BASE_SS:
+					seg = &svm->vmcb->save.ss;
+					break;
+				default:
+					printk(KERN_DEBUG "%s: unexpected\n",
+						__FUNCTION__);
+					return 1;
+			}
+
+			if (seg->attrib & SVM_SELECTOR_P_SHIFT) {
+				svm_inject_gp(&svm->vcpu, 0);
+				printk(KERN_DEBUG "%s: get io address failed\n",
+					__FUNCTION__);
+				return 1;
+			}
+
+			address += seg->base;
+		}
 	}
+
 	return kvm_setup_pio(&svm->vcpu, kvm_run, in, size, count, string,
 			     down, address, rep, port);
 }
Index: kvm/drivers/kvm/.svm.c.swp
===================================================================
Binary files kvm.orig/drivers/kvm/.svm.c.swp	2007-08-01 10:12:34.000000000 +0200 and /dev/null	1970-01-01 00:00:00.000000000 +0000 differ

[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 315 bytes --]

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

[-- Attachment #3: Type: text/plain, Size: 186 bytes --]

_______________________________________________
kvm-devel mailing list
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/kvm-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/5] vmx.c uses x86_decode_prefix() instead of get_io_count().
       [not found]                 ` <46B0501C.6060409-6ktuUTfB/bM@public.gmane.org>
  2007-08-01  9:22                   ` [PATCH 5/5] svm.c uses x86_decode_prefix() instead of io_address() and io_get_override() Laurent Vivier
@ 2007-08-02  8:48                   ` Avi Kivity
       [not found]                     ` <46B19A7B.2030109-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
  1 sibling, 1 reply; 10+ messages in thread
From: Avi Kivity @ 2007-08-02  8:48 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: kvm-devel

Laurent Vivier wrote:
> vmx.c uses x86_decode_prefix() instead of get_io_count().
>
>   
>  static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
>  {
>  	u64 exit_qualification;
> @@ -1831,8 +1780,32 @@
>  	port = exit_qualification >> 16;
>  	address = 0;
>  	if (string) {
> -		if (rep && !get_io_count(vcpu, &count))
> +		int mode;
> +		u64 inst;
> +		gva_t rip;
> +		struct x86_prefix prefix;
> +		u32 cs_ar = vmcs_read32(GUEST_CS_AR_BYTES);
> +		unsigned long addr_mask;
> +
> +		mode = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_VM) ?
> +				X86EMUL_MODE_REAL : (cs_ar & AR_L_MASK)
> +				? X86EMUL_MODE_PROT64 : (cs_ar & AR_DB_MASK)
> +				? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
> +
> +		rip = vmcs_readl(GUEST_RIP);
> +		if (mode != X86EMUL_MODE_PROT64)
> +			rip += vmcs_readl(GUEST_CS_BASE);
> +		if (emulator_read_std(rip, &inst, sizeof(inst), vcpu)
> +					!= X86EMUL_CONTINUE)
> +			return 1;
> +
> +		if (x86_decode_prefix(mode, (u8*)&inst, &prefix) == -1)
>  			return 1;
> +
> +		addr_mask = (~0ULL >> (64 - (prefix.ad_bytes <<3)));
> +		if (rep)
> +			count = vcpu->regs[VCPU_REGS_RCX] & addr_mask;
> +
>  		address = vmcs_readl(GUEST_LINEAR_ADDRESS);
>  	}
>  	return kvm_setup_pio(vcpu, kvm_run, in, size, count, string, down,

How about just calliing emulate_instruction() from here (just for the 
string case)?  That will eliminate all the setup code.

x86_emulate_memop() will need to be extended to decode ins/outs, but 
that's fairly easy.

-- 
error compiling committee.c: too many arguments to function


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/5] vmx.c uses x86_decode_prefix() instead of get_io_count().
       [not found]                     ` <46B19A7B.2030109-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
@ 2007-08-02  9:34                       ` Laurent Vivier
       [not found]                         ` <46B1A51C.2040104-6ktuUTfB/bM@public.gmane.org>
  0 siblings, 1 reply; 10+ messages in thread
From: Laurent Vivier @ 2007-08-02  9:34 UTC (permalink / raw)
  To: Avi Kivity; +Cc: kvm-devel


[-- Attachment #1.1: Type: text/plain, Size: 2844 bytes --]

Avi Kivity wrote:
> Laurent Vivier wrote:
>> vmx.c uses x86_decode_prefix() instead of get_io_count().
>>
>>    static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
>>  {
>>      u64 exit_qualification;
>> @@ -1831,8 +1780,32 @@
>>      port = exit_qualification >> 16;
>>      address = 0;
>>      if (string) {
>> -        if (rep && !get_io_count(vcpu, &count))
>> +        int mode;
>> +        u64 inst;
>> +        gva_t rip;
>> +        struct x86_prefix prefix;
>> +        u32 cs_ar = vmcs_read32(GUEST_CS_AR_BYTES);
>> +        unsigned long addr_mask;
>> +
>> +        mode = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_VM) ?
>> +                X86EMUL_MODE_REAL : (cs_ar & AR_L_MASK)
>> +                ? X86EMUL_MODE_PROT64 : (cs_ar & AR_DB_MASK)
>> +                ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
>> +
>> +        rip = vmcs_readl(GUEST_RIP);
>> +        if (mode != X86EMUL_MODE_PROT64)
>> +            rip += vmcs_readl(GUEST_CS_BASE);
>> +        if (emulator_read_std(rip, &inst, sizeof(inst), vcpu)
>> +                    != X86EMUL_CONTINUE)
>> +            return 1;
>> +
>> +        if (x86_decode_prefix(mode, (u8*)&inst, &prefix) == -1)
>>              return 1;
>> +
>> +        addr_mask = (~0ULL >> (64 - (prefix.ad_bytes <<3)));
>> +        if (rep)
>> +            count = vcpu->regs[VCPU_REGS_RCX] & addr_mask;
>> +
>>          address = vmcs_readl(GUEST_LINEAR_ADDRESS);
>>      }
>>      return kvm_setup_pio(vcpu, kvm_run, in, size, count, string, down,
> 
> How about just calliing emulate_instruction() from here (just for the
> string case)?  That will eliminate all the setup code.

But this setup is in emulate_instruction() so it will be executed anyway.

> x86_emulate_memop() will need to be extended to decode ins/outs, but
> that's fairly easy.

X86_decode_prefix() is a subset of instruction decoding part of
x86_emulate_memop(), kvm_setup_pio() can be seen as a subset of instruction
emulating part of x86_emulate_memop(). So I think in term of performance it is
better to do like that, but I agree by doing:

if (string)
	return emulate_instruction(vcpu, kvm_run, 0, 0);
else
	return kvm_setup_pio(vcpu, kvm_run, in, size, port);

it is more more ... more simple.

If you prefer simplicity, I can do like that ?
(but I know you prefer simplicity...)

BTW, I think PATCH 1,2 and 3 should be applied anyway because they allow to
introduce the separation between instruction decoding and instruction emulation
requested by the TODO "Split the emulator into two functions: one to decode into
the emulation context, and the other to actually execute the instruction."

Laurent
-- 
------------- Laurent.Vivier-6ktuUTfB/bM@public.gmane.org  --------------
          "Software is hard" - Donald Knuth


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 315 bytes --]

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

[-- Attachment #3: Type: text/plain, Size: 186 bytes --]

_______________________________________________
kvm-devel mailing list
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/kvm-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/5] vmx.c uses x86_decode_prefix() instead of get_io_count().
       [not found]                         ` <46B1A51C.2040104-6ktuUTfB/bM@public.gmane.org>
@ 2007-08-02  9:41                           ` Avi Kivity
       [not found]                             ` <46B1A6B8.7020404-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
  0 siblings, 1 reply; 10+ messages in thread
From: Avi Kivity @ 2007-08-02  9:41 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: kvm-devel

Laurent Vivier wrote:
>>
>> How about just calliing emulate_instruction() from here (just for the
>> string case)?  That will eliminate all the setup code.
>>     
>
> But this setup is in emulate_instruction() so it will be executed anyway.
>
>   

I'm  not worried about run-time overhead, but about the amount of code.

>> x86_emulate_memop() will need to be extended to decode ins/outs, but
>> that's fairly easy.
>>     
>
> X86_decode_prefix() is a subset of instruction decoding part of
> x86_emulate_memop(), kvm_setup_pio() can be seen as a subset of instruction
> emulating part of x86_emulate_memop(). So I think in term of performance it is
> better to do like that, but I agree by doing:
>
> if (string)
> 	return emulate_instruction(vcpu, kvm_run, 0, 0);
> else
> 	return kvm_setup_pio(vcpu, kvm_run, in, size, port);
>
> it is more more ... more simple.
>
> If you prefer simplicity, I can do like that ?
> (but I know you prefer simplicity...)
>
>   

Yes.  Note that x86_emulate_memop() will eventually call kvm_setup_pio() 
to complete the emulation.

> BTW, I think PATCH 1,2 and 3 should be applied anyway because they allow to
> introduce the separation between instruction decoding and instruction emulation
> requested by the TODO "Split the emulator into two functions: one to decode into
> the emulation context, and the other to actually execute the instruction."
>   

I agree.  I'll look into it with more detail.


-- 
error compiling committee.c: too many arguments to function


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/5] vmx.c uses x86_decode_prefix() instead of get_io_count().
       [not found]                             ` <46B1A6B8.7020404-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
@ 2007-08-02 16:46                               ` Laurent Vivier
  0 siblings, 0 replies; 10+ messages in thread
From: Laurent Vivier @ 2007-08-02 16:46 UTC (permalink / raw)
  To: Avi Kivity; +Cc: kvm-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 1399 bytes --]

Avi Kivity wrote:
> Laurent Vivier wrote:
>>>
>>> How about just calliing emulate_instruction() from here (just for the
>>> string case)?  That will eliminate all the setup code.
>>>     
>>
>> But this setup is in emulate_instruction() so it will be executed anyway.
>>
>>   
> 
> I'm  not worried about run-time overhead, but about the amount of code.
> 
>>> x86_emulate_memop() will need to be extended to decode ins/outs, but
>>> that's fairly easy.
>>>     
>>
>> X86_decode_prefix() is a subset of instruction decoding part of
>> x86_emulate_memop(), kvm_setup_pio() can be seen as a subset of
>> instruction
>> emulating part of x86_emulate_memop(). So I think in term of
>> performance it is
>> better to do like that, but I agree by doing:
>>
>> if (string)
>>     return emulate_instruction(vcpu, kvm_run, 0, 0);
>> else
>>     return kvm_setup_pio(vcpu, kvm_run, in, size, port);
>>
>> it is more more ... more simple.
>>
>> If you prefer simplicity, I can do like that ?
>> (but I know you prefer simplicity...)
>>
>>   
> 
> Yes.  Note that x86_emulate_memop() will eventually call kvm_setup_pio()
> to complete the emulation.

Just to have some comments, have a look to my little dirty patch (see attachment)

Laurent
-- 
------------- Laurent.Vivier-6ktuUTfB/bM@public.gmane.org  --------------
          "Software is hard" - Donald Knuth

[-- Attachment #1.1.2: emulate_ins_outs --]
[-- Type: text/plain, Size: 10428 bytes --]

Index: kvm/drivers/kvm/kvm_main.c
===================================================================
--- kvm.orig/drivers/kvm/kvm_main.c	2007-08-02 18:32:19.000000000 +0200
+++ kvm/drivers/kvm/kvm_main.c	2007-08-02 18:32:22.000000000 +0200
@@ -1222,6 +1222,8 @@
 
 	vcpu->mmio_is_write = 0;
 	r = x86_emulate_memop(&emulate_ctxt, &emulate_ops);
+	if (vcpu->pio.count)
+		return EMULATE_DO_MMIO;
 
 	if ((r || vcpu->mmio_is_write) && run) {
 		run->exit_reason = KVM_EXIT_MMIO;
Index: kvm/drivers/kvm/svm.c
===================================================================
--- kvm.orig/drivers/kvm/svm.c	2007-08-02 18:32:19.000000000 +0200
+++ kvm/drivers/kvm/svm.c	2007-08-02 18:35:03.000000000 +0200
@@ -98,20 +98,6 @@
 	return svm_features & feat;
 }
 
-static unsigned get_addr_size(struct vcpu_svm *svm)
-{
-	struct vmcb_save_area *sa = &svm->vmcb->save;
-	u16 cs_attrib;
-
-	if (!(sa->cr0 & X86_CR0_PE) || (sa->rflags & X86_EFLAGS_VM))
-		return 2;
-
-	cs_attrib = sa->cs.attrib;
-
-	return (cs_attrib & SVM_SELECTOR_L_MASK) ? 8 :
-				(cs_attrib & SVM_SELECTOR_DB_MASK) ? 4 : 2;
-}
-
 static inline u8 pop_irq(struct kvm_vcpu *vcpu)
 {
 	int word_index = __ffs(vcpu->irq_summary);
@@ -995,147 +981,32 @@
 	return 0;
 }
 
-static int io_get_override(struct vcpu_svm *svm,
-			  struct vmcb_seg **seg,
-			  int *addr_override)
-{
-	u8 inst[MAX_INST_SIZE];
-	unsigned ins_length;
-	gva_t rip;
-	int i;
-
-	rip =  svm->vmcb->save.rip;
-	ins_length = svm->next_rip - rip;
-	rip += svm->vmcb->save.cs.base;
-
-	if (ins_length > MAX_INST_SIZE)
-		printk(KERN_DEBUG
-		       "%s: inst length err, cs base 0x%llx rip 0x%llx "
-		       "next rip 0x%llx ins_length %u\n",
-		       __FUNCTION__,
-		       svm->vmcb->save.cs.base,
-		       svm->vmcb->save.rip,
-		       svm->vmcb->control.exit_info_2,
-		       ins_length);
-
-	if (emulator_read_std(rip, inst, ins_length, &svm->vcpu)
-	    != X86EMUL_CONTINUE)
-		/* #PF */
-		return 0;
-
-	*addr_override = 0;
-	*seg = NULL;
-	for (i = 0; i < ins_length; i++)
-		switch (inst[i]) {
-		case 0xf0:
-		case 0xf2:
-		case 0xf3:
-		case 0x66:
-			continue;
-		case 0x67:
-			*addr_override = 1;
-			continue;
-		case 0x2e:
-			*seg = &svm->vmcb->save.cs;
-			continue;
-		case 0x36:
-			*seg = &svm->vmcb->save.ss;
-			continue;
-		case 0x3e:
-			*seg = &svm->vmcb->save.ds;
-			continue;
-		case 0x26:
-			*seg = &svm->vmcb->save.es;
-			continue;
-		case 0x64:
-			*seg = &svm->vmcb->save.fs;
-			continue;
-		case 0x65:
-			*seg = &svm->vmcb->save.gs;
-			continue;
-		default:
-			return 1;
-		}
-	printk(KERN_DEBUG "%s: unexpected\n", __FUNCTION__);
-	return 0;
-}
-
-static unsigned long io_address(struct vcpu_svm *svm, int ins, gva_t *address)
-{
-	unsigned long addr_mask;
-	unsigned long *reg;
-	struct vmcb_seg *seg;
-	int addr_override;
-	struct vmcb_save_area *save_area = &svm->vmcb->save;
-	u16 cs_attrib = save_area->cs.attrib;
-	unsigned addr_size = get_addr_size(svm);
-
-	if (!io_get_override(svm, &seg, &addr_override))
-		return 0;
-
-	if (addr_override)
-		addr_size = (addr_size == 2) ? 4: (addr_size >> 1);
-
-	if (ins) {
-		reg = &svm->vcpu.regs[VCPU_REGS_RDI];
-		seg = &svm->vmcb->save.es;
-	} else {
-		reg = &svm->vcpu.regs[VCPU_REGS_RSI];
-		seg = (seg) ? seg : &svm->vmcb->save.ds;
-	}
-
-	addr_mask = ~0ULL >> (64 - (addr_size * 8));
-
-	if ((cs_attrib & SVM_SELECTOR_L_MASK) &&
-	    !(svm->vmcb->save.rflags & X86_EFLAGS_VM)) {
-		*address = (*reg & addr_mask);
-		return addr_mask;
-	}
-
-	if (!(seg->attrib & SVM_SELECTOR_P_SHIFT)) {
-		svm_inject_gp(&svm->vcpu, 0);
-		return 0;
-	}
-
-	*address = (*reg & addr_mask) + seg->base;
-	return addr_mask;
-}
-
 static int io_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
 {
 	u32 io_info = svm->vmcb->control.exit_info_1; //address size bug?
 	int size, down, in, string, rep;
 	unsigned port;
-	unsigned long count;
-	gva_t address = 0;
 
 	++svm->vcpu.stat.io_exits;
 
 	svm->next_rip = svm->vmcb->control.exit_info_2;
 
+	string = (io_info & SVM_IOIO_STR_MASK) != 0;
+
+	if (string) {
+		if (emulate_instruction(&svm->vcpu, kvm_run, 0, 0) == EMULATE_DO_MMIO)
+			return 0;
+		return 1;
+	}
+
 	in = (io_info & SVM_IOIO_TYPE_MASK) != 0;
 	port = io_info >> 16;
 	size = (io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT;
-	string = (io_info & SVM_IOIO_STR_MASK) != 0;
 	rep = (io_info & SVM_IOIO_REP_MASK) != 0;
-	count = 1;
 	down = (svm->vmcb->save.rflags & X86_EFLAGS_DF) != 0;
 
-	if (string) {
-		unsigned addr_mask;
-
-		addr_mask = io_address(svm, in, &address);
-		if (!addr_mask) {
-			printk(KERN_DEBUG "%s: get io address failed\n",
-			       __FUNCTION__);
-			return 1;
-		}
-
-		if (rep)
-			count = svm->vcpu.regs[VCPU_REGS_RCX] & addr_mask;
-	}
-	return kvm_setup_pio(&svm->vcpu, kvm_run, in, size, count, string,
-			     down, address, rep, port);
+	return kvm_setup_pio(&svm->vcpu, kvm_run, in, size, 1, 0,
+			     down, 0, rep, port);
 }
 
 static int nop_on_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
Index: kvm/drivers/kvm/vmx.c
===================================================================
--- kvm.orig/drivers/kvm/vmx.c	2007-08-02 18:32:19.000000000 +0200
+++ kvm/drivers/kvm/vmx.c	2007-08-02 18:34:39.000000000 +0200
@@ -1761,82 +1761,30 @@
 	return 0;
 }
 
-static int get_io_count(struct kvm_vcpu *vcpu, unsigned long *count)
-{
-	u64 inst;
-	gva_t rip;
-	int countr_size;
-	int i;
-
-	if ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_VM)) {
-		countr_size = 2;
-	} else {
-		u32 cs_ar = vmcs_read32(GUEST_CS_AR_BYTES);
-
-		countr_size = (cs_ar & AR_L_MASK) ? 8:
-			      (cs_ar & AR_DB_MASK) ? 4: 2;
-	}
-
-	rip =  vmcs_readl(GUEST_RIP);
-	if (countr_size != 8)
-		rip += vmcs_readl(GUEST_CS_BASE);
-
-	if (emulator_read_std(rip, &inst, sizeof(inst), vcpu) !=
-							X86EMUL_CONTINUE)
-		return 0;
-
-	for (i = 0; i < sizeof(inst); i++) {
-		switch (((u8*)&inst)[i]) {
-		case 0xf0:
-		case 0xf2:
-		case 0xf3:
-		case 0x2e:
-		case 0x36:
-		case 0x3e:
-		case 0x26:
-		case 0x64:
-		case 0x65:
-		case 0x66:
-			break;
-		case 0x67:
-			countr_size = (countr_size == 2) ? 4: (countr_size >> 1);
-		default:
-			goto done;
-		}
-	}
-	return 0;
-done:
-	countr_size *= 8;
-	*count = vcpu->regs[VCPU_REGS_RCX] & (~0ULL >> (64 - countr_size));
-	//printk("cx: %lx\n", vcpu->regs[VCPU_REGS_RCX]);
-	return 1;
-}
-
 static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
 	u64 exit_qualification;
 	int size, down, in, string, rep;
 	unsigned port;
-	unsigned long count;
-	gva_t address;
 
 	++vcpu->stat.io_exits;
 	exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
-	in = (exit_qualification & 8) != 0;
-	size = (exit_qualification & 7) + 1;
 	string = (exit_qualification & 16) != 0;
+
+	if (string) {
+		if (emulate_instruction(vcpu, kvm_run, 0, 0) == EMULATE_DO_MMIO)
+			return 0;
+		return 1;
+	}
+
+	size = (exit_qualification & 7) + 1;
+	in = (exit_qualification & 8) != 0;
 	down = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0;
-	count = 1;
 	rep = (exit_qualification & 32) != 0;
 	port = exit_qualification >> 16;
-	address = 0;
-	if (string) {
-		if (rep && !get_io_count(vcpu, &count))
-			return 1;
-		address = vmcs_readl(GUEST_LINEAR_ADDRESS);
-	}
-	return kvm_setup_pio(vcpu, kvm_run, in, size, count, string, down,
-			     address, rep, port);
+
+	return kvm_setup_pio(vcpu, kvm_run, in, size, 1, 0, down,
+			     0, rep, port);
 }
 
 static void
Index: kvm/drivers/kvm/x86_emulate.c
===================================================================
--- kvm.orig/drivers/kvm/x86_emulate.c	2007-08-02 18:32:19.000000000 +0200
+++ kvm/drivers/kvm/x86_emulate.c	2007-08-02 18:34:06.000000000 +0200
@@ -103,9 +103,12 @@
 	/* 0x58 - 0x5F */
 	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
 	ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
-	/* 0x60 - 0x6F */
+	/* 0x60 - 0x6B */
 	0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ ,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	/* 0x6C - 0x6F */
+	ByteOp  | ImplicitOps, ImplicitOps,	/* insb, insw/insd */
+	ByteOp  | ImplicitOps, ImplicitOps,	/* outsb, outsw/outsd */
 	/* 0x70 - 0x7F */
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	/* 0x80 - 0x87 */
@@ -428,10 +431,11 @@
 })
 
 /* Access/update address held in a register, based on addressing mode. */
+#define address_mask(reg)						\
+	((ad_bytes == sizeof(unsigned long)) ? 				\
+		(reg) :	((reg) & ((1UL << (ad_bytes << 3)) - 1)))
 #define register_address(base, reg)                                     \
-	((base) + ((ad_bytes == sizeof(unsigned long)) ? (reg) :	\
-		   ((reg) & ((1UL << (ad_bytes << 3)) - 1))))
-
+	((base) + address_mask(reg))
 #define register_address_increment(reg, inc)                            \
 	do {								\
 		/* signed type ensures sign extension to long */        \
@@ -1139,6 +1143,39 @@
 		register_address_increment(_regs[VCPU_REGS_RDI],
 			     (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
 		break;
+	case 0x6c:		/* insb */
+	case 0x6d:		/* insw/insd */
+		 if (kvm_setup_pio(ctxt->vcpu, NULL,
+				1, 					/* in */
+				(d & ByteOp) ? 1 : op_bytes, 		/* size */
+				rep_prefix ?
+				address_mask(_regs[VCPU_REGS_RCX]) + 1: 1,	/* count */
+				1, 					/* strings */
+				(_eflags & EFLG_DF),			/* down */
+				register_address(ctxt->es_base,
+						 _regs[VCPU_REGS_RDI]),	/* address */
+				rep_prefix,
+				_regs[VCPU_REGS_RDX]			/* port */
+				) == 0)
+			return -1;
+		return 0;
+	case 0x6e:		/* outsb */
+	case 0x6f:		/* outsw/outsd */
+		if (kvm_setup_pio(ctxt->vcpu, NULL,
+				0, 					/* in */
+				(d & ByteOp) ? 1 : op_bytes, 		/* size */
+				rep_prefix ?
+				address_mask(_regs[VCPU_REGS_RCX]) + 1: 1,	/* count */
+				1, 					/* strings */
+				(_eflags & EFLG_DF),			/* down */
+				register_address(override_base ?
+						 *override_base : ctxt->ds_base,
+						 _regs[VCPU_REGS_RSI]),	/* address */
+				rep_prefix,
+				_regs[VCPU_REGS_RDX]			/* port */
+				) == 0)
+			return -1;
+		return 0;
 	case 0xa6 ... 0xa7:	/* cmps */
 		DPRINTF("Urk! I don't handle CMPS.\n");
 		goto cannot_emulate;

[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 315 bytes --]

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

[-- Attachment #3: Type: text/plain, Size: 186 bytes --]

_______________________________________________
kvm-devel mailing list
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/kvm-devel

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2007-08-02 16:46 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-08-01  9:05 PATCH 0/5] Consolidate the insb/outsb emulation into x86_emulate.c Laurent Vivier
     [not found] ` <46B04CCA.2010503-6ktuUTfB/bM@public.gmane.org>
2007-08-01  9:09   ` [PATCH 1/5] change ctxt.*_base to an array ctxt.base[X86EMUL_BASE_*] Laurent Vivier
     [not found]     ` <46B04DD6.7010702-6ktuUTfB/bM@public.gmane.org>
2007-08-01  9:13       ` [PATCH 2/5] group all prefix decoding results in a structure called x86_prefix Laurent Vivier
     [not found]         ` <46B04EB9.5010103-6ktuUTfB/bM@public.gmane.org>
2007-08-01  9:16           ` [PATCH 3/5] extract prefix decoding part from x86_emulate_memop() to x86_decode_prefix() Laurent Vivier
     [not found]             ` <46B04F56.60607-6ktuUTfB/bM@public.gmane.org>
2007-08-01  9:19               ` [PATCH 4/5] vmx.c uses x86_decode_prefix() instead of get_io_count() Laurent Vivier
     [not found]                 ` <46B0501C.6060409-6ktuUTfB/bM@public.gmane.org>
2007-08-01  9:22                   ` [PATCH 5/5] svm.c uses x86_decode_prefix() instead of io_address() and io_get_override() Laurent Vivier
2007-08-02  8:48                   ` [PATCH 4/5] vmx.c uses x86_decode_prefix() instead of get_io_count() Avi Kivity
     [not found]                     ` <46B19A7B.2030109-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-08-02  9:34                       ` Laurent Vivier
     [not found]                         ` <46B1A51C.2040104-6ktuUTfB/bM@public.gmane.org>
2007-08-02  9:41                           ` Avi Kivity
     [not found]                             ` <46B1A6B8.7020404-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-08-02 16:46                               ` Laurent Vivier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox