1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef __LINUX_PAGE_EXT_H 3 #define __LINUX_PAGE_EXT_H 4 5 #include <linux/types.h> 6 #include <linux/stacktrace.h> 7 #include <linux/stackdepot.h> 8 9 struct pglist_data; 10 11 /** 12 * struct page_ext_operations - per page_ext client operations 13 * @offset: Offset to the client's data within page_ext. Offset is returned to 14 * the client by page_ext_init. 15 * @size: The size of the client data within page_ext. 16 * @need: Function that returns true if client requires page_ext. 17 * @init: (optional) Called to initialize client once page_exts are allocated. 18 * @need_shared_flags: True when client is using shared page_ext->flags 19 * field. 20 * 21 * Each Page Extension client must define page_ext_operations in 22 * page_ext_ops array. 23 */ 24 struct page_ext_operations { 25 size_t offset; 26 size_t size; 27 bool (*need)(void); 28 void (*init)(void); 29 bool need_shared_flags; 30 }; 31 32 extern bool deferred_struct_pages; 33 34 #ifdef CONFIG_PAGE_EXTENSION 35 36 /* 37 * The page_ext_flags users must set need_shared_flags to true. 38 */ 39 enum page_ext_flags { 40 PAGE_EXT_OWNER, 41 PAGE_EXT_OWNER_ALLOCATED, 42 #if defined(CONFIG_PAGE_IDLE_FLAG) && !defined(CONFIG_64BIT) 43 PAGE_EXT_YOUNG, 44 PAGE_EXT_IDLE, 45 #endif 46 }; 47 48 /* 49 * Page Extension can be considered as an extended mem_map. 50 * A page_ext page is associated with every page descriptor. The 51 * page_ext helps us add more information about the page. 52 * All page_ext are allocated at boot or memory hotplug event, 53 * then the page_ext for pfn always exists. 54 */ 55 struct page_ext { 56 unsigned long flags; 57 }; 58 59 extern bool early_page_ext; 60 extern unsigned long page_ext_size; 61 extern void pgdat_page_ext_init(struct pglist_data *pgdat); 62 early_page_ext_enabled(void)63static inline bool early_page_ext_enabled(void) 64 { 65 return early_page_ext; 66 } 67 68 #ifdef CONFIG_SPARSEMEM page_ext_init_flatmem(void)69static inline void page_ext_init_flatmem(void) 70 { 71 } 72 extern void page_ext_init(void); page_ext_init_flatmem_late(void)73static inline void page_ext_init_flatmem_late(void) 74 { 75 } 76 #else 77 extern void page_ext_init_flatmem(void); 78 extern void page_ext_init_flatmem_late(void); page_ext_init(void)79static inline void page_ext_init(void) 80 { 81 } 82 #endif 83 84 extern struct page_ext *page_ext_get(struct page *page); 85 extern void page_ext_put(struct page_ext *page_ext); 86 page_ext_next(struct page_ext * curr)87static inline struct page_ext *page_ext_next(struct page_ext *curr) 88 { 89 void *next = curr; 90 next += page_ext_size; 91 return next; 92 } 93 94 #else /* !CONFIG_PAGE_EXTENSION */ 95 struct page_ext; 96 early_page_ext_enabled(void)97static inline bool early_page_ext_enabled(void) 98 { 99 return false; 100 } 101 pgdat_page_ext_init(struct pglist_data * pgdat)102static inline void pgdat_page_ext_init(struct pglist_data *pgdat) 103 { 104 } 105 page_ext_init(void)106static inline void page_ext_init(void) 107 { 108 } 109 page_ext_init_flatmem_late(void)110static inline void page_ext_init_flatmem_late(void) 111 { 112 } 113 page_ext_init_flatmem(void)114static inline void page_ext_init_flatmem(void) 115 { 116 } 117 page_ext_get(struct page * page)118static inline struct page_ext *page_ext_get(struct page *page) 119 { 120 return NULL; 121 } 122 page_ext_put(struct page_ext * page_ext)123static inline void page_ext_put(struct page_ext *page_ext) 124 { 125 } 126 #endif /* CONFIG_PAGE_EXTENSION */ 127 #endif /* __LINUX_PAGE_EXT_H */ 128