From: "David Hildenbrand (Arm)" <david@kernel.org>
To: Sarthak Sharma <sarthak.sharma@arm.com>,
Andrew Morton <akpm@linux-foundation.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>,
"Liam R . Howlett" <liam@infradead.org>,
Vlastimil Babka <vbabka@kernel.org>,
Mike Rapoport <rppt@kernel.org>,
Suren Baghdasaryan <surenb@google.com>,
Michal Hocko <mhocko@suse.com>, Shuah Khan <shuah@kernel.org>,
Shuah Khan <skhan@linuxfoundation.org>,
Jonathan Corbet <corbet@lwn.net>, Jason Gunthorpe <jgg@ziepe.ca>,
John Hubbard <jhubbard@nvidia.com>, Peter Xu <peterx@redhat.com>,
Leon Romanovsky <leon@kernel.org>, Zi Yan <ziy@nvidia.com>,
Baolin Wang <baolin.wang@linux.alibaba.com>,
Nico Pache <npache@redhat.com>,
Ryan Roberts <ryan.roberts@arm.com>, Dev Jain <dev.jain@arm.com>,
Barry Song <baohua@kernel.org>, Lance Yang <lance.yang@linux.dev>,
Mark Brown <broonie@kernel.org>,
Anshuman Khandual <anshuman.khandual@arm.com>,
Muhammad Usama Anjum <usama.anjum@arm.com>,
linux-mm@kvack.org, linux-kselftest@vger.kernel.org,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
Rik van Riel <riel@surriel.com>
Subject: Re: [PATCH v10 6/6] selftests/mm: add a GUP selftest
Date: Fri, 11 Sep 2026 17:48:16 +0200 [thread overview]
Message-ID: <891915e3-3333-45f3-81a8-1ad38fa7ee37@kernel.org> (raw)
In-Reply-To: <20260911110950.200240-7-sarthak.sharma@arm.com>
On 9/11/26 13:09, Sarthak Sharma wrote:
> Add a new GUP selftest which uses kselftest_harness.h. Cover
> 12 mapping configurations: THP enabled, THP disabled and
> HugeTLB, each across private/shared mappings and with/without
> FOLL_WRITE. Run 5 test cases for every variant: get_user_pages,
> get_user_pages_fast, pin_user_pages, pin_user_pages_fast and
> pin_user_pages_longterm.
>
> Use two default hugeTLB pages and derive the mapping size from
> their size. This exercises GUP both within a single HugeTLB page
> and across a HugeTLB boundary, without reserving an excessive
> number of pages.
>
> Sweep four nr_pages_per_call values for each test: 1, 512, 123 and
> all pages. This preserves the coverage previously provided by
> run_gup_matrix(): 12 mapping combinations x 5 GUP/PUP operations x 4
> batch sizes. In total the selftest reports 60 TAP cases and issues
> 240 ioctls.
>
> Do not carry DUMP_USER_PAGES_TEST into the new selftest because its
> output is written to the kernel log and the selftest does not verify
> that output.
>
> Add the new gup binary to the selftests/mm build, run_vmtests.sh and
> MAINTAINERS. Update mm/Kconfig to describe the benchmark and
> selftest split.
>
> Suggested-by: David Hildenbrand (Arm) <david@kernel.org>
> Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
> Tested-by: Muhammad Usama Anjum <usama.anjum@arm.com>
> Signed-off-by: Sarthak Sharma <sarthak.sharma@arm.com>
> ---
> MAINTAINERS | 1 +
> mm/Kconfig | 19 +-
> tools/testing/selftests/mm/Makefile | 1 +
> tools/testing/selftests/mm/gup.c | 263 ++++++++++++++++++++++
> tools/testing/selftests/mm/run_vmtests.sh | 1 +
> 5 files changed, 273 insertions(+), 12 deletions(-)
> create mode 100644 tools/testing/selftests/mm/gup.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index cae3af861a7c..c47e655c4111 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -17188,6 +17188,7 @@ F: mm/gup.c
> F: mm/gup_test.c
> F: mm/gup_test.h
> F: tools/mm/gup_bench.c
> +F: tools/testing/selftests/mm/gup.c
> F: tools/testing/selftests/mm/gup_longterm.c
>
> MEMORY MANAGEMENT - KSM (Kernel Samepage Merging)
> diff --git a/mm/Kconfig b/mm/Kconfig
> index c180d40cd671..61ab1b8a2ebd 100644
> --- a/mm/Kconfig
> +++ b/mm/Kconfig
> @@ -1291,24 +1291,19 @@ config PERCPU_STATS
> be used to help understand percpu memory usage.
>
> config GUP_TEST
> - bool "Enable infrastructure for get_user_pages()-related unit tests"
> + bool "Enable infrastructure for get_user_pages()-related unit tests and benchmarks"
> depends on DEBUG_FS
> help
> Provides /sys/kernel/debug/gup_test, which in turn provides a way
> - to make ioctl calls that can launch kernel-based unit tests for
> - the get_user_pages*() and pin_user_pages*() family of API calls.
> + to make ioctl calls that can launch kernel-based unit tests and
> + benchmarks for the get_user_pages*() and pin_user_pages*() families
> + of API calls.
>
> - These tests include benchmark testing of the _fast variants of
> - get_user_pages*() and pin_user_pages*(), as well as smoke tests of
> + These include benchmark testing of the _fast variants of
> + get_user_pages*() and pin_user_pages*(), as well as tests of
> the non-_fast variants.
>
> - There is also a sub-test that allows running dump_page() on any
> - of up to eight pages (selected by command line args) within the
> - range of user-space addresses. These pages are either pinned via
> - pin_user_pages*(), or pinned via get_user_pages*(), as specified
> - by other command line arguments.
> -
> - See tools/testing/selftests/mm/gup_test.c
> + See tools/testing/selftests/mm/gup.c and tools/mm/gup_bench.c.
>
> comment "GUP_TEST needs to have DEBUG_FS enabled"
> depends on !GUP_TEST && !DEBUG_FS
> diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile
> index 11ca9b11fef1..9c03624fd293 100644
> --- a/tools/testing/selftests/mm/Makefile
> +++ b/tools/testing/selftests/mm/Makefile
> @@ -58,6 +58,7 @@ endif
>
> TEST_GEN_FILES = cow
> TEST_GEN_FILES += compaction_test
> +TEST_GEN_FILES += gup
> TEST_GEN_FILES += gup_longterm
> TEST_GEN_FILES += hmm-tests
> TEST_GEN_FILES += hugetlb-madvise
> diff --git a/tools/testing/selftests/mm/gup.c b/tools/testing/selftests/mm/gup.c
> new file mode 100644
> index 000000000000..31ae38e09136
> --- /dev/null
> +++ b/tools/testing/selftests/mm/gup.c
> @@ -0,0 +1,263 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#define __SANE_USERSPACE_TYPES__ // Use ll64
> +#include <fcntl.h>
> +#include <errno.h>
> +#include <stdbool.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <dirent.h>
> +#include <sys/ioctl.h>
> +#include <sys/mman.h>
> +#include <mm/gup_test.h>
> +#include "vm_util.h"
> +#include "kselftest_harness.h"
> +
> +#define MB (1UL << 20)
> +
> +/* Just the flags we need, copied from the kernel internals. */
> +#define FOLL_WRITE 0x01 /* check pte is writable */
BTW, it's odd that we support passing GUP-flags ... we should probably switch at
some point simpler attributes (bool write) or custom flags (but we don't seem to
need many ...).
> +
> +/* Page counts exercising single, THP-batch, partial, and full-mapping GUP. */
> +static const int nr_pages_list[] = { 1, 512, 123, -1 };
Would we want to calculate 512 dynamically at runtime using the PMD pagesize?
Could be something for a follow-up patch.
> +
> +#define GUP_TEST_FILE "/sys/kernel/debug/gup_test"
> +#define NR_HUGE_PAGES 2
I'd call this "NR_HUGETLB_PAGES".
[...]
> +
> +FIXTURE_SETUP(gup_test)
> +{
> + int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
> + char *p;
> +
> + self->size = 128 * MB;
> +
> + if (variant->hugetlb) {
> + if (!hp_size)
> + SKIP(return, "HugeTLB not available\n");
> +
> + if (hugetlb_free_default_pages() < NR_HUGE_PAGES)
> + SKIP(return, "Not enough huge pages\n");
> +
> + self->size = NR_HUGE_PAGES * hp_size;
> + mmap_flags |= MAP_HUGETLB;
> + }
> +
> + if (variant->shared)
> + mmap_flags = (mmap_flags & ~MAP_PRIVATE) | MAP_SHARED;
> +
> + /* gup_fd has to be >= 0. Already checked in main() */
> + self->gup_fd = open(GUP_TEST_FILE, O_RDWR);
> + ASSERT_GE(self->gup_fd, 0);
> +
> + self->addr = mmap(NULL, self->size, PROT_READ | PROT_WRITE,
> + mmap_flags, -1, 0);
> +
> + ASSERT_NE(self->addr, MAP_FAILED) {
> + int err = errno;
> +
> + close(self->gup_fd);
> + TH_LOG("mmap failed: %s", strerror(err));
> + }
> +
> + if (variant->thp)
> + madvise(self->addr, self->size, MADV_HUGEPAGE);
> + else if (!variant->hugetlb)
> + madvise(self->addr, self->size, MADV_NOHUGEPAGE);
> +
> + for (p = self->addr; (unsigned long)p < (unsigned long)self->addr
> + + self->size; p += psize())
> + p[0] = 0;
> +}
> +
> +FIXTURE_TEARDOWN(gup_test)
> +{
> + munmap(self->addr, self->size);
> + close(self->gup_fd);
> +}
> +
> +static void run_gup_cmd(struct __test_metadata *_metadata,
> + FIXTURE_DATA(gup_test) *self,
> + const FIXTURE_VARIANT(gup_test) *variant,
> + unsigned long command)
We prefer two tab indents.
> +{
> + int i;
> +
> + for (i = 0; i < (int)ARRAY_SIZE(nr_pages_list); i++) {
> + struct gup_test gup = {
> + .addr = (unsigned long)self->addr,
> + .size = self->size,
> + .nr_pages_per_call = nr_pages_list[i] < 0 ?
> + self->size / psize() : nr_pages_list[i],
> + .gup_flags = variant->write ? FOLL_WRITE : 0,
> + };
> +
> + TH_LOG("nr_pages_per_call=%u", gup.nr_pages_per_call);
> + ASSERT_EQ(ioctl(self->gup_fd, command, &gup), 0);
> + ASSERT_EQ(gup.size, self->size);
> + }
> +}
> +
> +TEST_F(gup_test, get_user_pages)
> +{
> + run_gup_cmd(_metadata, self, variant, GUP_BASIC_TEST);
> +}
> +
> +TEST_F(gup_test, pin_user_pages)
> +{
> + run_gup_cmd(_metadata, self, variant, PIN_BASIC_TEST);
> +}
> +
> +TEST_F(gup_test, get_user_pages_fast)
> +{
> + run_gup_cmd(_metadata, self, variant, GUP_FAST_BENCHMARK);
> +}
> +
> +TEST_F(gup_test, pin_user_pages_fast)
> +{
> + run_gup_cmd(_metadata, self, variant, PIN_FAST_BENCHMARK);
> +}
> +
> +TEST_F(gup_test, pin_user_pages_longterm)
> +{
> + run_gup_cmd(_metadata, self, variant, PIN_LONGTERM_BENCHMARK);
> +}
Heh, is there actually a reason why these kernel things are called _BENCHMARK?
I think they are really just tests that can be used for benchmarking ... the
measurement logic is entirely in user space.
We could consider cleaning that up as a follow-up.
> +
> +int main(int argc, char **argv)
> +{
> + int fd;
> +
> + fd = open(GUP_TEST_FILE, O_RDWR);
Could do
const int fd = open(GUP_TEST_FILE, O_RDWR);
Thanks for doing that!
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
I think reasonable extensions will be to execute tests on all available mTHP
sizes and all available hugetlb sizes, similar to what cow.c already does.
Can you look into that as part of some follow-up work? mTHP support will be
interesting for testing some of the patches Rik has been working on.
--
Cheers,
David
prev parent reply other threads:[~2026-09-11 15:48 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-11 11:09 [PATCH v10 0/6] selftests/mm: separate GUP microbenchmarking from functional testing Sarthak Sharma
2026-09-11 11:09 ` [PATCH v10 1/6] selftests/mm: make file helpers return errors Sarthak Sharma
2026-09-11 11:09 ` [PATCH v10 2/6] tools/lib/mm: add shared file helpers Sarthak Sharma
2026-09-11 11:09 ` [PATCH v10 3/6] tools/lib/mm: move hugepage_settings out of selftests Sarthak Sharma
2026-09-11 11:09 ` [PATCH v10 4/6] tools/mm: move gup_test from selftests/mm to tools/mm Sarthak Sharma
2026-09-11 11:09 ` [PATCH v10 5/6] tools/mm: make gup_bench a benchmark only tool Sarthak Sharma
2026-09-11 11:09 ` [PATCH v10 6/6] selftests/mm: add a GUP selftest Sarthak Sharma
2026-09-11 15:48 ` David Hildenbrand (Arm) [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=891915e3-3333-45f3-81a8-1ad38fa7ee37@kernel.org \
--to=david@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=anshuman.khandual@arm.com \
--cc=baohua@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=broonie@kernel.org \
--cc=corbet@lwn.net \
--cc=dev.jain@arm.com \
--cc=jgg@ziepe.ca \
--cc=jhubbard@nvidia.com \
--cc=lance.yang@linux.dev \
--cc=leon@kernel.org \
--cc=liam@infradead.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=mhocko@suse.com \
--cc=npache@redhat.com \
--cc=peterx@redhat.com \
--cc=riel@surriel.com \
--cc=rppt@kernel.org \
--cc=ryan.roberts@arm.com \
--cc=sarthak.sharma@arm.com \
--cc=shuah@kernel.org \
--cc=skhan@linuxfoundation.org \
--cc=surenb@google.com \
--cc=usama.anjum@arm.com \
--cc=vbabka@kernel.org \
--cc=ziy@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox