lkml.org 
[lkml]   [2017]   [Nov]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
SubjectRe: [PATCHv3 2/2] x86/selftests: Add test for mapping placement for 5-level paging
Date
"Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> writes:

> With 5-level paging, we have 56-bit virtual address space available for
> userspace. But we don't want to expose userspace to addresses above
> 47-bits, unless it asked specifically for it.
>
> We use mmap(2) hint address as a way for kernel to know if it's okay to
> allocate virtual memory above 47-bit.
>
> Let's add a self-test that covers few corner cases of the interface.
>
> Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>

Can we move this to selftest/vm/ ? I had a variant which i was using to
test issues on ppc64. One change we did recently was to use >=128TB as
the hint addr value to select larger address space. I also would like to
check for exact mmap return addr in some case. Attaching below the test
i was using. I will check whether this patch can be updated to test what
is converted in my selftest. I also want to do the boundary check twice.
The hash trasnslation mode in POWER require us to track addr limit and
we had bugs around address space slection before and after updating the
addr limit.

From 7739eb02bb6b6602572a9c259e915ef23950aae1 Mon Sep 17 00:00:00 2001
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
Date: Mon, 13 Nov 2017 10:41:10 +0530
Subject: [PATCH] selftest/mm: Add test for checking mmap across 128TB boundary

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
tools/testing/selftests/vm/Makefile | 1 +
tools/testing/selftests/vm/run_vmtests | 11 ++
tools/testing/selftests/vm/va_128TBswitch.c | 170 ++++++++++++++++++++++++++++
3 files changed, 182 insertions(+)
create mode 100644 tools/testing/selftests/vm/va_128TBswitch.c

diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
index cbb29e41ef2b..b1fb3cd7cf52 100644
--- a/tools/testing/selftests/vm/Makefile
+++ b/tools/testing/selftests/vm/Makefile
@@ -17,6 +17,7 @@ TEST_GEN_FILES += transhuge-stress
TEST_GEN_FILES += userfaultfd
TEST_GEN_FILES += mlock-random-test
TEST_GEN_FILES += virtual_address_range
+TEST_GEN_FILES += va_128TBswitch

TEST_PROGS := run_vmtests

diff --git a/tools/testing/selftests/vm/run_vmtests b/tools/testing/selftests/vm/run_vmtests
index 07548a1fa901..b367f7801b67 100755
--- a/tools/testing/selftests/vm/run_vmtests
+++ b/tools/testing/selftests/vm/run_vmtests
@@ -176,4 +176,15 @@ else
echo "[PASS]"
fi

