xref: /linux/tools/testing/selftests/mm/map_hugetlb.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Example of using hugepage memory in a user application using the mmap
4  * system call with MAP_HUGETLB flag.  Before running this program make
5  * sure the administrator has allocated enough default sized huge pages
6  * to cover the 256 MB allocation.
7  */
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <unistd.h>
11 #include <sys/mman.h>
12 #include <fcntl.h>
13 #include "vm_util.h"
14 #include "../kselftest.h"
15 
16 #define LENGTH (256UL*1024*1024)
17 #define PROTECTION (PROT_READ | PROT_WRITE)
18 
19 static void check_bytes(char *addr)
20 {
21 	ksft_print_msg("First hex is %x\n", *((unsigned int *)addr));
22 }
23 
24 static void write_bytes(char *addr, size_t length)
25 {
26 	unsigned long i;
27 
28 	for (i = 0; i < length; i++)
29 		*(addr + i) = (char)i;
30 }
31 
32 static void read_bytes(char *addr, size_t length)
33 {
34 	unsigned long i;
35 
36 	check_bytes(addr);
37 	for (i = 0; i < length; i++)
38 		if (*(addr + i) != (char)i)
39 			ksft_exit_fail_msg("Mismatch at %lu\n", i);
40 
41 	ksft_test_result_pass("Read correct data\n");
42 }
43 
44 int main(int argc, char **argv)
45 {
46 	void *addr;
47 	size_t hugepage_size;
48 	size_t length = LENGTH;
49 	int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB;
50 	int shift = 0;
51 
52 	hugepage_size = default_huge_page_size();
53 	/* munmap with fail if the length is not page aligned */
54 	if (hugepage_size > length)
55 		length = hugepage_size;
56 
57 	ksft_print_header();
58 	ksft_set_plan(1);
59 
60 	if (argc > 1)
61 		length = atol(argv[1]) << 20;
62 	if (argc > 2) {
63 		shift = atoi(argv[2]);
64 		if (shift)
65 			flags |= (shift & MAP_HUGE_MASK) << MAP_HUGE_SHIFT;
66 	}
67 
68 	if (shift)
69 		ksft_print_msg("%u kB hugepages\n", 1 << (shift - 10));
70 	else
71 		ksft_print_msg("Default size hugepages\n");
72 	ksft_print_msg("Mapping %lu Mbytes\n", (unsigned long)length >> 20);
73 
74 	addr = mmap(NULL, length, PROTECTION, flags, -1, 0);
75 	if (addr == MAP_FAILED)
76 		ksft_exit_fail_msg("mmap: %s\n", strerror(errno));
77 
78 	ksft_print_msg("Returned address is %p\n", addr);
79 	check_bytes(addr);
80 	write_bytes(addr, length);
81 	read_bytes(addr, length);
82 
83 	/* munmap() length of MAP_HUGETLB memory must be hugepage aligned */
84 	if (munmap(addr, length))
85 		ksft_exit_fail_msg("munmap: %s\n", strerror(errno));
86 
87 	ksft_finished();
88 }
89