svn commit: r273666 - head/sys/amd64/vmm

Neel Natu neel at FreeBSD.org
Sun Oct 26 03:03:42 UTC 2014


Author: neel
Date: Sun Oct 26 03:03:41 2014
New Revision: 273666
URL: https://svnweb.freebsd.org/changeset/base/273666

Log:
  Don't pass the 'error' return from an I/O port handler directly to vm_run().
  
  Most I/O port handlers return -1 to signal an error. If this value is returned
  without modification to vm_run() then it leads to incorrect behavior because
  '-1' is interpreted as ERESTART at the system call level.
  
  Fix this by always returning EIO to signal an error from an I/O port handler.
  
  MFC after:	1 week

Modified:
  head/sys/amd64/vmm/vmm_ioport.c

Modified: head/sys/amd64/vmm/vmm_ioport.c
==============================================================================
--- head/sys/amd64/vmm/vmm_ioport.c	Sun Oct 26 02:53:23 2014	(r273665)
+++ head/sys/amd64/vmm/vmm_ioport.c	Sun Oct 26 03:03:41 2014	(r273666)
@@ -106,15 +106,14 @@ emulate_inout_port(struct vm *vm, int vc
 	uint32_t mask, val;
 	int error;
 
-	error = 0;
-	*retu = true;
-
-	if (vmexit->u.inout.port >= MAX_IOPORTS)
-		goto done;
-
-	handler = ioport_handler[vmexit->u.inout.port];
-	if (handler == NULL)
-		goto done;
+	/*
+	 * If there is no handler for the I/O port then punt to userspace.
+	 */
+	if (vmexit->u.inout.port >= MAX_IOPORTS ||
+	    (handler = ioport_handler[vmexit->u.inout.port]) == NULL) {
+		*retu = true;
+		return (0);
+	}
 
 	mask = vie_size2mask(vmexit->u.inout.bytes);
 
@@ -124,20 +123,27 @@ emulate_inout_port(struct vm *vm, int vc
 
 	error = (*handler)(vm, vcpuid, vmexit->u.inout.in,
 	    vmexit->u.inout.port, vmexit->u.inout.bytes, &val);
+	if (error) {
+		/*
+		 * The value returned by this function is also the return value
+		 * of vm_run(). This needs to be a positive number otherwise it
+		 * can be interpreted as a "pseudo-error" like ERESTART.
+		 *
+		 * Enforce this by mapping all errors to EIO.
+		 */
+		return (EIO);
+	}
 
-	if (!error) {
-		*retu = false;
-		if (vmexit->u.inout.in) {
-			vmexit->u.inout.eax &= ~mask;
-			vmexit->u.inout.eax |= val & mask;
-			error = vm_set_register(vm, vcpuid,
-			    VM_REG_GUEST_RAX, vmexit->u.inout.eax);
-			KASSERT(error == 0, ("emulate_ioport: error %d "
-			    "setting guest rax register", error));
-		}
+	if (vmexit->u.inout.in) {
+		vmexit->u.inout.eax &= ~mask;
+		vmexit->u.inout.eax |= val & mask;
+		error = vm_set_register(vm, vcpuid, VM_REG_GUEST_RAX,
+		    vmexit->u.inout.eax);
+		KASSERT(error == 0, ("emulate_ioport: error %d setting guest "
+		    "rax register", error));
 	}
-done:
-	return (error);
+	*retu = false;
+	return (0);
 }
 
 static int


More information about the svn-src-all mailing list