Author: nwhitehorn
Date: Thu Apr 19 18:34:38 2018
New Revision: 332788
URL: https://svnweb.freebsd.org/changeset/base/332788

Log:
  Fix detection of memory overlap with the kernel in the case where a memory
  region marked "available" by firmware is contained entirely in the kernel.
  
  This had a tendency to happen with FDTs passed by loader, though could for
  other reasons as well, and would result in the kernel slowly cannibalizing
  itself for other purposes, eventually resulting in a crash.
  
  A similar fix is needed for mmu_oea.c and should probably just be rolled
  at that point into some generic code in platform.c for taking a mem_region
  list and removing chunks.
  
  PR:           226974
  Submitted by: [email protected]
  Reviewed by:  jhibbits
  Differential Revision:        D15121

Modified:
  head/sys/powerpc/aim/mmu_oea64.c

Modified: head/sys/powerpc/aim/mmu_oea64.c
==============================================================================
--- head/sys/powerpc/aim/mmu_oea64.c    Thu Apr 19 18:10:44 2018        
(r332787)
+++ head/sys/powerpc/aim/mmu_oea64.c    Thu Apr 19 18:34:38 2018        
(r332788)
@@ -695,12 +695,27 @@ moea64_setup_direct_map(mmu_t mmup, vm_offset_t kernel
                unmapped_buf_allowed = hw_direct_map;
 }
 
+/* Quick sort callout for comparing physical addresses. */
+static int
+pa_cmp(const void *a, const void *b)
+{
+       const vm_paddr_t *pa = a, *pb = b;
+
+       if (*pa < *pb)
+               return (-1);
+       else if (*pa > *pb)
+               return (1);
+       else
+               return (0);
+}
+
 void
 moea64_early_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t 
kernelend)
 {
        int             i, j;
        vm_size_t       physsz, hwphyssz;
        vm_paddr_t      kernelphysstart, kernelphysend;
+       int             rm_pavail;
 
 #ifndef __powerpc64__
        /* We don't have a direct map since there is no BAT */
@@ -763,10 +778,18 @@ moea64_early_bootstrap(mmu_t mmup, vm_offset_t kernels
        }
 
        /* Check for overlap with the kernel and exception vectors */
+       rm_pavail = 0;
        for (j = 0; j < 2*phys_avail_count; j+=2) {
                if (phys_avail[j] < EXC_LAST)
                        phys_avail[j] += EXC_LAST;
 
+               if (phys_avail[j] >= kernelphysstart &&
+                   phys_avail[j+1] <= kernelphysend) {
+                       phys_avail[j] = phys_avail[j+1] = ~0;
+                       rm_pavail++;
+                       continue;
+               }
+
                if (kernelphysstart >= phys_avail[j] &&
                    kernelphysstart < phys_avail[j+1]) {
                        if (kernelphysend < phys_avail[j+1]) {
@@ -792,6 +815,16 @@ moea64_early_bootstrap(mmu_t mmup, vm_offset_t kernels
                        phys_avail[j] = (kernelphysend & ~PAGE_MASK) +
                            PAGE_SIZE;
                }
+       }
+
+       /* Remove physical available regions marked for removal (~0) */
+       if (rm_pavail) {
+               qsort(phys_avail, 2*phys_avail_count, sizeof(phys_avail[0]),
+                       pa_cmp);
+               phys_avail_count -= rm_pavail;
+               for (i = 2*phys_avail_count;
+                    i < 2*(phys_avail_count + rm_pavail); i+=2)
+                       phys_avail[i] = phys_avail[i+1] = 0;
        }
 
        physmem = btoc(physsz);
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to