1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun #ifndef __LINUX_PAGE_EXT_H 3*4882a593Smuzhiyun #define __LINUX_PAGE_EXT_H 4*4882a593Smuzhiyun 5*4882a593Smuzhiyun #include <linux/types.h> 6*4882a593Smuzhiyun #include <linux/stacktrace.h> 7*4882a593Smuzhiyun #include <linux/stackdepot.h> 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun struct pglist_data; 10*4882a593Smuzhiyun struct page_ext_operations { 11*4882a593Smuzhiyun size_t offset; 12*4882a593Smuzhiyun size_t size; 13*4882a593Smuzhiyun bool (*need)(void); 14*4882a593Smuzhiyun void (*init)(void); 15*4882a593Smuzhiyun }; 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun #ifdef CONFIG_PAGE_EXTENSION 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun enum page_ext_flags { 20*4882a593Smuzhiyun PAGE_EXT_OWNER, 21*4882a593Smuzhiyun PAGE_EXT_OWNER_ALLOCATED, 22*4882a593Smuzhiyun #if defined(CONFIG_PAGE_PINNER) 23*4882a593Smuzhiyun /* page refcount was increased by GUP or follow_page(FOLL_GET) */ 24*4882a593Smuzhiyun PAGE_EXT_GET, 25*4882a593Smuzhiyun /* page migration failed */ 26*4882a593Smuzhiyun PAGE_EXT_PINNER_MIGRATION_FAILED, 27*4882a593Smuzhiyun #endif 28*4882a593Smuzhiyun #if defined(CONFIG_PAGE_IDLE_FLAG) && !defined(CONFIG_64BIT) 29*4882a593Smuzhiyun PAGE_EXT_YOUNG, 30*4882a593Smuzhiyun PAGE_EXT_IDLE, 31*4882a593Smuzhiyun #endif 32*4882a593Smuzhiyun }; 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun /* 35*4882a593Smuzhiyun * Page Extension can be considered as an extended mem_map. 36*4882a593Smuzhiyun * A page_ext page is associated with every page descriptor. The 37*4882a593Smuzhiyun * page_ext helps us add more information about the page. 38*4882a593Smuzhiyun * All page_ext are allocated at boot or memory hotplug event, 39*4882a593Smuzhiyun * then the page_ext for pfn always exists. 40*4882a593Smuzhiyun */ 41*4882a593Smuzhiyun struct page_ext { 42*4882a593Smuzhiyun unsigned long flags; 43*4882a593Smuzhiyun }; 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun extern unsigned long page_ext_size; 46*4882a593Smuzhiyun extern void pgdat_page_ext_init(struct pglist_data *pgdat); 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun #ifdef CONFIG_SPARSEMEM page_ext_init_flatmem(void)49*4882a593Smuzhiyunstatic inline void page_ext_init_flatmem(void) 50*4882a593Smuzhiyun { 51*4882a593Smuzhiyun } 52*4882a593Smuzhiyun extern void page_ext_init(void); page_ext_init_flatmem_late(void)53*4882a593Smuzhiyunstatic inline void page_ext_init_flatmem_late(void) 54*4882a593Smuzhiyun { 55*4882a593Smuzhiyun } 56*4882a593Smuzhiyun #else 57*4882a593Smuzhiyun extern void page_ext_init_flatmem(void); 58*4882a593Smuzhiyun extern void page_ext_init_flatmem_late(void); page_ext_init(void)59*4882a593Smuzhiyunstatic inline void page_ext_init(void) 60*4882a593Smuzhiyun { 61*4882a593Smuzhiyun } 62*4882a593Smuzhiyun #endif 63*4882a593Smuzhiyun struct page_ext *lookup_page_ext(const struct page *page); 64*4882a593Smuzhiyun extern struct page_ext *page_ext_get(struct page *page); 65*4882a593Smuzhiyun extern void page_ext_put(struct page_ext *page_ext); 66*4882a593Smuzhiyun page_ext_next(struct page_ext * curr)67*4882a593Smuzhiyunstatic inline struct page_ext *page_ext_next(struct page_ext *curr) 68*4882a593Smuzhiyun { 69*4882a593Smuzhiyun void *next = curr; 70*4882a593Smuzhiyun next += page_ext_size; 71*4882a593Smuzhiyun return next; 72*4882a593Smuzhiyun } 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun #else /* !CONFIG_PAGE_EXTENSION */ 75*4882a593Smuzhiyun struct page_ext; 76*4882a593Smuzhiyun pgdat_page_ext_init(struct pglist_data * pgdat)77*4882a593Smuzhiyunstatic inline void pgdat_page_ext_init(struct pglist_data *pgdat) 78*4882a593Smuzhiyun { 79*4882a593Smuzhiyun } 80*4882a593Smuzhiyun page_ext_init(void)81*4882a593Smuzhiyunstatic inline void page_ext_init(void) 82*4882a593Smuzhiyun { 83*4882a593Smuzhiyun } 84*4882a593Smuzhiyun page_ext_init_flatmem_late(void)85*4882a593Smuzhiyunstatic inline void page_ext_init_flatmem_late(void) 86*4882a593Smuzhiyun { 87*4882a593Smuzhiyun } 88*4882a593Smuzhiyun page_ext_init_flatmem(void)89*4882a593Smuzhiyunstatic inline void page_ext_init_flatmem(void) 90*4882a593Smuzhiyun { 91*4882a593Smuzhiyun } 92*4882a593Smuzhiyun page_ext_get(struct page * page)93*4882a593Smuzhiyunstatic inline struct page_ext *page_ext_get(struct page *page) 94*4882a593Smuzhiyun { 95*4882a593Smuzhiyun return NULL; 96*4882a593Smuzhiyun } 97*4882a593Smuzhiyun page_ext_put(struct page_ext * page_ext)98*4882a593Smuzhiyunstatic inline void page_ext_put(struct page_ext *page_ext) 99*4882a593Smuzhiyun { 100*4882a593Smuzhiyun } 101*4882a593Smuzhiyun #endif /* CONFIG_PAGE_EXTENSION */ 102*4882a593Smuzhiyun #endif /* __LINUX_PAGE_EXT_H */ 103