Skip to content

Commit bb08499

Browse files
davidhildenbrandakpm00
authored andcommitted
selftests/mm: two fixes for the pfnmap test
When unregistering the signal handler, we have to pass SIG_DFL, and blindly reading from PFN 0 and PFN 1 seems to be problematic on !x86 systems. In particularly, on arm64 tx2 machines where noting resides at these physical memory locations, we can generate RAS errors. Let's fix it by scanning /proc/iomem for actual "System RAM". Link: https://lkml.kernel.org/r/[email protected] Fixes: 2616b37 ("selftests/mm: add simple VM_PFNMAP tests based on mmap'ing /dev/mem") Signed-off-by: David Hildenbrand <[email protected]> Reported-by: Ryan Roberts <[email protected]> Closes: https://lore.kernel.org/all/[email protected]/T/#u Reviewed-by: Ryan Roberts <[email protected]> Tested-by: Aishwarya TCV <[email protected]> Cc: Shuah Khan <[email protected]> Cc: Lorenzo Stoakes <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 595cf68 commit bb08499

File tree

1 file changed

+57
-4
lines changed

1 file changed

+57
-4
lines changed

tools/testing/selftests/mm/pfnmap.c

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <stdint.h>
1313
#include <unistd.h>
1414
#include <errno.h>
15+
#include <stdio.h>
16+
#include <ctype.h>
1517
#include <fcntl.h>
1618
#include <signal.h>
1719
#include <setjmp.h>
@@ -43,14 +45,62 @@ static int test_read_access(char *addr, size_t size, size_t pagesize)
4345
/* Force a read that the compiler cannot optimize out. */
4446
*((volatile char *)(addr + offs));
4547
}
46-
if (signal(SIGSEGV, signal_handler) == SIG_ERR)
48+
if (signal(SIGSEGV, SIG_DFL) == SIG_ERR)
4749
return -EINVAL;
4850

4951
return ret;
5052
}
5153

54+
static int find_ram_target(off_t *phys_addr,
55+
unsigned long long pagesize)
56+
{
57+
unsigned long long start, end;
58+
char line[80], *end_ptr;
59+
FILE *file;
60+
61+
/* Search /proc/iomem for the first suitable "System RAM" range. */
62+
file = fopen("/proc/iomem", "r");
63+
if (!file)
64+
return -errno;
65+
66+
while (fgets(line, sizeof(line), file)) {
67+
/* Ignore any child nodes. */
68+
if (!isalnum(line[0]))
69+
continue;
70+
71+
if (!strstr(line, "System RAM\n"))
72+
continue;
73+
74+
start = strtoull(line, &end_ptr, 16);
75+
/* Skip over the "-" */
76+
end_ptr++;
77+
/* Make end "exclusive". */
78+
end = strtoull(end_ptr, NULL, 16) + 1;
79+
80+
/* Actual addresses are not exported */
81+
if (!start && !end)
82+
break;
83+
84+
/* We need full pages. */
85+
start = (start + pagesize - 1) & ~(pagesize - 1);
86+
end &= ~(pagesize - 1);
87+
88+
if (start != (off_t)start)
89+
break;
90+
91+
/* We need two pages. */
92+
if (end > start + 2 * pagesize) {
93+
fclose(file);
94+
*phys_addr = start;
95+
return 0;
96+
}
97+
}
98+
return -ENOENT;
99+
}
100+
52101
FIXTURE(pfnmap)
53102
{
103+
off_t phys_addr;
54104
size_t pagesize;
55105
int dev_mem_fd;
56106
char *addr1;
@@ -63,14 +113,17 @@ FIXTURE_SETUP(pfnmap)
63113
{
64114
self->pagesize = getpagesize();
65115

116+
/* We'll require two physical pages throughout our tests ... */
117+
if (find_ram_target(&self->phys_addr, self->pagesize))
118+
SKIP(return, "Cannot find ram target in '/proc/iomem'\n");
119+
66120
self->dev_mem_fd = open("/dev/mem", O_RDONLY);
67121
if (self->dev_mem_fd < 0)
68122
SKIP(return, "Cannot open '/dev/mem'\n");
69123

70-
/* We'll require the first two pages throughout our tests ... */
71124
self->size1 = self->pagesize * 2;
72125
self->addr1 = mmap(NULL, self->size1, PROT_READ, MAP_SHARED,
73-
self->dev_mem_fd, 0);
126+
self->dev_mem_fd, self->phys_addr);
74127
if (self->addr1 == MAP_FAILED)
75128
SKIP(return, "Cannot mmap '/dev/mem'\n");
76129

@@ -129,7 +182,7 @@ TEST_F(pfnmap, munmap_split)
129182
*/
130183
self->size2 = self->pagesize;
131184
self->addr2 = mmap(NULL, self->pagesize, PROT_READ, MAP_SHARED,
132-
self->dev_mem_fd, 0);
185+
self->dev_mem_fd, self->phys_addr);
133186
ASSERT_NE(self->addr2, MAP_FAILED);
134187
}
135188

0 commit comments

Comments
 (0)