Index: sys/amd64/amd64/machdep.c =================================================================== --- sys/amd64/amd64/machdep.c +++ sys/amd64/amd64/machdep.c @@ -124,6 +124,7 @@ #include #include #include +#include #include #include #include @@ -210,21 +214,6 @@ long Maxmem = 0; long realmem = 0; -/* - * The number of PHYSMAP entries must be one less than the number of - * PHYSSEG entries because the PHYSMAP entry that spans the largest - * physical address that is accessible by ISA DMA is split into two - * PHYSSEG entries. - */ -#define PHYSMAP_SIZE (2 * (VM_PHYSSEG_MAX - 1)) - -vm_paddr_t phys_avail[PHYSMAP_SIZE + 2]; -vm_paddr_t dump_avail[PHYSMAP_SIZE + 2]; - -/* must be 2 less so 0 0 can signal end of chunks */ -#define PHYS_AVAIL_ARRAY_END (nitems(phys_avail) - 2) -#define DUMP_AVAIL_ARRAY_END (nitems(dump_avail) - 2) - struct kva_md_info kmi; static struct trapframe proc0_tf; Index: sys/amd64/include/physmem.h =================================================================== --- /dev/null +++ sys/amd64/include/physmem.h @@ -0,0 +1,51 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2018 Johannes Lundberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PHYSMEM_H_ +#define _MACHINE_PHYSMEM_H_ + +#include +#include + +/* + * The number of PHYSMAP entries must be one less than the number of + * PHYSSEG entries because the PHYSMAP entry that spans the largest + * physical address that is accessible by ISA DMA is split into two + * PHYSSEG entries. + */ +#define PHYSMAP_SIZE (2 * (VM_PHYSSEG_MAX - 1)) + +/* must be 2 less so 0 0 can signal end of chunks */ +#define PHYS_AVAIL_ARRAY_END (nitems(phys_avail) - 2) +#define DUMP_AVAIL_ARRAY_END (nitems(dump_avail) - 2) + +/* kern_physmem.c */ +extern vm_paddr_t phys_avail[PHYSMAP_SIZE + 2]; +extern vm_paddr_t dump_avail[PHYSMAP_SIZE + 2]; +void phys_avail_reserve(vm_paddr_t start, vm_paddr_t end); + +#endif /* _MACHINE_PHYSMEM_H_ */ Index: sys/amd64/include/pmap.h =================================================================== --- sys/amd64/include/pmap.h +++ sys/amd64/include/pmap.h @@ -239,6 +239,8 @@ #include +#include + typedef u_int64_t pd_entry_t; typedef u_int64_t pt_entry_t; typedef u_int64_t pdp_entry_t; @@ -393,8 +395,6 @@ extern caddr_t CADDR1; extern pt_entry_t *CMAP1; -extern vm_paddr_t phys_avail[]; -extern vm_paddr_t dump_avail[]; extern vm_offset_t virtual_avail; extern vm_offset_t virtual_end; extern vm_paddr_t dmaplimit; Index: sys/conf/files.amd64 =================================================================== --- sys/conf/files.amd64 +++ sys/conf/files.amd64 @@ -618,6 +618,7 @@ isa/syscons_isa.c optional sc isa/vga_isa.c optional vga kern/kern_clocksource.c standard +kern/kern_physmem.c standard kern/imgact_aout.c optional compat_aout kern/imgact_gzip.c optional gzip kern/link_elf_obj.c standard Index: sys/conf/files.i386 =================================================================== --- sys/conf/files.i386 +++ sys/conf/files.i386 @@ -542,6 +542,7 @@ isa/syscons_isa.c optional sc isa/vga_isa.c optional vga kern/kern_clocksource.c standard +kern/kern_physmem.c standard kern/imgact_aout.c optional compat_aout kern/imgact_gzip.c optional gzip kern/subr_sfbuf.c standard Index: sys/i386/i386/machdep.c =================================================================== --- sys/i386/i386/machdep.c +++ sys/i386/i386/machdep.c @@ -127,6 +127,7 @@ #include #include #include +#include #include #include #include @@ -192,21 +196,6 @@ FEATURE(pae, "Physical Address Extensions"); #endif -/* - * The number of PHYSMAP entries must be one less than the number of - * PHYSSEG entries because the PHYSMAP entry that spans the largest - * physical address that is accessible by ISA DMA is split into two - * PHYSSEG entries. - */ -#define PHYSMAP_SIZE (2 * (VM_PHYSSEG_MAX - 1)) - -vm_paddr_t phys_avail[PHYSMAP_SIZE + 2]; -vm_paddr_t dump_avail[PHYSMAP_SIZE + 2]; - -/* must be 2 less so 0 0 can signal end of chunks */ -#define PHYS_AVAIL_ARRAY_END (nitems(phys_avail) - 2) -#define DUMP_AVAIL_ARRAY_END (nitems(dump_avail) - 2) - struct kva_md_info kmi; static struct trapframe proc0_tf; Index: sys/i386/include/physmem.h =================================================================== --- /dev/null +++ sys/i386/include/physmem.h @@ -0,0 +1,51 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2018 Johannes Lundberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_PHYSMEM_H_ +#define _MACHINE_PHYSMEM_H_ + +#include +#include + +/* + * The number of PHYSMAP entries must be one less than the number of + * PHYSSEG entries because the PHYSMAP entry that spans the largest + * physical address that is accessible by ISA DMA is split into two + * PHYSSEG entries. + */ +#define PHYSMAP_SIZE (2 * (VM_PHYSSEG_MAX - 1)) + +/* must be 2 less so 0 0 can signal end of chunks */ +#define PHYS_AVAIL_ARRAY_END (nitems(phys_avail) - 2) +#define DUMP_AVAIL_ARRAY_END (nitems(dump_avail) - 2) + +/* kern_physmem.c */ +extern vm_paddr_t phys_avail[PHYSMAP_SIZE + 2]; +extern vm_paddr_t dump_avail[PHYSMAP_SIZE + 2]; +void phys_avail_reserve(vm_paddr_t start, vm_paddr_t end); + +#endif /* _MACHINE_PHYSMEM_H_ */ Index: sys/i386/include/pmap.h =================================================================== --- sys/i386/include/pmap.h +++ sys/i386/include/pmap.h @@ -171,6 +171,8 @@ #include +#include + #if defined(PAE) || defined(PAE_TABLES) typedef uint64_t pdpt_entry_t; @@ -358,8 +360,6 @@ extern caddr_t CADDR3; extern pt_entry_t *CMAP3; -extern vm_paddr_t phys_avail[]; -extern vm_paddr_t dump_avail[]; extern char *ptvmmap; /* poor name! */ extern vm_offset_t virtual_avail; extern vm_offset_t virtual_end; Index: sys/kern/kern_physmem.c =================================================================== --- /dev/null +++ sys/kern/kern_physmem.c @@ -0,0 +1,157 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2018 Johannes Lundberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +static void phys_avail_insert_at(unsigned int index, vm_paddr_t val); +static void phys_avail_delete_at(unsigned int index); + +vm_paddr_t phys_avail[PHYSMAP_SIZE + 2]; +vm_paddr_t dump_avail[PHYSMAP_SIZE + 2]; + +static void +phys_avail_insert_at(unsigned int index, vm_paddr_t val) +{ + unsigned int i; + + i = PHYS_AVAIL_ARRAY_END; + while (i >= index) { + phys_avail[i + 1] = phys_avail[i]; + i--; + } + phys_avail[i + 1] = val; +} + +static void +phys_avail_delete_at(unsigned int index) +{ + unsigned int i; + + i = index; + while (i <= PHYS_AVAIL_ARRAY_END) { + phys_avail[i] = phys_avail[i + 1]; + i++; + } +} + +void +phys_avail_reserve(vm_paddr_t start, vm_paddr_t end) +{ + unsigned int i; + /* Check if inside a hole before first segment. */ + if (end <= phys_avail[0]) + return; + + i = 0; + /* Check if inside any hole. */ + while (phys_avail[i + 2] != 0) { + if (start >= phys_avail[i + 1] && end <= phys_avail[i + 2]) + return; + i += 2; + } + + /* Check if new hole is after last segment end (i+1). */ + if (start >= phys_avail[i + 1]) + return; + + i=0; + /* Check if inside any segment */ + while (phys_avail[i + 1] != 0) { + if (start > phys_avail[i] && end < phys_avail[i + 1]) { + phys_avail_insert_at(i + 1, end); + phys_avail_insert_at(i + 1, start); + return; + } + i += 2; + } + + /* Other cases */ + i=0; + while (phys_avail[i] < start && i <= PHYS_AVAIL_ARRAY_END) { + i++; + } + + if (phys_avail[i + 1] == 0) { + /* The new hole starts in the last segment and ends after. */ + phys_avail[i] = start; + return; + } + + /* At the index located on or after the new hole start. */ + if (i % 2 == 0) { + /* + * Even index mean beginning of a segment. If hole ends in + * segment, shrink the segment. If exact match, delete the + * segment. Other cases are handled below. + */ + if (start == phys_avail[i]) { + if (end < phys_avail[i + 1]) { + phys_avail[i] = end; + return; + } else if (end == phys_avail[i + 1]) { + phys_avail_delete_at(i); + phys_avail_delete_at(i); + return; + } + } + } else { + /* + * Odd index mean the hole starts inside a memory segment. + * Shrink segment to hole start. + */ + phys_avail[i] = start; + i++; + } + + int deleted = 0; + while (phys_avail[i] <= end && phys_avail[i + 1] != 0) { + phys_avail_delete_at(i); + deleted++; + } + + /* At the index located after the new hole end. */ + if (i % 2 == 0 && deleted % 2 == 1) { + /* + * If index is even and odd number of entries have been deleted, + * we are at the end of a segment. Insert hole end before this + * segment end. + */ + phys_avail_insert_at(i, end); + } else if (i % 2 == 1) { + /* + * Odd index mean our hole ends in the previous segment, + * move segment start to new hole end. + */ + phys_avail[i-1] = start; + } +}