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 8 struct pglist_data; 9 10 #ifdef CONFIG_PAGE_EXTENSION 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 /* 33 * The page_ext_flags users must set need_shared_flags to true. 34 */ 35 enum page_ext_flags { 36 PAGE_EXT_OWNER, 37 PAGE_EXT_OWNER_ALLOCATED, 38 #if defined(CONFIG_PAGE_IDLE_FLAG) && !defined(CONFIG_64BIT) 39 PAGE_EXT_YOUNG, 40 PAGE_EXT_IDLE, 41 #endif 42 }; 43 44 /* 45 * Page Extension can be considered as an extended mem_map. 46 * A page_ext page is associated with every page descriptor. The 47 * page_ext helps us add more information about the page. 48 * All page_ext are allocated at boot or memory hotplug event, 49 * then the page_ext for pfn always exists. 50 */ 51 struct page_ext { 52 unsigned long flags; 53 }; 54 55 extern bool early_page_ext; 56 extern unsigned long page_ext_size; 57 extern void pgdat_page_ext_init(struct pglist_data *pgdat); 58 early_page_ext_enabled(void)59static inline bool early_page_ext_enabled(void) 60 { 61 return early_page_ext; 62 } 63 64 #ifdef CONFIG_SPARSEMEM page_ext_init_flatmem(void)65static inline void page_ext_init_flatmem(void) 66 { 67 } 68 extern void page_ext_init(void); page_ext_init_flatmem_late(void)69static inline void page_ext_init_flatmem_late(void) 70 { 71 } 72 #else 73 extern void page_ext_init_flatmem(void); 74 extern void page_ext_init_flatmem_late(void); page_ext_init(void)75static inline void page_ext_init(void) 76 { 77 } 78 #endif 79 80 extern struct page_ext *page_ext_get(const struct page *page); 81 extern void page_ext_put(struct page_ext *page_ext); 82 page_ext_data(struct page_ext * page_ext,struct page_ext_operations * ops)83static inline void *page_ext_data(struct page_ext *page_ext, 84 struct page_ext_operations *ops) 85 { 86 return (void *)(page_ext) + ops->offset; 87 } 88 page_ext_next(struct page_ext * curr)89static inline struct page_ext *page_ext_next(struct page_ext *curr) 90 { 91 void *next = curr; 92 next += page_ext_size; 93 return next; 94 } 95 96 #else /* !CONFIG_PAGE_EXTENSION */ 97 struct page_ext; 98 early_page_ext_enabled(void)99static inline bool early_page_ext_enabled(void) 100 { 101 return false; 102 } 103 pgdat_page_ext_init(struct pglist_data * pgdat)104static inline void pgdat_page_ext_init(struct pglist_data *pgdat) 105 { 106 } 107 page_ext_init(void)108static inline void page_ext_init(void) 109 { 110 } 111 page_ext_init_flatmem_late(void)112static inline void page_ext_init_flatmem_late(void) 113 { 114 } 115 page_ext_init_flatmem(void)116static inline void page_ext_init_flatmem(void) 117 { 118 } 119 page_ext_get(const struct page * page)120static inline struct page_ext *page_ext_get(const struct page *page) 121 { 122 return NULL; 123 } 124 page_ext_put(struct page_ext * page_ext)125static inline void page_ext_put(struct page_ext *page_ext) 126 { 127 } 128 #endif /* CONFIG_PAGE_EXTENSION */ 129 #endif /* __LINUX_PAGE_EXT_H */ 130