Hi,

Pmemrange being a difficult algorithm and reports of dma controllers
being unhappy with what it serves up, plus some prodding from theo,
caused me to write this little validation step.

Very low overhead, but guaranteed to catch bugs when they happen,
instead of when finally a dma controller does its own validation.

Ok?
-- 
Ariane


Index: uvm_pmemrange.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_pmemrange.c,v
retrieving revision 1.22
diff -u -d -p -r1.22 uvm_pmemrange.c
--- uvm_pmemrange.c     6 Apr 2011 12:31:10 -0000       1.22
+++ uvm_pmemrange.c     18 May 2011 16:42:36 -0000
@@ -746,6 +746,9 @@ uvm_pmr_getpages(psize_t count, paddr_t 
        int     memtype;                /* Requested memtype. */
        int     memtype_init;           /* Best memtype. */
        int     desperate;              /* True if allocation failed. */
+#ifdef DIAGNOSTIC
+       struct  vm_page *diag_prev;     /* Used during validation. */
+#endif /* DIAGNOSTIC */
 
        /*
         * Validate arguments.
@@ -1048,6 +1051,11 @@ out:
        uvm_unlock_fpageq();
 
        /* Update statistics and zero pages if UVM_PLA_ZERO. */
+#ifdef DIAGNOSTIC
+       fnsegs = 0;
+       fcount = 0;
+       diag_prev = NULL;
+#endif /* DIAGNOSTIC */
        TAILQ_FOREACH(found, result, pageq) {
                atomic_clearbits_int(&found->pg_flags,
                    PG_PMAP0|PG_PMAP1|PG_PMAP2|PG_PMAP3);
@@ -1074,7 +1082,36 @@ out:
                 */
                KDASSERT(start == 0 || atop(VM_PAGE_TO_PHYS(found)) >= start);
                KDASSERT(end == 0 || atop(VM_PAGE_TO_PHYS(found)) < end);
+
+#ifdef DIAGNOSTIC
+               /*
+                * Update fcount (# found pages) and
+                * fnsegs (# found segments) counters.
+                */
+               if (diag_prev == NULL ||
+                   /* new segment if it contains a hole */
+                   atop(VM_PAGE_TO_PHYS(diag_prev)) + 1 !=
+                   atop(VM_PAGE_TO_PHYS(found)) ||
+                   /* new segment if it crosses boundary */
+                   (atop(VM_PAGE_TO_PHYS(diag_prev)) & ~(boundary - 1)) !=
+                   (atop(VM_PAGE_TO_PHYS(found)) & ~(boundary - 1)))
+                       fnsegs++;
+               fcount++;
+
+               diag_prev = found;
+#endif /* DIAGNOSTIC */
        }
+
+#ifdef DIAGNOSTIC
+       /*
+        * Panic on algorithm failure.
+        */
+       if (fcount > count || fnsegs > maxseg)
+               panic("pmemrange allocation error: "
+                   "allocated %ld pages in %d segments, "
+                   "but request was %ld pages in %d segments",
+                   fcount, fnsegs, count, maxseg);
+#endif /* DIAGNOSTIC */
 
        return 0;
 }

Reply via email to