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