Date: Thu, 19 Apr 2018 18:34:38 +0000 (UTC) From: Nathan Whitehorn <nwhitehorn@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r332788 - head/sys/powerpc/aim Message-ID: <201804191834.w3JIYcLx059559@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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@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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201804191834.w3JIYcLx059559>