• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2024 Google LLC. All rights reserved.
4  * Author(s): Kalesh Singh <kaleshsingh@google.com>
5  */
6 
7 #ifndef PGSIZE_HELPER_H
8 #define PGSIZE_HELPER_H
9 
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 
14 #define MAX_PAGE_SIZE (64*1024)
15 
16 #if defined(__x86_64__)
17 /*
18  * Android emulates the userspace page size on some x86_64 emulators.
19  * The kernel page size still remains 4KiB (0x1000).
20  */
kernel_page_size(void)21 static inline size_t kernel_page_size(void)
22 {
23     return 0x1000;
24 }
25 #else
kernel_page_size(void)26 static inline size_t kernel_page_size(void)
27 {
28 	return getpagesize();
29 }
30 #endif
31 
32 /*
33  * NOTE: For all cases except Android x86_64 page size emulators,
34  * kernel_page_size == page_size, and the below macros are effectively
35  * no-ops.
36  */
37 
38 /* The number of kernel pages covered by size */
nr_kernel_pages(size_t size)39 static inline size_t nr_kernel_pages(size_t size)
40 {
41     return size / kernel_page_size();
42 }
43 
44 /* The number of kernel pages in a @nr_pages userspace pages */
nr_pgs_to_nr_kernel_pgs(size_t nr_pages)45 static size_t nr_pgs_to_nr_kernel_pgs(size_t nr_pages)
46 {
47     return nr_pages * nr_kernel_pages(getpagesize());
48 }
49 
50 /* The number of userspace pages in a @nr_pages kernel pages */
nr_kernel_pgs_to_nr_pgs(size_t nr_pages)51 static size_t nr_kernel_pgs_to_nr_pgs(size_t nr_pages)
52 {
53     return nr_pages / nr_kernel_pages(getpagesize());
54 }
55 
56 /*
57  * Make the backing file large enough to cover the last corresponding kernel page.
58  *
59  * This is an artifact of x86_64 page size emulation on Android, to handle
60  * file_map_fault's, which does allow access to the partial page after the end
61  * of the file.
62  */
63 #define SAFE_FILE_PRINTF_PGSIZE_EMULATION(file, str)                            \
64 do {                                                                            \
65     if (kernel_page_size() == getpagesize()) {                                  \
66         SAFE_FILE_PRINTF(file, str);                                            \
67     } else {                                                                    \
68         int str_len = strlen(str);                                              \
69         int nr_writes = ((kernel_page_size()                                    \
70                             * (nr_pgs_to_nr_kernel_pgs(1) - 1)) / str_len) + 1; \
71         int total_len = str_len * nr_writes;                                    \
72         char *buffer = SAFE_MALLOC(total_len + 1);                              \
73         for (int i = 0; i < nr_writes; i++)                                     \
74             strcat(buffer, str);                                                \
75         SAFE_FILE_PRINTF(file, buffer);                                         \
76         free(buffer);                                                           \
77     }                                                                           \
78 } while (0)
79 #endif /* PGSIZE_HELPER_H */
80