From 85df21fe3963f2a70863253ee7445e5fe624c966 Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Sat, 1 May 2021 18:11:54 -0400 Subject: [PATCH 1/1] pin_user_pages_fast SMP scalability benchmark This requires the kernel built with CONFIG_GUP_FAST=y and it must be run as root it won't be able to open /sys/kernel/debug/gup_test. Signed-off-by: Andrea Arcangeli --- tests/pin_fast.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 tests/pin_fast.c diff --git a/tests/pin_fast.c b/tests/pin_fast.c new file mode 100644 index 0000000..b1e6282 --- /dev/null +++ b/tests/pin_fast.c @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +/* exercises pin_user_pages_fast, requires a kernel with CONFIG_GUP_TEST=y */ +char *testcase_description = "pin_user_pages_fast SMP scalability benchmark"; + +static int gup_fd; +#define NR_PAGES 1024 +#define BUFLEN (getpagesize() * NR_PAGES) + +#define GUP_TEST_MAX_PAGES_TO_DUMP 8 +#define PIN_FAST_BENCHMARK _IOWR('g', 2, struct gup_test) + +struct gup_test { + __u64 get_delta_usec; + __u64 put_delta_usec; + __u64 addr; + __u64 size; + __u32 nr_pages_per_call; + __u32 flags; + /* + * Each non-zero entry is the number of the page (1-based: first page is + * page 1, so that zero entries mean "do nothing") from the .addr base. + */ + __u32 which_pages[GUP_TEST_MAX_PAGES_TO_DUMP]; +}; + +void testcase_prepare(unsigned long nr_tasks) +{ + gup_fd = open("/sys/kernel/debug/gup_test", O_RDWR); + assert(gup_fd >= 0); +} + +void testcase(unsigned long long *iterations, unsigned long nr) +{ + char *p = aligned_alloc(getpagesize()*512, BUFLEN); + assert(p); + assert(!madvise(p, BUFLEN, MADV_HUGEPAGE)); + for (int i = 0; i < NR_PAGES; i++) + p[getpagesize()*i] = 0; + + struct gup_test gup = { + .size = BUFLEN, + .addr = (unsigned long)p, + .nr_pages_per_call = 1, + }; + + while (1) { + assert(!ioctl(gup_fd, PIN_FAST_BENCHMARK, &gup)); + + (*iterations)++; + } + + free(p); +} + +void testcase_cleanup(void) +{ + assert(!close(gup_fd)); +}