xref: /openbmc/linux/include/linux/page_ext.h (revision 67311a36)
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 Zhe static 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 Kim static 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 Huang static 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 Kim static 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 Shi static 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 Babka static 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 Zhe static 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 Kim static inline void pgdat_page_ext_init(struct pglist_data *pgdat)
106eefa864bSJoonsoo Kim {
107eefa864bSJoonsoo Kim }
108eefa864bSJoonsoo Kim 
page_ext_init(void)109eefa864bSJoonsoo Kim static inline void page_ext_init(void)
110eefa864bSJoonsoo Kim {
111eefa864bSJoonsoo Kim }
112eefa864bSJoonsoo Kim 
page_ext_init_flatmem_late(void)1137fb7ab6dSZhenhua Huang static inline void page_ext_init_flatmem_late(void)
1147fb7ab6dSZhenhua Huang {
1157fb7ab6dSZhenhua Huang }
1167fb7ab6dSZhenhua Huang 
page_ext_init_flatmem(void)117eefa864bSJoonsoo Kim static inline void page_ext_init_flatmem(void)
118eefa864bSJoonsoo Kim {
119eefa864bSJoonsoo Kim }
120b1d5488aSCharan Teja Kalla 
page_ext_get(struct page * page)121b1d5488aSCharan Teja Kalla static 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 Kalla static 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