Enable these tests to be run on other pfnmap'ed memory like
NVIDIA's EGM.

Add '--' as a separator to pass in file path. This allows
passing of cmd line arguments to kselftest_harness.
Use '/dev/mem' as default filename.

Existing test passes:
        pfnmap
        TAP version 13
        1..6
        # Starting 6 tests from 1 test cases.
        # PASSED: 6 / 6 tests passed.
        # Totals: pass:6 fail:0 xfail:0 xpass:0 skip:0 error:0

Pass params to kselftest_harness:
        pfnmap -r pfnmap:mremap_fixed
        TAP version 13
        1..1
        # Starting 1 tests from 1 test cases.
        #  RUN           pfnmap.mremap_fixed ...
        #            OK  pfnmap.mremap_fixed
        ok 1 pfnmap.mremap_fixed
        # PASSED: 1 / 1 tests passed.
        # Totals: pass:1 fail:0 xfail:0 xpass:0 skip:0 error:0

Pass non-existent file name as input:
        pfnmap -- /dev/blah
        TAP version 13
        1..6
        # Starting 6 tests from 1 test cases.
        #  RUN           pfnmap.madvise_disallowed ...
        #      SKIP      Cannot open '/dev/blah'

Pass non pfnmap'ed file as input:
        pfnmap -r pfnmap.madvise_disallowed -- randfile
        TAP version 13
        1..1
        # Starting 1 tests from 1 test cases.
        #  RUN           pfnmap.madvise_disallowed ...
        #      SKIP      Invalid file: 'randfile'. Not pfnmap'ed

Signed-off-by: Sudarsan Mahendran <[email protected]>
---

v1 -> v2:
* Add verify_pfnmap func to sanity check the input param
* mmap with zero offset if filename != '/dev/mem'

---
 tools/testing/selftests/mm/pfnmap.c | 62 ++++++++++++++++++++++++-----
 1 file changed, 53 insertions(+), 9 deletions(-)

diff --git a/tools/testing/selftests/mm/pfnmap.c 
b/tools/testing/selftests/mm/pfnmap.c
index 866ac023baf5..e078b961c333 100644
--- a/tools/testing/selftests/mm/pfnmap.c
+++ b/tools/testing/selftests/mm/pfnmap.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Basic VM_PFNMAP tests relying on mmap() of '/dev/mem'
+ * Basic VM_PFNMAP tests relying on mmap() of input file provided.
+ * Use '/dev/mem' as default.
  *
  * Copyright 2025, Red Hat, Inc.
  *
@@ -25,6 +26,7 @@
 #include "vm_util.h"
 
 static sigjmp_buf sigjmp_buf_env;
+static char *file = "/dev/mem";
 
 static void signal_handler(int sig)
 {
@@ -98,6 +100,30 @@ static int find_ram_target(off_t *phys_addr,
        return -ENOENT;
 }
 
+static int verify_pfnmap(void)
+{
+       FILE *smaps_fp;
+       char line[512];
+       int found_mmap_entry = 0;
+
+       smaps_fp = fopen("/proc/self/smaps", "r");
+       if (!smaps_fp)
+               return -errno;
+       while (fgets(line, sizeof(line), smaps_fp) != NULL) {
+               if (strstr(line, file) && strstr(line, " r--s "))
+                       found_mmap_entry = 1;
+
+               if (found_mmap_entry &&
+                   strncmp(line, "VmFlags:", strlen("VmFlags:")) == 0) {
+                       if (strstr(line, " pf "))
+                               return 0;
+                       found_mmap_entry = 0;
+               }
+       }
+       fclose(smaps_fp);
+       return -ENOENT;
+}
+
 FIXTURE(pfnmap)
 {
        off_t phys_addr;
@@ -113,23 +139,31 @@ FIXTURE_SETUP(pfnmap)
 {
        self->pagesize = getpagesize();
 
-       /* We'll require two physical pages throughout our tests ... */
-       if (find_ram_target(&self->phys_addr, self->pagesize))
-               SKIP(return, "Cannot find ram target in '/proc/iomem'\n");
+       if (strncmp(file, "/dev/mem", strlen("/dev/mem")) == 0) {
+               /* We'll require two physical pages throughout our tests ... */
+               if (find_ram_target(&self->phys_addr, self->pagesize))
+                       SKIP(return,
+                                  "Cannot find ram target in '/proc/iomem'\n");
+       } else {
+               self->phys_addr = 0;
+       }
 
-       self->dev_mem_fd = open("/dev/mem", O_RDONLY);
+       self->dev_mem_fd = open(file, O_RDONLY);
        if (self->dev_mem_fd < 0)
-               SKIP(return, "Cannot open '/dev/mem'\n");
+               SKIP(return, "Cannot open '%s'\n", file);
 
        self->size1 = self->pagesize * 2;
        self->addr1 = mmap(NULL, self->size1, PROT_READ, MAP_SHARED,
                           self->dev_mem_fd, self->phys_addr);
        if (self->addr1 == MAP_FAILED)
-               SKIP(return, "Cannot mmap '/dev/mem'\n");
+               SKIP(return, "Cannot mmap '%s'\n", file);
+
+       if (verify_pfnmap())
+               SKIP(return, "Invalid file: '%s'. Not pfnmap'ed\n", file);
 
        /* ... and want to be able to read from them. */
        if (test_read_access(self->addr1, self->size1, self->pagesize))
-               SKIP(return, "Cannot read-access mmap'ed '/dev/mem'\n");
+               SKIP(return, "Cannot read-access mmap'ed '%s'\n", file);
 
        self->size2 = 0;
        self->addr2 = MAP_FAILED;
@@ -246,4 +280,14 @@ TEST_F(pfnmap, fork)
        ASSERT_EQ(ret, 0);
 }
 
-TEST_HARNESS_MAIN
+int main(int argc, char **argv)
+{
+       for (int i = 1; i < argc; i++) {
+               if (strcmp(argv[i], "--") == 0) {
+                       if (i + 1 < argc && strlen(argv[i + 1]) > 0)
+                               file = argv[i + 1];
+                       return test_harness_run(i, argv);
+               }
+       }
+       return test_harness_run(argc, argv);
+}
-- 
2.50.1.565.gc32cd1483b-goog


Reply via email to