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 | * For the ia64 architecture, the Linux kernel reserves Region number 4 for |
13 | * huge pages. That means that if one requires a fixed address, a huge page |
14 | * aligned address starting with 0x800000... will be required. If a fixed |
15 | * address is not required, the kernel will select an address in the proper |
16 | * range. |
17 | * Other architectures, such as ppc64, i386 or x86_64 are not so constrained. |
18 | */ |
19 | #define _GNU_SOURCE |
20 | #include <stdlib.h> |
21 | #include <stdio.h> |
22 | #include <unistd.h> |
23 | #include <sys/mman.h> |
24 | #include <fcntl.h> |
25 | #include "../kselftest.h" |
26 | |
27 | #define LENGTH (256UL*1024*1024) |
28 | #define PROTECTION (PROT_READ | PROT_WRITE) |
29 | |
30 | /* Only ia64 requires this */ |
31 | #ifdef __ia64__ |
32 | #define ADDR (void *)(0x8000000000000000UL) |
33 | #define FLAGS (MAP_SHARED | MAP_FIXED) |
34 | #else |
35 | #define ADDR (void *)(0x0UL) |
36 | #define FLAGS (MAP_SHARED) |
37 | #endif |
38 | |
39 | static void check_bytes(char *addr) |
40 | { |
41 | ksft_print_msg(msg: "First hex is %x\n" , *((unsigned int *)addr)); |
42 | } |
43 | |
44 | static void write_bytes(char *addr) |
45 | { |
46 | unsigned long i; |
47 | |
48 | for (i = 0; i < LENGTH; i++) |
49 | *(addr + i) = (char)i; |
50 | } |
51 | |
52 | static int read_bytes(char *addr) |
53 | { |
54 | unsigned long i; |
55 | |
56 | check_bytes(addr); |
57 | for (i = 0; i < LENGTH; i++) |
58 | if (*(addr + i) != (char)i) { |
59 | ksft_print_msg(msg: "Error: Mismatch at %lu\n" , i); |
60 | return 1; |
61 | } |
62 | return 0; |
63 | } |
64 | |
65 | int main(void) |
66 | { |
67 | void *addr; |
68 | int fd, ret; |
69 | |
70 | ksft_print_header(); |
71 | ksft_set_plan(plan: 1); |
72 | |
73 | fd = memfd_create("hugepage-mmap" , MFD_HUGETLB); |
74 | if (fd < 0) |
75 | ksft_exit_fail_msg(msg: "memfd_create() failed: %s\n" , strerror(errno)); |
76 | |
77 | addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, fd, 0); |
78 | if (addr == MAP_FAILED) { |
79 | close(fd); |
80 | ksft_exit_fail_msg(msg: "mmap(): %s\n" , strerror(errno)); |
81 | } |
82 | |
83 | ksft_print_msg(msg: "Returned address is %p\n" , addr); |
84 | check_bytes(addr); |
85 | write_bytes(addr); |
86 | ret = read_bytes(addr); |
87 | |
88 | munmap(addr, LENGTH); |
89 | close(fd); |
90 | |
91 | ksft_test_result(!ret, "Read same data\n" ); |
92 | |
93 | ksft_exit(!ret); |
94 | } |
95 | |