Skip to contentSkip to conversation

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

PATCH In review Laurent Vivier 2 participants 10 messages Aug 1, 2007 – Aug 2, 2007 8 messages not in the archive KVM

lore
Share & tools
lore
#0 lore raw

[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. ***

Signature · 2 lines
------------- Laurent.Vivier-6ktuUTfB/[email protected]  --------------
          "Software is hard" - Donald Knuth

-------------------------------------------------------------------------
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/

_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel

A message that is not in the archive (sent off-list or not yet received): 46B04CCA.2010503-6ktuUTfB/[email protected]

#2 lore raw

PATCH 1/5 change ctxt.*_base to an array ctxt.base[X86EMUL_BASE_*]

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

Signature · 2 lines
------------- Laurent.Vivier-6ktuUTfB/[email protected]  --------------
          "Software is hard" - Donald Knuth
drivers/kvm/kvm_main.c +16 -10
Index: kvm/drivers/kvm/kvm_main.c
===================================================================
@@ -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);
drivers/kvm/x86_emulate.c +29 -24

121 lines not on this page · raw message

drivers/kvm/x86_emulate.h +11 -7
Index: kvm/drivers/kvm/x86_emulate.h
===================================================================
@@ -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. */

-------------------------------------------------------------------------
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/

_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel

A message that is not in the archive (sent off-list or not yet received): 46B04DD6.7010702-6ktuUTfB/[email protected]

#4 lore raw

PATCH 2/5 group all prefix decoding results in a structure called 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.

Signature · 2 lines
------------- Laurent.Vivier-6ktuUTfB/[email protected]  --------------
          "Software is hard" - Donald Knuth
drivers/kvm/x86_emulate.h +15 -0
Index: kvm/drivers/kvm/x86_emulate.h
===================================================================
@@ -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
drivers/kvm/x86_emulate.c +102 -100

540 lines not on this page · raw message

-------------------------------------------------------------------------
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/

_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel

A message that is not in the archive (sent off-list or not yet received): 46B04EB9.5010103-6ktuUTfB/[email protected]

#6 lore raw

PATCH 3/5 extract prefix decoding part from x86_emulate_memop() to x86_decode_prefix()

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

Signature · 2 lines
------------- Laurent.Vivier-6ktuUTfB/[email protected]  --------------
          "Software is hard" - Donald Knuth
drivers/kvm/x86_emulate.c +73 -45
Index: kvm/drivers/kvm/x86_emulate.c
===================================================================
@@ -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) {
drivers/kvm/x86_emulate.h +7 -0
Index: kvm/drivers/kvm/x86_emulate.h
===================================================================
@@ -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.

-------------------------------------------------------------------------
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/

_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel

A message that is not in the archive (sent off-list or not yet received): 46B04F56.60607-6ktuUTfB/[email protected]

#8 lore raw

PATCH 4/5 vmx.c uses x86_decode_prefix() instead of get_io_count().

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

Signature · 2 lines
------------- Laurent.Vivier-6ktuUTfB/[email protected]  --------------
          "Software is hard" - Donald Knuth
drivers/kvm/vmx.c +25 -52
Index: kvm/drivers/kvm/vmx.c
===================================================================
@@ -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,

-------------------------------------------------------------------------
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/

_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel

A message that is not in the archive (sent off-list or not yet received): 46B0501C.6060409-6ktuUTfB/[email protected]

#10 lore raw

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

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. ***

Signature · 2 lines
------------- Laurent.Vivier-6ktuUTfB/[email protected]  --------------
          "Software is hard" - Donald Knuth
drivers/kvm/svm.c +83 -127
Index: kvm/drivers/kvm/svm.c
===================================================================
@@ -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

-------------------------------------------------------------------------
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/

_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel

#11 lore raw

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

In reply to a message not in the archive
Quoted 30 lines · Laurent Vivier

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

static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) {

drivers/kvm/vmx.c +19 -1
 	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;
+

drivers/kvm/vmx.c line 1811

Quoted 10 lines
drivers/kvm/vmx.c +6 -0
+		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.

Signature · 8 lines
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/

A message that is not in the archive (sent off-list or not yet received): 46B19A7B.2030109-atKUWr5tajBWk0Htik3J/[email protected]

#13 lore raw

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

Quoted 35 lines · Avi Kivity
Quoted 34 lines · Laurent Vivier

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;
drivers/kvm/vmx.c +23 -1
@@ -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)
Quoted 8 lines

drivers/kvm/vmx.c line 1811

Quoted 5 lines
drivers/kvm/vmx.c +2 -0
+            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.

Quoted 2 lines

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

Signature · 2 lines
------------- Laurent.Vivier-6ktuUTfB/[email protected]  --------------
          "Software is hard" - Donald Knuth

-------------------------------------------------------------------------
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/

_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel

A message that is not in the archive (sent off-list or not yet received): 46B1A51C.2040104-6ktuUTfB/[email protected]

#15 lore raw

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

Quoted 8 lines · Laurent Vivier
Quoted 4 lines

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.

Quoted 10 lines
Quoted 3 lines

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)

Quoted 10 lines
	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.

Quoted 5 lines

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.

Signature · 8 lines
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/

A message that is not in the archive (sent off-list or not yet received): 46B1A6B8.7020404-atKUWr5tajBWk0Htik3J/[email protected]

#17 lore raw

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

Quoted 30 lines · Avi Kivity
Quoted 8 lines · Laurent Vivier
Quoted 4 lines

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.

Quoted 18 lines
Quoted 3 lines

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.

Quoted 7 lines
Quoted 4 lines

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

Signature · 2 lines
------------- Laurent.Vivier-6ktuUTfB/[email protected]  --------------
          "Software is hard" - Donald Knuth
drivers/kvm/kvm_main.c +2 -0
Index: kvm/drivers/kvm/kvm_main.c
===================================================================
@@ -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;
drivers/kvm/svm.c +10 -139

177 lines not on this page · raw message

drivers/kvm/vmx.c +12 -64

94 lines not on this page · raw message

drivers/kvm/x86_emulate.c +42 -5

67 lines not on this page · raw message

-------------------------------------------------------------------------
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/

_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel