Index: lib/libc/tests/gen/Makefile =================================================================== --- lib/libc/tests/gen/Makefile +++ lib/libc/tests/gen/Makefile @@ -11,6 +11,7 @@ ATF_TESTS_C+= fpclassify2_test ATF_TESTS_C+= ftw_test ATF_TESTS_C+= getentropy_test +ATF_TESTS_C+= getpagesize_test ATF_TESTS_C+= getmntinfo_test ATF_TESTS_C+= glob2_test ATF_TESTS_C+= makecontext_test Index: lib/libc/tests/gen/getpagesize_test.c =================================================================== --- /dev/null +++ lib/libc/tests/gen/getpagesize_test.c @@ -0,0 +1,215 @@ +/*- + * Copyright (c) 2022 The FreeBSD Foundation + * + * 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. + */ + +/* + * Tests the various ways to read the page size. + */ + +#include + +#include +#include +#include +#include + +#include + +#include + +#define PS_K(x) ((size_t)(x) * 1024) +#define PS_M(x) (PS_K(x) * 1024) +#define PS_G(x) (PS_M(x) * 1024) +#define PS_T(x) (PS_M(x) * 1024) + +#if defined(__aarch64__) +/* TODO: Check for 512GB after we bump MAXPAGESIZES */ +#define PS_4K +static const size_t page_sizes_4k[] = { PS_K(4), PS_M(2), PS_G(1), 0 }; +#define PS_16K +static const size_t page_sizes_16k[] = { PS_K(16), PS_M(32), PS_G(64), 0 }; +#define PS_64K +static const size_t page_sizes_64k[] = { PS_K(64), PS_M(512), PS_T(4), 0 }; + +#elif defined(__amd64__) +#define PS_4K +static const size_t page_sizes_4k[] = { PS_K(4), PS_M(2), PS_G(1), 0 }; + +#elif defined(__arm__) +#define PS_4K +static const size_t page_sizes_4k[] = { PS_K(4), PS_M(1), 0 }; + +#elif defined(__i386__) +/* Skip for now as the i386 sizes are more complicated */ +#define SKIP_PAGESIZES +#define PS_4K +static const size_t page_sizes_4k[] = { PS_K(4), 0 }; + +#elif defined(__powerpc__) +/* Skip for now as the powerpc sizes are more complicated */ +#define SKIP_PAGESIZES +#define PS_4K +static const size_t page_sizes_4k[] = { PS_K(4), 0 }; + +#elif defined(__riscv) +#define PS_4K +static const size_t page_sizes_4k[] = { PS_K(4), PS_M(2), 0 }; + +#else +#error Unknown architecture +#endif + +static const size_t *page_sizes[] = { +#ifdef PS_4K + page_sizes_4k, +#endif +#ifdef PS_16K + page_sizes_16k, +#endif +#ifdef PS_64K + page_sizes_64k +#endif +}; + +_Static_assert(sizeof(page_sizes) > 0, "No page sizes defined"); + +ATF_TC_WITHOUT_HEAD(getpagesize_test); +ATF_TC_BODY(getpagesize_test, tc) +{ + size_t ps, sc_pagesize, size; + int mib[2]; + int aux_pagesize, error, i, sysctl_pagesize; + bool found; + + ps = getpagesize(); + ATF_REQUIRE(ps > 0); + + found = false; + for (i = 0; i < nitems(page_sizes); i++) { + if (page_sizes[i][0] == ps) { + found = true; + break; + } + } + ATF_REQUIRE_MSG(found, "Unknown page size %zu", ps); + + error = elf_aux_info(AT_PAGESZ, &aux_pagesize, sizeof(aux_pagesize)); + if (error == 0) { + ATF_REQUIRE(aux_pagesize == ps); + } + + mib[0] = CTL_HW; + mib[1] = HW_PAGESIZE; + size = sizeof(sysctl_pagesize); + error = sysctl(mib, nitems(mib), &sysctl_pagesize, &size, NULL, 0); + if (error == 0) { + ATF_REQUIRE(sysctl_pagesize == ps); + } + + sc_pagesize = sysconf(_SC_PAGESIZE); + ATF_REQUIRE_MSG(sc_pagesize == ps, + "Incorrect page size from sysconf(_SC_PAGESIZE) (%zu != %zu)", + sc_pagesize, ps); + + sc_pagesize = sysconf(_SC_PAGE_SIZE); + ATF_REQUIRE_MSG(sc_pagesize == ps, + "Incorrect page size from sysconf(_SC_PAGESIZE) (%zu != %zu)", + sc_pagesize, ps); +} + +#ifndef SKIP_PAGESIZES +ATF_TC_WITHOUT_HEAD(getpagesizes_test); +ATF_TC_BODY(getpagesizes_test, tc) +{ + const size_t *sizes; + size_t ps[MAXPAGESIZES], size; + u_long ps_ul[MAXPAGESIZES]; + int error, i, pscnt; + + pscnt = getpagesizes(ps, MAXPAGESIZES); + ATF_REQUIRE_MSG(pscnt != -1, "getpagesizes failed; errno=%d", errno); + ATF_REQUIRE(pscnt > 0); + + sizes = NULL; + for (i = 0; i < nitems(page_sizes); i++) { + if (page_sizes[i][0] == ps[0]) { + sizes = page_sizes[i]; + break; + } + } + ATF_REQUIRE_MSG(sizes != NULL, "Unknown page size %zu", ps[0]); + + for (i = 0; sizes[i] != 0 && i < pscnt; i++) { + ATF_REQUIRE(i < MAXPAGESIZES); + ATF_REQUIRE(sizes[i] == ps[i]); + } + ATF_REQUIRE(i == pscnt); + + error = elf_aux_info(AT_PAGESIZES, ps_ul, sizeof(ps_ul)); + if (error == 0) { + for (i = 0; sizes[i] != 0 && i < pscnt; i++) { + ATF_REQUIRE(i < MAXPAGESIZES); + ATF_REQUIRE(sizes[i] == ps_ul[i]); + } + } + + size = sizeof(ps_ul); + error = sysctlbyname("hw.pagesizes", ps_ul, &size, NULL, 0); + if (error == 0) { + for (i = 0; sizes[i] != 0 && i < pscnt; i++) { + ATF_REQUIRE(i < MAXPAGESIZES); + ATF_REQUIRE(sizes[i] == ps_ul[i]); + } + } +} +#endif + +ATF_TC_WITHOUT_HEAD(getpagesize_eq_test); +ATF_TC_BODY(getpagesize_eq_test, tc) +{ + size_t ps[MAXPAGESIZES], page_size; + int pscnt; + + pscnt = getpagesizes(ps, MAXPAGESIZES); + ATF_REQUIRE_MSG(pscnt != -1, "getpagesizes failed; errno=%d", errno); + ATF_REQUIRE(pscnt > 0); + + page_size = getpagesize(); + ATF_REQUIRE_EQ(page_size, ps[0]); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, getpagesize_test); +#ifndef SKIP_PAGESIZES + ATF_TP_ADD_TC(tp, getpagesizes_test); +#endif + ATF_TP_ADD_TC(tp, getpagesize_eq_test); + + return (atf_no_error()); +}