xref: /linux/tools/testing/selftests/mm/hugepage-mmap.c (revision 55d0969c451159cff86949b38c39171cab962069)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * hugepage-mmap:
4  *
5  * Example of using huge page memory in a user application using the mmap
6  * system call.  Before running this application, make sure that the
7  * administrator has mounted the hugetlbfs filesystem (on some directory
8  * like /mnt) using the command mount -t hugetlbfs nodev /mnt. In this
9  * example, the app is requesting memory of size 256MB that is backed by
10  * huge pages.
11  */
12 #define _GNU_SOURCE
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <unistd.h>
16 #include <sys/mman.h>
17 #include <fcntl.h>
18 #include "../kselftest.h"
19 
20 #define LENGTH (256UL*1024*1024)
21 #define PROTECTION (PROT_READ | PROT_WRITE)
22 
23 static void check_bytes(char *addr)
24 {
25 	ksft_print_msg("First hex is %x\n", *((unsigned int *)addr));
26 }
27 
28 static void write_bytes(char *addr)
29 {
30 	unsigned long i;
31 
32 	for (i = 0; i < LENGTH; i++)
33 		*(addr + i) = (char)i;
34 }
35 
36 static int read_bytes(char *addr)
37 {
38 	unsigned long i;
39 
40 	check_bytes(addr);
41 	for (i = 0; i < LENGTH; i++)
42 		if (*(addr + i) != (char)i) {
43 			ksft_print_msg("Error: Mismatch at %lu\n", i);
44 			return 1;
45 		}
46 	return 0;
47 }
48 
49 int main(void)
50 {
51 	void *addr;
52 	int fd, ret;
53 
54 	ksft_print_header();
55 	ksft_set_plan(1);
56 
57 	fd = memfd_create("hugepage-mmap", MFD_HUGETLB);
58 	if (fd < 0)
59 		ksft_exit_fail_msg("memfd_create() failed: %s\n", strerror(errno));
60 
61 	addr = mmap(NULL, LENGTH, PROTECTION, MAP_SHARED, fd, 0);
62 	if (addr == MAP_FAILED) {
63 		close(fd);
64 		ksft_exit_fail_msg("mmap(): %s\n", strerror(errno));
65 	}
66 
67 	ksft_print_msg("Returned address is %p\n", addr);
68 	check_bytes(addr);
69 	write_bytes(addr);
70 	ret = read_bytes(addr);
71 
72 	munmap(addr, LENGTH);
73 	close(fd);
74 
75 	ksft_test_result(!ret, "Read same data\n");
76 
77 	ksft_exit(!ret);
78 }
79