svn commit: r332788 - head/sys/powerpc/aim

Nathan Whitehorn nwhitehorn at FreeBSD.org
Thu Apr 19 18:34:39 UTC 2018


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:	leandro.lupori at gmail.com
  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);


More information about the svn-src-head mailing list