tools/testing/selftests/mm/va_high_addr_switch.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/mm/va_high_addr_switch.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/mm/va_high_addr_switch.c
Extension
.c
Size
8414 bytes
Lines
341
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct testcase {
	void *addr;
	unsigned long size;
	unsigned long flags;
	const char *msg;
	unsigned int low_addr_required:1;
	unsigned int keep_mapped:1;
};

static struct testcase *testcases;
static struct testcase *hugetlb_testcases;
static int sz_testcases, sz_hugetlb_testcases;
static unsigned long switch_hint;

/* Initialize testcases inside a function to compute parameters at runtime */
void testcases_init(void)
{
	unsigned long pagesize = getpagesize();
	unsigned long hugepagesize = default_huge_page_size();
	unsigned long low_addr = (1UL << 30);
	unsigned long addr_switch_hint = ADDR_MARK_128TB;
	unsigned long high_addr = HIGH_ADDR_128TB;

#ifdef __aarch64__

	/* Post LPA2, the lower userspace VA on a 16K pagesize is 47 bits. */
	if (pagesize != (16UL << 10)) {
		addr_switch_hint = ADDR_MARK_256TB;
		high_addr = HIGH_ADDR_256TB;
	}
#endif

	struct testcase t[] = {
		{
			/*
			 * If stack is moved, we could possibly allocate
			 * this at the requested address.
			 */
			.addr = ((void *)(addr_switch_hint - pagesize)),
			.size = pagesize,
			.flags = MAP_PRIVATE | MAP_ANONYMOUS,
			.msg = "mmap(addr_switch_hint - pagesize, pagesize)",
			.low_addr_required = 1,
		},
		{
			/*
			 * Unless MAP_FIXED is specified, allocation based on hint
			 * addr is never at requested address or above it, which is
			 * beyond high address switch boundary in this case. Instead,
			 * a suitable allocation is found in lower address space.
			 */
			.addr = ((void *)(addr_switch_hint - pagesize)),
			.size = 2 * pagesize,
			.flags = MAP_PRIVATE | MAP_ANONYMOUS,
			.msg = "mmap(addr_switch_hint - pagesize, (2 * pagesize))",
			.low_addr_required = 1,
		},
		{
			/*
			 * Exact mapping at high address switch boundary, should
			 * be obtained even without MAP_FIXED as area is free.
			 */
			.addr = ((void *)(addr_switch_hint)),
			.size = pagesize,
			.flags = MAP_PRIVATE | MAP_ANONYMOUS,
			.msg = "mmap(addr_switch_hint, pagesize)",
			.keep_mapped = 1,
		},
		{
			.addr = (void *)(addr_switch_hint),
			.size = 2 * pagesize,
			.flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
			.msg = "mmap(addr_switch_hint, 2 * pagesize, MAP_FIXED)",
		},
		{
			.addr = NULL,
			.size = 2 * pagesize,
			.flags = MAP_PRIVATE | MAP_ANONYMOUS,
			.msg = "mmap(NULL)",
			.low_addr_required = 1,
		},
		{
			.addr = (void *)low_addr,
			.size = 2 * pagesize,
			.flags = MAP_PRIVATE | MAP_ANONYMOUS,
			.msg = "mmap(low_addr)",
			.low_addr_required = 1,
		},
		{
			.addr = (void *)high_addr,

Annotation

Implementation Notes