svn commit: r284688 - head/lib/libvmmapi

Neel Natu neel at FreeBSD.org
Mon Jun 22 01:11:25 UTC 2015


Author: neel
Date: Mon Jun 22 00:30:34 2015
New Revision: 284688
URL: https://svnweb.freebsd.org/changeset/base/284688

Log:
  Fix a regression in "movs" emulation after r284539. The regression was caused
  due to a change in behavior of the 'vm_map_gpa()'.
  
  Prior to r284539 if 'vm_map_gpa()' was called to map an address range in the
  guest MMIO region then it would return NULL. This was used by the "movs"
  emulation to detect if the 'src' or 'dst' operand was in MMIO space.
  
  Post r284539 'vm_map_gpa()' started returning a non-NULL pointer even when
  mapping the guest MMIO region.
  
  Fix this by returning non-NULL only if [gaddr, gaddr+len) is entirely
  within the 'lowmem' or 'highmem' regions and NULL otherwise.
  
  Pointy hat to:	neel
  Reviewed by:	grehan
  Reported by:	tychon, Ben Perrault (ben.perrault at gmail.com)
  MFC after:	1 week

Modified:
  head/lib/libvmmapi/vmmapi.c

Modified: head/lib/libvmmapi/vmmapi.c
==============================================================================
--- head/lib/libvmmapi/vmmapi.c	Mon Jun 22 00:05:22 2015	(r284687)
+++ head/lib/libvmmapi/vmmapi.c	Mon Jun 22 00:30:34 2015	(r284688)
@@ -415,19 +415,28 @@ vm_setup_memory(struct vmctx *ctx, size_
 	return (0);
 }
 
+/*
+ * Returns a non-NULL pointer if [gaddr, gaddr+len) is entirely contained in
+ * the lowmem or highmem regions.
+ *
+ * In particular return NULL if [gaddr, gaddr+len) falls in guest MMIO region.
+ * The instruction emulation code depends on this behavior.
+ */
 void *
 vm_map_gpa(struct vmctx *ctx, vm_paddr_t gaddr, size_t len)
 {
-	vm_paddr_t start, end, mapend;
 
-	start = gaddr;
-	end = gaddr + len;
-	mapend = ctx->highmem ? 4*GB + ctx->highmem : ctx->lowmem;
+	if (ctx->lowmem > 0) {
+		if (gaddr < ctx->lowmem && gaddr + len <= ctx->lowmem)
+			return (ctx->baseaddr + gaddr);
+	}
 
-	if (start <= end && end <= mapend)
-		return (ctx->baseaddr + start);
-	else
-		return (NULL);
+	if (ctx->highmem > 0) {
+		if (gaddr >= 4*GB && gaddr + len <= 4*GB + ctx->highmem)
+			return (ctx->baseaddr + gaddr);
+	}
+
+	return (NULL);
 }
 
 size_t


More information about the svn-src-all mailing list