Author: neel
Date: Fri Feb  1 03:49:09 2013
New Revision: 246191
URL: http://svnweb.freebsd.org/changeset/base/246191

Log:
  Fix a broken assumption in the passthru implementation that the MSI-X table
  can only be located at the beginning or the end of the BAR.
  
  If the MSI-table is located in the middle of a BAR then we will split the
  BAR into two and create two mappings - one before the table and one after
  the table - leaving a hole in place of the table so accesses to it can be
  trapped and emulated.
  
  Obtained from:        NetApp

Modified:
  head/sys/amd64/vmm/io/ppt.c
  head/usr.sbin/bhyve/pci_passthru.c

Modified: head/sys/amd64/vmm/io/ppt.c
==============================================================================
--- head/sys/amd64/vmm/io/ppt.c Fri Feb  1 02:41:47 2013        (r246190)
+++ head/sys/amd64/vmm/io/ppt.c Fri Feb  1 03:49:09 2013        (r246191)
@@ -56,9 +56,18 @@ __FBSDID("$FreeBSD$");
 /* XXX locking */
 
 #define        MAX_PPTDEVS     (sizeof(pptdevs) / sizeof(pptdevs[0]))
-#define        MAX_MMIOSEGS    (PCIR_MAX_BAR_0 + 1)
 #define        MAX_MSIMSGS     32
 
+/*
+ * If the MSI-X table is located in the middle of a BAR then that MMIO
+ * region gets split into two segments - one segment above the MSI-X table
+ * and the other segment below the MSI-X table - with a hole in place of
+ * the MSI-X table so accesses to it can be trapped and emulated.
+ *
+ * So, allocate a MMIO segment for each BAR register + 1 additional segment.
+ */
+#define        MAX_MMIOSEGS    ((PCIR_MAX_BAR_0 + 1) + 1)
+
 MALLOC_DEFINE(M_PPTMSIX, "pptmsix", "Passthru MSI-X resources");
 
 struct pptintr_arg {                           /* pptintr(pptintr_arg) */

Modified: head/usr.sbin/bhyve/pci_passthru.c
==============================================================================
--- head/usr.sbin/bhyve/pci_passthru.c  Fri Feb  1 02:41:47 2013        
(r246190)
+++ head/usr.sbin/bhyve/pci_passthru.c  Fri Feb  1 03:49:09 2013        
(r246191)
@@ -355,14 +355,18 @@ msix_table_write(struct vmctx *ctx, int 
 static int
 init_msix_table(struct vmctx *ctx, struct passthru_softc *sc, uint64_t base)
 {
-       int idx;
-       size_t table_size;
+       int b, s, f;
+       int error, idx;
+       size_t len, remaining, table_size;
        vm_paddr_t start;
-       size_t len;
        struct pci_devinst *pi = sc->psc_pi;
 
        assert(pci_msix_table_bar(pi) >= 0 && pci_msix_pba_bar(pi) >= 0);
 
+       b = sc->psc_sel.pc_bus;
+       s = sc->psc_sel.pc_dev;
+       f = sc->psc_sel.pc_func;
+
        /* 
         * If the MSI-X table BAR maps memory intended for
         * other uses, it is at least assured that the table 
@@ -372,34 +376,44 @@ init_msix_table(struct vmctx *ctx, struc
        if (pi->pi_msix.pba_bar == pi->pi_msix.table_bar && 
            ((pi->pi_msix.pba_offset - pi->pi_msix.table_offset) < 4096)) {
                /* Need to also emulate the PBA, not supported yet */
-               printf("Unsupported MSI-X configuration: %d/%d/%d\n",
-                      sc->psc_sel.pc_bus, sc->psc_sel.pc_dev,
-                      sc->psc_sel.pc_func);
+               printf("Unsupported MSI-X configuration: %d/%d/%d\n", b, s, f);
                return (-1);
        }
 
-       /* 
-        * May need to split the BAR into 3 regions:
-        * Before the MSI-X table, the MSI-X table, and after it
-        * XXX for now, assume that the table is not in the middle
-        */
+       /* Compute the MSI-X table size */
        table_size = pi->pi_msix.table_count * MSIX_TABLE_ENTRY_SIZE;
+       table_size = roundup2(table_size, 4096);
+
        idx = pi->pi_msix.table_bar;
+       start = pi->pi_bar[idx].addr;
+       remaining = pi->pi_bar[idx].size;
 
-       /* Round up to page size */
-       table_size = roundup2(table_size, 4096);
-       if (pi->pi_msix.table_offset == 0) {            
-               /* Map everything after the MSI-X table */
-               start = pi->pi_bar[idx].addr + table_size;
-               len = pi->pi_bar[idx].size - table_size;
-       } else {
-                /* Map everything before the MSI-X table */
-               start = pi->pi_bar[idx].addr;
+       /* Map everything before the MSI-X table */
+       if (pi->pi_msix.table_offset > 0) {
                len = pi->pi_msix.table_offset;
+               error = vm_map_pptdev_mmio(ctx, b, s, f, start, len, base);
+               if (error)
+                       return (error);
+
+               base += len;
+               start += len;
+               remaining -= len;
+       }
+
+       /* Skip the MSI-X table */
+       base += table_size;
+       start += table_size;
+       remaining -= table_size;
+
+       /* Map everything beyond the end of the MSI-X table */
+       if (remaining > 0) {
+               len = remaining;
+               error = vm_map_pptdev_mmio(ctx, b, s, f, start, len, base);
+               if (error)
+                       return (error);
        }
-       return (vm_map_pptdev_mmio(ctx, sc->psc_sel.pc_bus, 
-                                  sc->psc_sel.pc_dev, sc->psc_sel.pc_func, 
-                                  start, len, base + table_size));
+
+       return (0);
 }
 
 static int
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to