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