diff --git a/sys/kern/subr_physmem.c b/sys/kern/subr_physmem.c --- a/sys/kern/subr_physmem.c +++ b/sys/kern/subr_physmem.c @@ -29,8 +29,10 @@ #include __FBSDID("$FreeBSD$"); +#ifdef _KERNEL #include "opt_acpi.h" #include "opt_ddb.h" +#endif /* * Routines for describing and initializing anything related to physical memory. @@ -40,12 +42,19 @@ #include #include #include + +#ifdef _KERNEL #include #include #include #include #include #include +#else +#include +#include +#include +#endif /* * These structures are used internally to keep track of regions of physical @@ -87,6 +96,20 @@ long realmem; long Maxmem; +#ifndef _KERNEL +static void +panic(const char *fmt, ...) +{ + va_list va; + + va_start(va, fmt); + vfprintf(stderr, fmt, va); + fprintf(stderr, "\n"); + va_end(va); + __builtin_trap(); +} +#endif + /* * Print the contents of the physical and excluded region tables using the * provided printf-like output function (which will be either printf or @@ -469,6 +492,7 @@ return (regions_to_avail(avail, EXFLAG_NOALLOC, maxavail, 0, NULL, NULL)); } +#ifdef _KERNEL /* * Process all the regions added earlier into the global avail lists. * @@ -495,6 +519,7 @@ panic("No memory entries in phys_avail"); Maxmem = atop(phys_avail[nextidx - 1]); } +#endif #ifdef DDB #include diff --git a/tests/sys/kern/Makefile b/tests/sys/kern/Makefile --- a/tests/sys/kern/Makefile +++ b/tests/sys/kern/Makefile @@ -23,6 +23,7 @@ TEST_METADATA.ptrace_test+= timeout="15" ATF_TESTS_C+= reaper ATF_TESTS_C+= sigaltstack +ATF_TESTS_C+= subr_physmem_test PLAIN_TESTS_C+= subr_unit_test ATF_TESTS_C+= sysctl_kern_proc ATF_TESTS_C+= sys_getrandom @@ -78,6 +79,9 @@ SRCS.libkern_crc32+= crc32c_armv8.S .endif +CFLAGS.subr_physmem.c+= -D_WANT_FREEBSD_BITSET +SRCS.subr_physmem_test+= subr_physmem_test.c subr_physmem.c + # subr_unit.c contains functions whose prototypes lie in headers that cannot be # included in userland. But as far as subr_unit_test goes, they're effectively # static. So it's ok to disable -Wmissing-prototypes for this program. diff --git a/tests/sys/kern/subr_physmem_test.c b/tests/sys/kern/subr_physmem_test.c new file mode 100644 --- /dev/null +++ b/tests/sys/kern/subr_physmem_test.c @@ -0,0 +1,122 @@ +/*- + * Copyright (c) 2021 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Andrew Turner under + * sponsorship from the FreeBSD Foundation. + * + * 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 + +ATF_TC_WITHOUT_HEAD(hwregion); +ATF_TC_BODY(hwregion, tc) +{ + vm_paddr_t avail[4]; + size_t len; + + physmem_hardware_region(2 * PAGE_SIZE, PAGE_SIZE); + + len = physmem_avail(avail, 4); + ATF_CHECK_EQ(len, 2); + ATF_CHECK_EQ(avail[0], 2 * PAGE_SIZE); + ATF_CHECK_EQ(avail[1], 3 * PAGE_SIZE); + + /* Add an overlap */ + physmem_hardware_region(2 * PAGE_SIZE, 2 * PAGE_SIZE); + len = physmem_avail(avail, 4); + ATF_CHECK_EQ(len, 2); + ATF_CHECK_EQ(avail[0], 2 * PAGE_SIZE); + ATF_CHECK_EQ(avail[1], 4 * PAGE_SIZE); + + /* Add a touching region */ + physmem_hardware_region(4 * PAGE_SIZE, PAGE_SIZE); + len = physmem_avail(avail, 4); + ATF_CHECK_EQ(len, 2); + ATF_CHECK_EQ(avail[0], 2 * PAGE_SIZE); + ATF_CHECK_EQ(avail[1], 5 * PAGE_SIZE); + + /* Add a partial overlap */ + physmem_hardware_region(4 * PAGE_SIZE, 2 * PAGE_SIZE); + len = physmem_avail(avail, 4); + ATF_CHECK_EQ(len, 2); + ATF_CHECK_EQ(avail[0], 2 * PAGE_SIZE); + ATF_CHECK_EQ(avail[1], 6 * PAGE_SIZE); + + /* Add a non-page aligned section */ + physmem_hardware_region(6 * PAGE_SIZE, PAGE_SIZE / 2); + len = physmem_avail(avail, 4); + ATF_CHECK_EQ(len, 2); + ATF_CHECK_EQ(avail[0], 2 * PAGE_SIZE); + ATF_CHECK_EQ(avail[1], 6 * PAGE_SIZE); + +#ifdef notyet /* This doesn't currently work */ + /* Add the remaining part of the page */ + physmem_hardware_region(6 * PAGE_SIZE + PAGE_SIZE / 2, PAGE_SIZE / 2); + len = physmem_avail(avail, 4); + ATF_CHECK_EQ(len, 2); + ATF_CHECK_EQ(avail[0], 2 * PAGE_SIZE); + ATF_CHECK_EQ(avail[1], 7 * PAGE_SIZE); +#endif +} + +ATF_TC_WITHOUT_HEAD(hwregion_exclude); +ATF_TC_BODY(hwregion_exclude, tc) +{ + vm_paddr_t avail[6]; + size_t len; + + physmem_hardware_region(2 * PAGE_SIZE, 5 * PAGE_SIZE); + physmem_exclude_region(4 * PAGE_SIZE, PAGE_SIZE, EXFLAG_NOALLOC); + + len = physmem_avail(avail, 6); + ATF_CHECK_EQ(len, 4); + ATF_CHECK_EQ(avail[0], 2 * PAGE_SIZE); + ATF_CHECK_EQ(avail[1], 4 * PAGE_SIZE); + ATF_CHECK_EQ(avail[2], 5 * PAGE_SIZE); + ATF_CHECK_EQ(avail[3], 7 * PAGE_SIZE); + + /* Check mis-aligned/sized excluded regions work */ + physmem_exclude_region(4 * PAGE_SIZE - 1, PAGE_SIZE + 2, + EXFLAG_NOALLOC); + len = physmem_avail(avail, 6); + ATF_CHECK_EQ(len, 4); + ATF_CHECK_EQ(avail[0], 2 * PAGE_SIZE); + ATF_CHECK_EQ(avail[1], 3 * PAGE_SIZE); + ATF_CHECK_EQ(avail[2], 6 * PAGE_SIZE); + ATF_CHECK_EQ(avail[3], 7 * PAGE_SIZE); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, hwregion); + ATF_TP_ADD_TC(tp, hwregion_exclude); + return (atf_no_error()); +}