1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 2eefa864bSJoonsoo Kim #ifndef __LINUX_PAGE_EXT_H 3eefa864bSJoonsoo Kim #define __LINUX_PAGE_EXT_H 4eefa864bSJoonsoo Kim 548c96a36SJoonsoo Kim #include <linux/types.h> 648c96a36SJoonsoo Kim #include <linux/stacktrace.h> 7f2ca0b55SJoonsoo Kim #include <linux/stackdepot.h> 848c96a36SJoonsoo Kim 9eefa864bSJoonsoo Kim struct pglist_data; 106189eb82SPasha Tatashin 11*67311a36SKemeng Shi #ifdef CONFIG_PAGE_EXTENSION 126189eb82SPasha Tatashin /** 136189eb82SPasha Tatashin * struct page_ext_operations - per page_ext client operations 146189eb82SPasha Tatashin * @offset: Offset to the client's data within page_ext. Offset is returned to 156189eb82SPasha Tatashin * the client by page_ext_init. 166189eb82SPasha Tatashin * @size: The size of the client data within page_ext. 176189eb82SPasha Tatashin * @need: Function that returns true if client requires page_ext. 186189eb82SPasha Tatashin * @init: (optional) Called to initialize client once page_exts are allocated. 196189eb82SPasha Tatashin * @need_shared_flags: True when client is using shared page_ext->flags 206189eb82SPasha Tatashin * field. 216189eb82SPasha Tatashin * 226189eb82SPasha Tatashin * Each Page Extension client must define page_ext_operations in 236189eb82SPasha Tatashin * page_ext_ops array. 246189eb82SPasha Tatashin */ 25eefa864bSJoonsoo Kim struct page_ext_operations { 26980ac167SJoonsoo Kim size_t offset; 27980ac167SJoonsoo Kim size_t size; 28eefa864bSJoonsoo Kim bool (*need)(void); 29eefa864bSJoonsoo Kim void (*init)(void); 306189eb82SPasha Tatashin bool need_shared_flags; 31eefa864bSJoonsoo Kim }; 32eefa864bSJoonsoo Kim 336189eb82SPasha Tatashin /* 346189eb82SPasha Tatashin * The page_ext_flags users must set need_shared_flags to true. 356189eb82SPasha Tatashin */ 36e30825f1SJoonsoo Kim enum page_ext_flags { 3748c96a36SJoonsoo Kim PAGE_EXT_OWNER, 38fdf3bf80SVlastimil Babka PAGE_EXT_OWNER_ALLOCATED, 391c676e0dSSeongJae Park #if defined(CONFIG_PAGE_IDLE_FLAG) && !defined(CONFIG_64BIT) 4033c3fc71SVladimir Davydov PAGE_EXT_YOUNG, 4133c3fc71SVladimir Davydov PAGE_EXT_IDLE, 4233c3fc71SVladimir Davydov #endif 43e30825f1SJoonsoo Kim }; 44e30825f1SJoonsoo Kim 45e30825f1SJoonsoo Kim /* 46eefa864bSJoonsoo Kim * Page Extension can be considered as an extended mem_map. 47eefa864bSJoonsoo Kim * A page_ext page is associated with every page descriptor. The 48eefa864bSJoonsoo Kim * page_ext helps us add more information about the page. 49eefa864bSJoonsoo Kim * All page_ext are allocated at boot or memory hotplug event, 50eefa864bSJoonsoo Kim * then the page_ext for pfn always exists. 51eefa864bSJoonsoo Kim */ 52eefa864bSJoonsoo Kim struct page_ext { 53eefa864bSJoonsoo Kim unsigned long flags; 54eefa864bSJoonsoo Kim }; 55eefa864bSJoonsoo Kim 56c4f20f14SLi Zhe extern bool early_page_ext; 575556cfe8SVlastimil Babka extern unsigned long page_ext_size; 58eefa864bSJoonsoo Kim extern void pgdat_page_ext_init(struct pglist_data *pgdat); 59eefa864bSJoonsoo Kim early_page_ext_enabled(void)60c4f20f14SLi Zhestatic inline bool early_page_ext_enabled(void) 61c4f20f14SLi Zhe { 62c4f20f14SLi Zhe return early_page_ext; 63c4f20f14SLi Zhe } 64c4f20f14SLi Zhe 65eefa864bSJoonsoo Kim #ifdef CONFIG_SPARSEMEM page_ext_init_flatmem(void)66eefa864bSJoonsoo Kimstatic inline void page_ext_init_flatmem(void) 67eefa864bSJoonsoo Kim { 68eefa864bSJoonsoo Kim } 69eefa864bSJoonsoo Kim extern void page_ext_init(void); page_ext_init_flatmem_late(void)707fb7ab6dSZhenhua Huangstatic inline void page_ext_init_flatmem_late(void) 717fb7ab6dSZhenhua Huang { 727fb7ab6dSZhenhua Huang } 73eefa864bSJoonsoo Kim #else 74eefa864bSJoonsoo Kim extern void page_ext_init_flatmem(void); 757fb7ab6dSZhenhua Huang extern void page_ext_init_flatmem_late(void); page_ext_init(void)76eefa864bSJoonsoo Kimstatic inline void page_ext_init(void) 77eefa864bSJoonsoo Kim { 78eefa864bSJoonsoo Kim } 79eefa864bSJoonsoo Kim #endif 80eefa864bSJoonsoo Kim 81b1d5488aSCharan Teja Kalla extern struct page_ext *page_ext_get(struct page *page); 82b1d5488aSCharan Teja Kalla extern void page_ext_put(struct page_ext *page_ext); 83eefa864bSJoonsoo Kim page_ext_data(struct page_ext * page_ext,struct page_ext_operations * ops)84c0a5d93aSKemeng Shistatic inline void *page_ext_data(struct page_ext *page_ext, 85c0a5d93aSKemeng Shi struct page_ext_operations *ops) 86c0a5d93aSKemeng Shi { 87c0a5d93aSKemeng Shi return (void *)(page_ext) + ops->offset; 88c0a5d93aSKemeng Shi } 89c0a5d93aSKemeng Shi page_ext_next(struct page_ext * curr)905556cfe8SVlastimil Babkastatic inline struct page_ext *page_ext_next(struct page_ext *curr) 915556cfe8SVlastimil Babka { 925556cfe8SVlastimil Babka void *next = curr; 935556cfe8SVlastimil Babka next += page_ext_size; 945556cfe8SVlastimil Babka return next; 955556cfe8SVlastimil Babka } 965556cfe8SVlastimil Babka 97eefa864bSJoonsoo Kim #else /* !CONFIG_PAGE_EXTENSION */ 98eefa864bSJoonsoo Kim struct page_ext; 99eefa864bSJoonsoo Kim early_page_ext_enabled(void)100c4f20f14SLi Zhestatic inline bool early_page_ext_enabled(void) 101c4f20f14SLi Zhe { 102c4f20f14SLi Zhe return false; 103c4f20f14SLi Zhe } 104c4f20f14SLi Zhe pgdat_page_ext_init(struct pglist_data * pgdat)105eefa864bSJoonsoo Kimstatic inline void pgdat_page_ext_init(struct pglist_data *pgdat) 106eefa864bSJoonsoo Kim { 107eefa864bSJoonsoo Kim } 108eefa864bSJoonsoo Kim page_ext_init(void)109eefa864bSJoonsoo Kimstatic inline void page_ext_init(void) 110eefa864bSJoonsoo Kim { 111eefa864bSJoonsoo Kim } 112eefa864bSJoonsoo Kim page_ext_init_flatmem_late(void)1137fb7ab6dSZhenhua Huangstatic inline void page_ext_init_flatmem_late(void) 1147fb7ab6dSZhenhua Huang { 1157fb7ab6dSZhenhua Huang } 1167fb7ab6dSZhenhua Huang page_ext_init_flatmem(void)117eefa864bSJoonsoo Kimstatic inline void page_ext_init_flatmem(void) 118eefa864bSJoonsoo Kim { 119eefa864bSJoonsoo Kim } 120b1d5488aSCharan Teja Kalla page_ext_get(struct page * page)121b1d5488aSCharan Teja Kallastatic inline struct page_ext *page_ext_get(struct page *page) 122b1d5488aSCharan Teja Kalla { 123b1d5488aSCharan Teja Kalla return NULL; 124b1d5488aSCharan Teja Kalla } 125b1d5488aSCharan Teja Kalla page_ext_put(struct page_ext * page_ext)126b1d5488aSCharan Teja Kallastatic inline void page_ext_put(struct page_ext *page_ext) 127b1d5488aSCharan Teja Kalla { 128b1d5488aSCharan Teja Kalla } 129eefa864bSJoonsoo Kim #endif /* CONFIG_PAGE_EXTENSION */ 130eefa864bSJoonsoo Kim #endif /* __LINUX_PAGE_EXT_H */ 131