From 96efdf51429812ec9b09f5ddb6ff24c80719e628 Mon Sep 17 00:00:00 2001 Message-Id: <96efdf51429812ec9b09f5ddb6ff24c80719e628.1566225007.git.aquini@redhat.com> In-Reply-To: References: From: David Gibson Date: Sun, 18 Aug 2019 16:03:21 +1000 Subject: [RHEL7 PATCH 27/31] tests: Improve TASK_SIZE detection in task-size-overrun task-size-overrun is designed to test kernel behaviour in some edge cases involving making a hugepage mapping right near the address space limits. In order to do that, it needs to know the TASK_SIZE of the kernel it's running on. Currently it does that with a linear search from the last extant mapping. But with kernels supporting a very large address space that can take prohibitively long. We've had problems with that before, resulting in some hacks to skip a large chunk of address space. Those hacks are dependent on platform, though, which is ugly and fragile. Case in point, recent powerpc kernels now support a 4PiB address space, so the logic we have there is insufficient to finish the search in reasonable time. To handle this in a more robust way, this replaces the linear search with a binary search between the last extant mapping and (2^wordsize). Signed-off-by: David Gibson Signed-off-by: Eric B Munson Signed-off-by: Rafael Aquini --- tests/task-size-overrun.c | 57 +++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/tests/task-size-overrun.c b/tests/task-size-overrun.c index 914ef65..29b6045 100644 --- a/tests/task-size-overrun.c +++ b/tests/task-size-overrun.c @@ -64,45 +64,44 @@ static unsigned long find_last_mapped(void) return end; } +#define ALIGN_DOWN(x,a) ((x) & ~((a) - 1)) + static unsigned long find_task_size(void) { - unsigned long addr; + unsigned long low, high; /* PFNs */ void *p; - addr = find_last_mapped(); - if (!addr || ((addr % getpagesize()) != 0)) - FAIL("Bogus stack end address, 0x%lx!?", addr); + low = find_last_mapped(); + if (!low || ((low % getpagesize()) != 0)) + FAIL("Bogus stack end address, 0x%lx!?", low); + low = low / getpagesize(); + + /* This sum should get us (2^(wordsize) - 2 pages) */ + high = (unsigned long)(-2 * getpagesize()) / getpagesize(); + + verbose_printf("Binary searching for task size PFNs 0x%lx..0x%lx\n", + low, high); + + while (high > low + 1) { + unsigned long pfn = (low + high) / 2; + unsigned long addr = pfn * getpagesize(); + + assert((pfn >= low) && (pfn <= high)); - while (addr) { p = mmap64((void *)addr, getpagesize(), PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0); if (p == MAP_FAILED) { - verbose_printf("Searching map failed: %s\n", strerror(errno)); - return addr; + verbose_printf("Map failed at 0x%lx (%s)\n", + addr, strerror(errno)); + high = pfn; + } else { + verbose_printf("Map succeeded at 0x%lx\n", addr); + munmap(p, getpagesize()); + low = pfn; } - munmap(p, getpagesize()); - addr += getpagesize(); -#if defined(__powerpc64__) - if (addr > (1UL << 46) && addr < (1UL << 47)) - addr = 1UL << 47; /* 64TB */ - else if (addr > (1UL << 47) && addr < (1UL << 48)) - addr = 1UL << 48; /* 128TB */ - else if (addr > (1UL << 48) && addr < (1UL << 49)) - addr = 1UL << 49; /* 512TB */ - else if (addr > (1UL << 49) && addr < (1UL << 50)) - addr = 1UL << 50; /* 1PB */ - else if (addr > (1UL << 50) && addr < (1UL << 51)) - addr = 1UL << 51; /* 2PB */ - else if (addr > (1UL << 51) && addr < (1UL << 52)) - addr = 1UL << 52; /* 4PB */ -#endif -#if defined(__s390x__) - if (addr > (1UL << 42) && addr < (1UL << 53)) - addr = 1UL << 53; -#endif } - /* addr wrapped around */ - return 0; + + return low * getpagesize(); } int main(int argc, char *argv[]) -- 1.8.3.1