From owner-svn-src-all@freebsd.org Fri Jun 1 12:43:14 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 41C3CF7F35B; Fri, 1 Jun 2018 12:43:14 +0000 (UTC) (envelope-from leitao@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id EB66E79847; Fri, 1 Jun 2018 12:43:13 +0000 (UTC) (envelope-from leitao@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id CD1F828F28; Fri, 1 Jun 2018 12:43:13 +0000 (UTC) (envelope-from leitao@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w51ChDSB096929; Fri, 1 Jun 2018 12:43:13 GMT (envelope-from leitao@FreeBSD.org) Received: (from leitao@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w51ChDNl096928; Fri, 1 Jun 2018 12:43:13 GMT (envelope-from leitao@FreeBSD.org) Message-Id: <201806011243.w51ChDNl096928@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: leitao set sender to leitao@FreeBSD.org using -f From: Breno Leitao Date: Fri, 1 Jun 2018 12:43:13 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r334485 - head/sys/powerpc/ofw X-SVN-Group: head X-SVN-Commit-Author: leitao X-SVN-Commit-Paths: head/sys/powerpc/ofw X-SVN-Commit-Revision: 334485 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 01 Jun 2018 12:43:14 -0000 Author: leitao Date: Fri Jun 1 12:43:13 2018 New Revision: 334485 URL: https://svnweb.freebsd.org/changeset/base/334485 Log: powerpc64: Avoid overwriting initrd area Currently kexec loads an initrd file into the main memory but does not mark that region as reserved, thus the area is not protected. If any initrd/md file is loaded from kexec/petitboot, the region might become corarupted/overwritten since FreeBSD does not know the region is 'reserved'. This patch simply adds the initrd area as a reserved memory region. Approved by: jhibbits Differential Revision: https://reviews.freebsd.org/D15610 Modified: head/sys/powerpc/ofw/ofw_machdep.c Modified: head/sys/powerpc/ofw/ofw_machdep.c ============================================================================== --- head/sys/powerpc/ofw/ofw_machdep.c Fri Jun 1 12:09:07 2018 (r334484) +++ head/sys/powerpc/ofw/ofw_machdep.c Fri Jun 1 12:43:13 2018 (r334485) @@ -225,41 +225,19 @@ parse_ofw_memory(phandle_t node, const char *prop, str #ifdef FDT static int -excise_fdt_reserved(struct mem_region *avail, int asz) +excise_reserved_regions(struct mem_region *avail, int asz, + struct mem_region *exclude, int esz) { - struct { - uint64_t address; - uint64_t size; - } fdtmap[32]; - ssize_t fdtmapsize; - phandle_t chosen; int i, j, k; - chosen = OF_finddevice("/chosen"); - fdtmapsize = OF_getprop(chosen, "fdtmemreserv", fdtmap, sizeof(fdtmap)); - - for (j = 0; j < fdtmapsize/sizeof(fdtmap[0]); j++) { - fdtmap[j].address = be64toh(fdtmap[j].address) & ~PAGE_MASK; - fdtmap[j].size = round_page(be64toh(fdtmap[j].size)); - } - - KASSERT(j*sizeof(fdtmap[0]) < sizeof(fdtmap), - ("Exceeded number of FDT reservations")); - /* Add a virtual entry for the FDT itself */ - if (fdt != NULL) { - fdtmap[j].address = (vm_offset_t)fdt & ~PAGE_MASK; - fdtmap[j].size = round_page(fdt_totalsize(fdt)); - fdtmapsize += sizeof(fdtmap[0]); - } - for (i = 0; i < asz; i++) { - for (j = 0; j < fdtmapsize/sizeof(fdtmap[0]); j++) { + for (j = 0; j < esz; j++) { /* * Case 1: Exclusion region encloses complete * available entry. Drop it and move on. */ - if (fdtmap[j].address <= avail[i].mr_start && - fdtmap[j].address + fdtmap[j].size >= + if (exclude[j].mr_start <= avail[i].mr_start && + exclude[j].mr_start + exclude[j].mr_size >= avail[i].mr_start + avail[i].mr_size) { for (k = i+1; k < asz; k++) avail[k-1] = avail[k]; @@ -274,20 +252,20 @@ excise_fdt_reserved(struct mem_region *avail, int asz) * a new available entry with the region after * the excluded region, if any. */ - if (fdtmap[j].address >= avail[i].mr_start && - fdtmap[j].address < avail[i].mr_start + + if (exclude[j].mr_start >= avail[i].mr_start && + exclude[j].mr_start < avail[i].mr_start + avail[i].mr_size) { - if (fdtmap[j].address + fdtmap[j].size < + if (exclude[j].mr_start + exclude[j].mr_size < avail[i].mr_start + avail[i].mr_size) { avail[asz].mr_start = - fdtmap[j].address + fdtmap[j].size; + exclude[j].mr_start + exclude[j].mr_size; avail[asz].mr_size = avail[i].mr_start + avail[i].mr_size - avail[asz].mr_start; asz++; } - avail[i].mr_size = fdtmap[j].address - + avail[i].mr_size = exclude[j].mr_start - avail[i].mr_start; } @@ -297,13 +275,13 @@ excise_fdt_reserved(struct mem_region *avail, int asz) * The case of a contained exclusion zone has already * been caught in case 2. */ - if (fdtmap[j].address + fdtmap[j].size >= - avail[i].mr_start && fdtmap[j].address + - fdtmap[j].size < avail[i].mr_start + + if (exclude[j].mr_start + exclude[j].mr_size >= + avail[i].mr_start && exclude[j].mr_start + + exclude[j].mr_size < avail[i].mr_start + avail[i].mr_size) { avail[i].mr_size += avail[i].mr_start; avail[i].mr_start = - fdtmap[j].address + fdtmap[j].size; + exclude[j].mr_start + exclude[j].mr_size; avail[i].mr_size -= avail[i].mr_start; } } @@ -311,6 +289,62 @@ excise_fdt_reserved(struct mem_region *avail, int asz) return (asz); } + +static int +excise_initrd_region(struct mem_region *avail, int asz) +{ + phandle_t chosen; + uint64_t start, end; + ssize_t size; + struct mem_region initrdmap[1]; + + chosen = OF_finddevice("/chosen"); + size = OF_getprop(chosen, "linux,initrd-start", &start, sizeof(start)); + if (size <= 0) + return (asz); + + size = OF_getprop(chosen, "linux,initrd-end", &end, sizeof(end)); + if (size <= 0) + return (asz); + + initrdmap[0].mr_start = start; + initrdmap[0].mr_size = end - start; + + asz = excise_reserved_regions(avail, asz, initrdmap, 1); + + return (asz); +} + +static int +excise_fdt_reserved(struct mem_region *avail, int asz) +{ + struct mem_region fdtmap[32]; + ssize_t fdtmapsize; + phandle_t chosen; + int j, fdtentries; + + chosen = OF_finddevice("/chosen"); + fdtmapsize = OF_getprop(chosen, "fdtmemreserv", fdtmap, sizeof(fdtmap)); + + for (j = 0; j < fdtmapsize/sizeof(fdtmap[0]); j++) { + fdtmap[j].mr_start = be64toh(fdtmap[j].mr_start) & ~PAGE_MASK; + fdtmap[j].mr_size = round_page(be64toh(fdtmap[j].mr_size)); + } + + KASSERT(j*sizeof(fdtmap[0]) < sizeof(fdtmap), + ("Exceeded number of FDT reservations")); + /* Add a virtual entry for the FDT itself */ + if (fdt != NULL) { + fdtmap[j].mr_start = (vm_offset_t)fdt & ~PAGE_MASK; + fdtmap[j].mr_size = round_page(fdt_totalsize(fdt)); + fdtmapsize += sizeof(fdtmap[0]); + } + + fdtentries = fdtmapsize/sizeof(fdtmap[0]); + asz = excise_reserved_regions(avail, asz, fdtmap, fdtentries); + + return (asz); +} #endif /* @@ -364,6 +398,13 @@ ofw_mem_regions(struct mem_region *memp, int *memsz, phandle = OF_finddevice("/chosen"); if (OF_hasprop(phandle, "fdtmemreserv")) asz = excise_fdt_reserved(availp, asz); + + /* If the kernel is being loaded through kexec, initrd region is listed + * in /chosen but the region is not marked as reserved, so, we might exclude + * it here. + */ + if (OF_hasprop(phandle, "linux,initrd-start")) + asz = excise_initrd_region(availp, asz); #endif *memsz = msz;