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