Print this page
8622 panic in PTE_set_all()
8623 IMMU_CONTIG_PADDR is broken for cookies with more than one page
8625 nvme causes bad free panic in IOMMU
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>

@@ -26,10 +26,11 @@
  * Copyright (c) 2009, Intel Corporation.
  * All rights reserved.
  */
 /*
  * Copyright 2012 Garrett D'Amore <garrett@damore.org>.  All rights reserved.
+ * Copyright 2017 Joyent, Inc.
  */
 
 /*
  * DVMA code
  * This file contains Intel IOMMU code that deals with DVMA

@@ -56,11 +57,12 @@
 #define IMMU_PCI_REV2CLASS(r)   ((r) >> 8)  /* classcode from revid */
 #define IMMU_PCI_CLASS2BASE(c)  ((c) >> 16) /* baseclass from classcode */
 #define IMMU_PCI_CLASS2SUB(c)   (((c) >> 8) & 0xff); /* classcode */
 
 #define IMMU_CONTIG_PADDR(d, p) \
-        ((d).dck_paddr && ((d).dck_paddr + IMMU_PAGESIZE) == (p))
+        ((d).dck_paddr && ((d).dck_paddr + (d).dck_npages * IMMU_PAGESIZE) \
+            == (p))
 
 typedef struct dvma_arg {
         immu_t *dva_immu;
         dev_info_t *dva_rdip;
         dev_info_t *dva_ddip;

@@ -2123,10 +2125,11 @@
                 if (nvpages <= dcookies[j].dck_npages)
                         break;
                 nvpages -= dcookies[j].dck_npages;
         }
 
+        VERIFY(j >= 0);
         nppages = nvpages;
         paddr = dcookies[j].dck_paddr +
             (dcookies[j].dck_npages - nppages) * IMMU_PAGESIZE;
 
         nvpages = *nvpages_ptr;

@@ -2664,14 +2667,12 @@
                         /* call into the VM to get the paddr */
                         paddr = pfn_to_pa(hat_getpfnum(vas->a_hat, vaddr));
                         vaddr += psize;
                 }
 
-                npages++;
-
                 if (ihp->ihp_npremapped > 0) {
-                        *ihp->ihp_preptes[npages - 1] =
+                        *ihp->ihp_preptes[npages] =
                             PDTE_PADDR(paddr) | rwmask;
                 } else if (IMMU_CONTIG_PADDR(dcookies[dmax], paddr)) {
                         dcookies[dmax].dck_npages++;
                 } else {
                         /* No, we need a new dcookie */

@@ -2689,16 +2690,19 @@
                                     uint_t, npages, uint_t, dmax+1);
 
                                 dvma += (npages << IMMU_PAGESHIFT);
                                 npages = 0;
                                 dmax = 0;
-                        } else
+                        } else {
                                 dmax++;
+                        }
                         dcookies[dmax].dck_paddr = paddr;
                         dcookies[dmax].dck_npages = 1;
                 }
                 size -= psize;
+                if (npages != 0)
+                        npages++;
         }
 
         /*
          * Finish up, mapping all, or all of the remaining,
          * physical memory ranges.