Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Nov 2012 04:07:19 +0000 (UTC)
From:      Neel Natu <neel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r243390 - projects/bhyve/sys/amd64/vmm/io
Message-ID:  <201211220407.qAM47J97089861@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: neel
Date: Thu Nov 22 04:07:18 2012
New Revision: 243390
URL: http://svnweb.freebsd.org/changeset/base/243390

Log:
  Fix a bug in the MSI-X resource allocation for PCI passthrough devices.
  
  In the case where the underlying host had disabled MSI-X via the
  "hw.pci.enable_msix" tunable, the ppt_setup_msix() function would fail
  and return an error without properly cleaning up. This in turn would
  cause a page fault on the next boot of the guest.
  
  Fix this by calling ppt_teardown_msix() in all the error return paths.
  
  Obtained from:	NetApp

Modified:
  projects/bhyve/sys/amd64/vmm/io/ppt.c

Modified: projects/bhyve/sys/amd64/vmm/io/ppt.c
==============================================================================
--- projects/bhyve/sys/amd64/vmm/io/ppt.c	Thu Nov 22 04:03:09 2012	(r243389)
+++ projects/bhyve/sys/amd64/vmm/io/ppt.c	Thu Nov 22 04:07:18 2012	(r243390)
@@ -247,7 +247,7 @@ ppt_teardown_msix_intr(struct pptdev *pp
 static void 
 ppt_teardown_msix(struct pptdev *ppt)
 {
-	int i, error;
+	int i;
 
 	if (ppt->msix.num_msgs == 0) 
 		return;
@@ -267,9 +267,7 @@ ppt_teardown_msix(struct pptdev *ppt)
 	free(ppt->msix.cookie, M_PPTMSIX);
 	free(ppt->msix.arg, M_PPTMSIX);
 
-	error = pci_release_msi(ppt->dev);
-	if (error) 
-		printf("ppt_teardown_msix: Failed to release MSI-X resources (error %i)\n", error);
+	pci_release_msi(ppt->dev);
 
 	ppt->msix.num_msgs = 0;
 }
@@ -519,7 +517,7 @@ ppt_setup_msix(struct vm *vm, int vcpu, 
 {
 	struct pptdev *ppt;
 	struct pci_devinfo *dinfo;
-	int numvec, vector_count, rid, error;
+	int numvec, alloced, rid, error;
 	size_t res_size, cookie_size, arg_size;
 
 	ppt = ppt_find(bus, slot, func);
@@ -538,48 +536,39 @@ ppt_setup_msix(struct vm *vm, int vcpu, 
 	 *	Allocate the IRQ resources
 	 *	Set up some variables in ppt->msix
 	 */
-	if (!ppt->msix.msix_table_res) {
-		ppt->msix.res = NULL;
-		ppt->msix.cookie = NULL;
-		ppt->msix.arg = NULL;
-
-		rid = dinfo->cfg.msix.msix_table_bar;
-		ppt->msix.msix_table_res = bus_alloc_resource_any(ppt->dev, SYS_RES_MEMORY,
-								  &rid, RF_ACTIVE);
-		if (ppt->msix.msix_table_res == NULL) 
-			return (ENOSPC);
-
-		ppt->msix.msix_table_rid = rid;
-
-		vector_count = numvec = pci_msix_count(ppt->dev);
-
-		error = pci_alloc_msix(ppt->dev, &numvec);
-		if (error) 
-			return (error);
-		else if (vector_count != numvec) {
-			pci_release_msi(ppt->dev);
-			return (ENOSPC);
-		} 
-
-		ppt->msix.num_msgs = numvec;
+	if (ppt->msix.num_msgs == 0) {
+		numvec = pci_msix_count(ppt->dev);
+		if (numvec <= 0)
+			return (EINVAL);
 
 		ppt->msix.startrid = 1;
+		ppt->msix.num_msgs = numvec;
 
 		res_size = numvec * sizeof(ppt->msix.res[0]);
 		cookie_size = numvec * sizeof(ppt->msix.cookie[0]);
 		arg_size = numvec * sizeof(ppt->msix.arg[0]);
 
-		ppt->msix.res = malloc(res_size, M_PPTMSIX, M_WAITOK);
-		ppt->msix.cookie = malloc(cookie_size, M_PPTMSIX, M_WAITOK);
-		ppt->msix.arg = malloc(arg_size, M_PPTMSIX, M_WAITOK);
-		if (ppt->msix.res == NULL || ppt->msix.cookie == NULL || 
-		    ppt->msix.arg == NULL) {
+		ppt->msix.res = malloc(res_size, M_PPTMSIX, M_WAITOK | M_ZERO);
+		ppt->msix.cookie = malloc(cookie_size, M_PPTMSIX,
+					  M_WAITOK | M_ZERO);
+		ppt->msix.arg = malloc(arg_size, M_PPTMSIX, M_WAITOK | M_ZERO);
+
+		rid = dinfo->cfg.msix.msix_table_bar;
+		ppt->msix.msix_table_res = bus_alloc_resource_any(ppt->dev,
+					       SYS_RES_MEMORY, &rid, RF_ACTIVE);
+
+		if (ppt->msix.msix_table_res == NULL) {
 			ppt_teardown_msix(ppt);
 			return (ENOSPC);
 		}
-		bzero(ppt->msix.res, res_size);
-		bzero(ppt->msix.cookie, cookie_size);
-		bzero(ppt->msix.arg, arg_size);
+		ppt->msix.msix_table_rid = rid;
+
+		alloced = numvec;
+		error = pci_alloc_msix(ppt->dev, &alloced);
+		if (error || alloced != numvec) {
+			ppt_teardown_msix(ppt);
+			return (error == 0 ? ENOSPC: error);
+		}
 	}
 
 	if ((vector_control & PCIM_MSIX_VCTRL_MASK) == 0) {



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