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)21static inline size_t kernel_page_size(void) 22 { 23 return 0x1000; 24 } 25 #else kernel_page_size(void)26static 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)39static 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)45static 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)51static 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