Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 25 May 2014 00:57:24 +0000 (UTC)
From:      Neel Natu <neel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r266641 - in head: sys/amd64/include sys/amd64/vmm sys/amd64/vmm/intel usr.sbin/bhyve
Message-ID:  <201405250057.s4P0vOWv011967@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: neel
Date: Sun May 25 00:57:24 2014
New Revision: 266641
URL: http://svnweb.freebsd.org/changeset/base/266641

Log:
  Do the linear address calculation for the ins/outs emulation using a new
  API function 'vie_calculate_gla()'.
  
  While the current implementation is simplistic it forms the basis of doing
  segmentation checks if the guest is in 32-bit protected mode.

Modified:
  head/sys/amd64/include/vmm.h
  head/sys/amd64/include/vmm_instruction_emul.h
  head/sys/amd64/vmm/intel/vmx.c
  head/sys/amd64/vmm/vmm_instruction_emul.c
  head/sys/amd64/vmm/vmm_ioport.c
  head/usr.sbin/bhyve/inout.c

Modified: head/sys/amd64/include/vmm.h
==============================================================================
--- head/sys/amd64/include/vmm.h	Sun May 25 00:57:07 2014	(r266640)
+++ head/sys/amd64/include/vmm.h	Sun May 25 00:57:24 2014	(r266641)
@@ -426,7 +426,6 @@ struct vm_inout_str {
 	int		addrsize;
 	enum vm_reg_name seg_name;
 	struct seg_desc seg_desc;
-	uint64_t	gla;		/* may be set to VIE_INVALID_GLA */
 };
 
 struct vm_exit {

Modified: head/sys/amd64/include/vmm_instruction_emul.h
==============================================================================
--- head/sys/amd64/include/vmm_instruction_emul.h	Sun May 25 00:57:07 2014	(r266640)
+++ head/sys/amd64/include/vmm_instruction_emul.h	Sun May 25 00:57:24 2014	(r266641)
@@ -67,6 +67,9 @@ int vie_canonical_check(enum vm_cpu_mode
 
 uint64_t vie_size2mask(int size);
 
+int vie_calculate_gla(enum vm_cpu_mode cpu_mode, int addrsize,
+    enum vm_reg_name seg, struct seg_desc *desc, uint64_t off, uint64_t *gla);
+
 #ifdef _KERNEL
 /*
  * APIs to fetch and decode the instruction from nested page fault handler.
@@ -89,9 +92,6 @@ int vmm_gla2gpa(struct vm *vm, int vcpui
 
 void vie_init(struct vie *vie);
 
-uint64_t vie_segbase(enum vm_reg_name segment, enum vm_cpu_mode cpu_mode,
-    const struct seg_desc *desc);
-
 /*
  * Decode the instruction fetched into 'vie' so it can be emulated.
  *

Modified: head/sys/amd64/vmm/intel/vmx.c
==============================================================================
--- head/sys/amd64/vmm/intel/vmx.c	Sun May 25 00:57:07 2014	(r266640)
+++ head/sys/amd64/vmm/intel/vmx.c	Sun May 25 00:57:24 2014	(r266641)
@@ -2012,7 +2012,6 @@ vmx_exit_process(struct vmx *vmx, int vc
 			vis->count = inout_str_count(vmx, vcpu, vis->inout.rep);
 			vis->addrsize = inout_str_addrsize(inst_info);
 			inout_str_seginfo(vmx, vcpu, inst_info, in, vis);
-			vis->gla = vmcs_gla();
 		}
 		break;
 	case EXIT_REASON_CPUID:

Modified: head/sys/amd64/vmm/vmm_instruction_emul.c
==============================================================================
--- head/sys/amd64/vmm/vmm_instruction_emul.c	Sun May 25 00:57:07 2014	(r266640)
+++ head/sys/amd64/vmm/vmm_instruction_emul.c	Sun May 25 00:57:24 2014	(r266641)
@@ -607,6 +607,38 @@ vie_size2mask(int size)
 	return (size2mask[size]);
 }
 
+int
+vie_calculate_gla(enum vm_cpu_mode cpu_mode, int addrsize, enum vm_reg_name seg,
+    struct seg_desc *desc, uint64_t offset, uint64_t *gla)
+{
+	uint64_t segbase;
+	int glasize;
+
+	KASSERT(seg >= VM_REG_GUEST_ES && seg <= VM_REG_GUEST_GS,
+	    ("%s: invalid segment %d", __func__, seg));
+
+	glasize = (cpu_mode == CPU_MODE_64BIT) ? 8 : 4;
+
+	/*
+	 * In 64-bit mode all segments except %fs and %gs have a segment
+	 * base address of 0.
+	 */
+	if (cpu_mode == CPU_MODE_64BIT && seg != VM_REG_GUEST_FS &&
+	    seg != VM_REG_GUEST_GS) {
+		segbase = 0;
+	} else {
+		segbase = desc->base;
+	}
+
+	/*
+	 * Truncate 'offset' to the effective address size before adding
+	 * it to the segment base.
+	 */
+	offset &= vie_size2mask(addrsize);
+	*gla = (segbase + offset) & vie_size2mask(glasize);
+	return (0);
+}
+
 #ifdef _KERNEL
 void
 vie_init(struct vie *vie)
@@ -1271,42 +1303,4 @@ vmm_decode_instruction(struct vm *vm, in
 
 	return (0);
 }
-
-uint64_t
-vie_segbase(enum vm_reg_name seg, enum vm_cpu_mode cpu_mode,
-    const struct seg_desc *desc)
-{
-	int basesize;
-
-	basesize = 4;	/* default segment width in bytes */
-
-	switch (seg) {
-	case VM_REG_GUEST_ES:
-	case VM_REG_GUEST_CS:
-	case VM_REG_GUEST_SS:
-	case VM_REG_GUEST_DS:
-		if (cpu_mode == CPU_MODE_64BIT) {
-			/*
-			 * Segments having an implicit base address of 0
-			 * in 64-bit mode.
-			 */
-			return (0);
-		}
-		break;
-	case VM_REG_GUEST_FS:
-	case VM_REG_GUEST_GS:
-		if (cpu_mode == CPU_MODE_64BIT) {
-			/*
-			 * In 64-bit mode the FS and GS base address is 8 bytes
-			 * wide.
-			 */
-			basesize = 8;
-		}
-		break;
-	default:
-		panic("%s: invalid segment register %d", __func__, seg);
-	}
-
-	return (desc->base & size2mask[basesize]);
-}
 #endif	/* _KERNEL */

Modified: head/sys/amd64/vmm/vmm_ioport.c
==============================================================================
--- head/sys/amd64/vmm/vmm_ioport.c	Sun May 25 00:57:07 2014	(r266640)
+++ head/sys/amd64/vmm/vmm_ioport.c	Sun May 25 00:57:24 2014	(r266641)
@@ -144,7 +144,6 @@ static int
 emulate_inout_str(struct vm *vm, int vcpuid, struct vm_exit *vmexit, bool *retu)
 {
 	struct vm_inout_str *vis;
-	uint64_t gla, index, segbase;
 	int in;
 
 	vis = &vmexit->u.inout_str;
@@ -182,21 +181,6 @@ emulate_inout_str(struct vm *vm, int vcp
 		return (EINVAL);
 	}
 
-	segbase = vie_segbase(vis->seg_name, vis->paging.cpu_mode,
-	    &vis->seg_desc);
-	index = vis->index & vie_size2mask(vis->addrsize);
-	gla = segbase + index;
-
-	/*
-	 * Verify that the computed linear address matches with the one
-	 * provided by hardware.
-	 */
-	if (vis->gla != VIE_INVALID_GLA) {
-		KASSERT(gla == vis->gla, ("%s: gla mismatch "
-		    "%#lx/%#lx", __func__, gla, vis->gla));
-	}
-	vis->gla = gla;
-
 	*retu = true;
 	return (0);	/* Return to userspace to finish emulation */
 }

Modified: head/usr.sbin/bhyve/inout.c
==============================================================================
--- head/usr.sbin/bhyve/inout.c	Sun May 25 00:57:07 2014	(r266640)
+++ head/usr.sbin/bhyve/inout.c	Sun May 25 00:57:24 2014	(r266641)
@@ -147,15 +147,25 @@ emulate_inout(struct vmctx *ctx, int vcp
 		/* Count register */
 		count = vis->count & vie_size2mask(addrsize);
 
-		if (vie_alignment_check(vis->paging.cpl, bytes, vis->cr0,
-		    vis->rflags, vis->gla)) {
-			error = vm_inject_exception2(ctx, vcpu, IDT_AC, 0);
-			assert(error == 0);
-			return (INOUT_RESTART);
-		}
-
-		gla = vis->gla;
 		while (count) {
+			if (vie_calculate_gla(vis->paging.cpu_mode,
+			    vis->addrsize, vis->seg_name, &vis->seg_desc,
+			    index, &gla)) {
+				error = vm_inject_exception2(ctx, vcpu,
+				    IDT_GP, 0);
+				assert(error == 0);
+				return (INOUT_RESTART);
+			}
+
+			if (vie_alignment_check(vis->paging.cpl, bytes,
+			    vis->cr0, vis->rflags, gla)) {
+				error = vm_inject_exception2(ctx, vcpu,
+				    IDT_AC, 0);
+				assert(error == 0);
+				return (INOUT_RESTART);
+			}
+
+
 			val = 0;
 			if (!in) {
 				error = vm_copyin(ctx, vcpu, &vis->paging,
@@ -190,7 +200,6 @@ emulate_inout(struct vmctx *ctx, int vcp
 				index += bytes;
 
 			count--;
-			gla += bytes;
 		}
 
 		/* Update index register */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405250057.s4P0vOWv011967>