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