libhugetlbfs/SOURCES/0027-tests-Improve-TASK_SIZ...

116 lines
3.9 KiB
Diff

From 96efdf51429812ec9b09f5ddb6ff24c80719e628 Mon Sep 17 00:00:00 2001
Message-Id: <96efdf51429812ec9b09f5ddb6ff24c80719e628.1566225007.git.aquini@redhat.com>
In-Reply-To: <d42f467a923dfc09309acb7a83b42e3285fbd8f4.1566225007.git.aquini@redhat.com>
References: <d42f467a923dfc09309acb7a83b42e3285fbd8f4.1566225007.git.aquini@redhat.com>
From: David Gibson <david@gibson.dropbear.id.au>
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 <david@gibson.dropbear.id.au>
Signed-off-by: Eric B Munson <eric@munsonfam.org>
Signed-off-by: Rafael Aquini <aquini@redhat.com>
---
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