linux-yocto/tools/testing/selftests/mm/map_fixed_noreplace.c
Mark Brown e7d2a28bd0 selftests: mm: make map_fixed_noreplace test names stable
KTAP parsers interpret the output of ksft_test_result_*() as being the
name of the test.  The map_fixed_noreplace test uses a dynamically
allocated base address for the mmap()s that it tests and currently
includes this in the test names that it logs so the test names that are
logged are not stable between runs.  It also uses multiples of PAGE_SIZE
which mean that runs for kernels with different PAGE_SIZE configurations
can't be directly compared.  Both these factors cause issues for CI
systems when interpreting and displaying results.

Fix this by replacing the current test names with fixed strings describing
the intent of the mappings that are logged, the existing messages with the
actual addresses and sizes are retained as diagnostic prints to aid in
debugging.

Link: https://lkml.kernel.org/r/20240605-kselftest-mm-fixed-noreplace-v1-1-a235db8b9be9@kernel.org
Fixes: 4838cf70e5 ("selftests/mm: map_fixed_noreplace: conform test to TAP format output")
Signed-off-by: Mark Brown <broonie@kernel.org>
Reviewed-by: Ryan Roberts <ryan.roberts@arm.com>
Cc: Muhammad Usama Anjum <usama.anjum@collabora.com>
Cc: Shuah Khan <shuah@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
2024-06-15 10:43:07 -07:00

202 lines
5.4 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Test that MAP_FIXED_NOREPLACE works.
*
* Copyright 2018, Jann Horn <jannh@google.com>
* Copyright 2018, Michael Ellerman, IBM Corporation.
*/
#include <sys/mman.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "../kselftest.h"
static void dump_maps(void)
{
char cmd[32];
snprintf(cmd, sizeof(cmd), "cat /proc/%d/maps", getpid());
system(cmd);
}
static unsigned long find_base_addr(unsigned long size)
{
void *addr;
unsigned long flags;
flags = MAP_PRIVATE | MAP_ANONYMOUS;
addr = mmap(NULL, size, PROT_NONE, flags, -1, 0);
if (addr == MAP_FAILED)
ksft_exit_fail_msg("Error: couldn't map the space we need for the test\n");
if (munmap(addr, size) != 0)
ksft_exit_fail_msg("Error: munmap failed\n");
return (unsigned long)addr;
}
int main(void)
{
unsigned long base_addr;
unsigned long flags, addr, size, page_size;
char *p;
ksft_print_header();
ksft_set_plan(9);
page_size = sysconf(_SC_PAGE_SIZE);
/* let's find a base addr that is free before we start the tests */
size = 5 * page_size;
base_addr = find_base_addr(size);
flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE;
/* Check we can map all the areas we need below */
addr = base_addr;
size = 5 * page_size;
p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
if (p == MAP_FAILED) {
dump_maps();
ksft_exit_fail_msg("Error: couldn't map the space we need for the test\n");
}
if (munmap((void *)addr, 5 * page_size) != 0) {
dump_maps();
ksft_exit_fail_msg("Error: munmap failed!?\n");
}
ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
ksft_test_result_pass("mmap() 5*PAGE_SIZE at base\n");
addr = base_addr + page_size;
size = 3 * page_size;
p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
if (p == MAP_FAILED) {
dump_maps();
ksft_exit_fail_msg("Error: first mmap() failed unexpectedly\n");
}
ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
ksft_test_result_pass("mmap() 3*PAGE_SIZE at base+PAGE_SIZE\n");
/*
* Exact same mapping again:
* base | free | new
* +1 | mapped | new
* +2 | mapped | new
* +3 | mapped | new
* +4 | free | new
*/
addr = base_addr;
size = 5 * page_size;
p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
if (p != MAP_FAILED) {
dump_maps();
ksft_exit_fail_msg("Error:1: mmap() succeeded when it shouldn't have\n");
}
ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
ksft_test_result_pass("mmap() 5*PAGE_SIZE at base\n");
/*
* Second mapping contained within first:
*
* base | free |
* +1 | mapped |
* +2 | mapped | new
* +3 | mapped |
* +4 | free |
*/
addr = base_addr + (2 * page_size);
size = page_size;
p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
if (p != MAP_FAILED) {
dump_maps();
ksft_exit_fail_msg("Error:2: mmap() succeeded when it shouldn't have\n");
}
ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
ksft_test_result_pass("mmap() 2*PAGE_SIZE at base+PAGE_SIZE\n");
/*
* Overlap end of existing mapping:
* base | free |
* +1 | mapped |
* +2 | mapped |
* +3 | mapped | new
* +4 | free | new
*/
addr = base_addr + (3 * page_size);
size = 2 * page_size;
p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
if (p != MAP_FAILED) {
dump_maps();
ksft_exit_fail_msg("Error:3: mmap() succeeded when it shouldn't have\n");
}
ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
ksft_test_result_pass("mmap() 2*PAGE_SIZE at base+(3*PAGE_SIZE)\n");
/*
* Overlap start of existing mapping:
* base | free | new
* +1 | mapped | new
* +2 | mapped |
* +3 | mapped |
* +4 | free |
*/
addr = base_addr;
size = 2 * page_size;
p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
if (p != MAP_FAILED) {
dump_maps();
ksft_exit_fail_msg("Error:4: mmap() succeeded when it shouldn't have\n");
}
ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
ksft_test_result_pass("mmap() 2*PAGE_SIZE bytes at base\n");
/*
* Adjacent to start of existing mapping:
* base | free | new
* +1 | mapped |
* +2 | mapped |
* +3 | mapped |
* +4 | free |
*/
addr = base_addr;
size = page_size;
p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
if (p == MAP_FAILED) {
dump_maps();
ksft_exit_fail_msg("Error:5: mmap() failed when it shouldn't have\n");
}
ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
ksft_test_result_pass("mmap() PAGE_SIZE at base\n");
/*
* Adjacent to end of existing mapping:
* base | free |
* +1 | mapped |
* +2 | mapped |
* +3 | mapped |
* +4 | free | new
*/
addr = base_addr + (4 * page_size);
size = page_size;
p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
if (p == MAP_FAILED) {
dump_maps();
ksft_exit_fail_msg("Error:6: mmap() failed when it shouldn't have\n");
}
ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
ksft_test_result_pass("mmap() PAGE_SIZE at base+(4*PAGE_SIZE)\n");
addr = base_addr;
size = 5 * page_size;
if (munmap((void *)addr, size) != 0) {
dump_maps();
ksft_exit_fail_msg("Error: munmap failed!?\n");
}
ksft_test_result_pass("Base Address unmap() successful\n");
ksft_finished();
}