+echo "-----------------------------"
+echo "running virtual address 128TB switch test"
+echo "-----------------------------"
+./va_128TBswitch
+if [ $? -ne 0 ]; then
+ echo "[FAIL]"
+ exitcode=1
+else
+ echo "[PASS]"
+fi
+
exit $exitcode
diff --git a/tools/testing/selftests/vm/va_128TBswitch.c b/tools/testing/selftests/vm/va_128TBswitch.c
new file mode 100644
index 000000000000..dfa501b825a8
--- /dev/null
+++ b/tools/testing/selftests/vm/va_128TBswitch.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright IBM Corporation, 2017
+ * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2.1 of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+
+#ifdef DEBUG
+#define pr_debug(fmt, ...) printf(fmt, ##__VA_ARGS__)
+#else
+#define pr_debug(fmt, ...)
+#endif
+
+/*
+ * >= 128TB is the hint addr value we used to select
+ * large address space.
+ */
+#define ADDR_SWITCH_HINT (1UL << 47)
+
+#ifdef __powerpc64__
+#define MAP_SIZE 64*1024
+#else
+#define MAP_SIZE 4*1024
+#endif
+
+
+void report_failure(long in_addr, unsigned long flags)
+{
+ printf("Failed to map 0x%lx with flags 0x%lx\n", in_addr, flags);
+ exit(1);
+}
+
+int *__map_addr(long in_addr, int size, unsigned long flags, int unmap)
+{
+ int *addr;
+
+ addr = (int *)mmap((void *)in_addr, size, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE | flags, -1, 0);
+ if (addr == MAP_FAILED)
+ report_failure(in_addr, flags);
+ pr_debug("Mapped addr 0x%lx-0x%lx for request 0x%lx with flag 0x%lx\n",
+ (unsigned long)addr, ((unsigned long)addr + size), in_addr, flags);
+ /*
+ * Try to access to catch errors in fault handling/slb miss handling
+ */
+ *addr = 10;
+ if (unmap)
+ munmap(addr, size);
+ return addr;
+}
+
+int *map_addr(long in_addr, unsigned long flags, int unmap)
+{
+ return __map_addr(in_addr, MAP_SIZE, flags, unmap);
+}
+
+void boundary_check(void)
+{
+ int *a;
+
+ /*
+ * If stack is moved, we could possibly allocate
+ * this at the requested address.
+ */
+ a = map_addr((ADDR_SWITCH_HINT - MAP_SIZE), 0, 1);
+ if ((unsigned long)a > ADDR_SWITCH_HINT - MAP_SIZE)
+ report_failure(ADDR_SWITCH_HINT - MAP_SIZE, 0);
+
+ /*
+ * We should never allocate at the requested address or above it
+ * The len cross the 128TB boundary. Without MAP_FIXED
+ * we will always search in the lower address space.
+ */
+ a = __map_addr((ADDR_SWITCH_HINT - MAP_SIZE), 2*MAP_SIZE, 0, 1);
+ if ((unsigned long)a >= ADDR_SWITCH_HINT - MAP_SIZE)
+ report_failure(ADDR_SWITCH_HINT - MAP_SIZE, 0);
+ /*
+ * Exact mapping at 128TB, the area is free we should get that
+ * even without MAP_FIXED. Don't unmap. We check fixed in the
+ * same range later.
+ */
+ a = map_addr(ADDR_SWITCH_HINT, 0, 0);
+ if ((unsigned long)a != ADDR_SWITCH_HINT)
+ report_failure(ADDR_SWITCH_HINT, 0);
+
+ a = map_addr(ADDR_SWITCH_HINT + MAP_SIZE, 0, 1);
+ if ((unsigned long)a < ADDR_SWITCH_HINT)
+ report_failure(ADDR_SWITCH_HINT, 0);
+
+#if 0
+ /*
+ * Enable this with stack mapped MAP_SIZE below 128TB
+ */
+ a = map_addr((ADDR_SWITCH_HINT - MAP_SIZE), MAP_FIXED, 1);
+ if ((unsigned long)a != ADDR_SWITCH_HINT - MAP_SIZE)
+ report_failure(ADDR_SWITCH_HINT - MAP_SIZE, 0);
+ a = __map_addr((ADDR_SWITCH_HINT - MAP_SIZE), 2*MAP_SIZE, MAP_FIXED, 1);
+ if ((unsigned long)a != ADDR_SWITCH_HINT - MAP_SIZE)
+ report_failure(ADDR_SWITCH_HINT - MAP_SIZE, MAP_FIXED);
+
+#endif
+ a = map_addr(ADDR_SWITCH_HINT, MAP_FIXED, 1);
+ if ((unsigned long)a != ADDR_SWITCH_HINT)
+ report_failure(ADDR_SWITCH_HINT, MAP_FIXED);
+}
+
+static int supported_arch(void)
+{
+#if defined(__powerpc64__)
+ return 1;
+#elif defined(__x86_64__)
+ return 1;
+#else
+ return 0;
+#endif
+
+}
+
+int main(int argc, char *argv[])
+{
+ int *a;
+
+ if (!supported_arch())
+ return 0;
+ /*
+ * check the 128TB boundary before we update addr_limit
+ */
+ boundary_check();
+
+ a = map_addr(0, 0, 1);
+ if ((unsigned long)a > ADDR_SWITCH_HINT)
+ report_failure(0, 0);
+
+ a = map_addr(-1, 0, 1);
+ if ((unsigned long)a < ADDR_SWITCH_HINT)
+ report_failure(-1, 0);
+
+ /* don't unmap this one */
+ a = map_addr((1UL << 48), 0, 0);
+ if ((unsigned long)a != 1UL << 48)
+ report_failure((1UL << 48), 0);
+
+ a = map_addr((1UL << 48), 0, 1);
+ if ((unsigned long)a < ADDR_SWITCH_HINT)
+ report_failure((1UL << 48), 0);
+
+ a = map_addr(0, 0, 1);
+ if ((unsigned long)a > ADDR_SWITCH_HINT)
+ report_failure(0, 0);
+
+ a = map_addr(-1, 0, 1);
+ if ((unsigned long)a < ADDR_SWITCH_HINT)
+ report_failure(-1, 0);
+ /*
+ * Try boundary conditions again after we allocated something above 128TB
+ * and updated addr_limit.
+ */
+ boundary_check();
+}
--
2.14.3
\
 
 \ /
  Last update: 2017-11-22 06:42    [W:0.065 / U:1.144 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site