1  /* SPDX-License-Identifier: GPL-2.0 */
2  #ifndef _ASM_GENERIC_SECTIONS_H_
3  #define _ASM_GENERIC_SECTIONS_H_
4  
5  /* References to section boundaries */
6  
7  #include <linux/compiler.h>
8  #include <linux/types.h>
9  
10  /*
11   * Usage guidelines:
12   * _text, _data: architecture specific, don't use them in arch-independent code
13   * [_stext, _etext]: contains .text.* sections, may also contain .rodata.*
14   *                   and/or .init.* sections
15   * [_sdata, _edata]: contains .data.* sections, may also contain .rodata.*
16   *                   and/or .init.* sections.
17   * [__start_rodata, __end_rodata]: contains .rodata.* sections
18   * [__start_ro_after_init, __end_ro_after_init]:
19   *		     contains .data..ro_after_init section
20   * [__init_begin, __init_end]: contains .init.* sections, but .init.text.*
21   *                   may be out of this range on some architectures.
22   * [_sinittext, _einittext]: contains .init.text.* sections
23   * [__bss_start, __bss_stop]: contains BSS sections
24   *
25   * Following global variables are optional and may be unavailable on some
26   * architectures and/or kernel configurations.
27   *	_text, _data
28   *	__kprobes_text_start, __kprobes_text_end
29   *	__entry_text_start, __entry_text_end
30   *	__ctors_start, __ctors_end
31   *	__irqentry_text_start, __irqentry_text_end
32   *	__softirqentry_text_start, __softirqentry_text_end
33   *	__start_opd, __end_opd
34   */
35  extern char _text[], _stext[], _etext[];
36  extern char _data[], _sdata[], _edata[];
37  extern char __bss_start[], __bss_stop[];
38  extern char __init_begin[], __init_end[];
39  extern char _sinittext[], _einittext[];
40  extern char __start_ro_after_init[], __end_ro_after_init[];
41  extern char _end[];
42  extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[];
43  extern char __kprobes_text_start[], __kprobes_text_end[];
44  extern char __entry_text_start[], __entry_text_end[];
45  extern char __start_rodata[], __end_rodata[];
46  extern char __irqentry_text_start[], __irqentry_text_end[];
47  extern char __softirqentry_text_start[], __softirqentry_text_end[];
48  extern char __start_once[], __end_once[];
49  
50  /* Start and end of .ctors section - used for constructor calls. */
51  extern char __ctors_start[], __ctors_end[];
52  
53  /* Start and end of .opd section - used for function descriptors. */
54  extern char __start_opd[], __end_opd[];
55  
56  /* Start and end of instrumentation protected text section */
57  extern char __noinstr_text_start[], __noinstr_text_end[];
58  
59  extern __visible const void __nosave_begin, __nosave_end;
60  
61  /* Function descriptor handling (if any).  Override in asm/sections.h */
62  #ifdef CONFIG_HAVE_FUNCTION_DESCRIPTORS
63  void *dereference_function_descriptor(void *ptr);
64  void *dereference_kernel_function_descriptor(void *ptr);
65  #else
66  #define dereference_function_descriptor(p) ((void *)(p))
67  #define dereference_kernel_function_descriptor(p) ((void *)(p))
68  
69  /* An address is simply the address of the function. */
70  typedef struct {
71  	unsigned long addr;
72  } func_desc_t;
73  #endif
74  
have_function_descriptors(void)75  static inline bool have_function_descriptors(void)
76  {
77  	return IS_ENABLED(CONFIG_HAVE_FUNCTION_DESCRIPTORS);
78  }
79  
80  /**
81   * memory_contains - checks if an object is contained within a memory region
82   * @begin: virtual address of the beginning of the memory region
83   * @end: virtual address of the end of the memory region
84   * @virt: virtual address of the memory object
85   * @size: size of the memory object
86   *
87   * Returns: true if the object specified by @virt and @size is entirely
88   * contained within the memory region defined by @begin and @end, false
89   * otherwise.
90   */
memory_contains(void * begin,void * end,void * virt,size_t size)91  static inline bool memory_contains(void *begin, void *end, void *virt,
92  				   size_t size)
93  {
94  	return virt >= begin && virt + size <= end;
95  }
96  
97  /**
98   * memory_intersects - checks if the region occupied by an object intersects
99   *                     with another memory region
100   * @begin: virtual address of the beginning of the memory region
101   * @end: virtual address of the end of the memory region
102   * @virt: virtual address of the memory object
103   * @size: size of the memory object
104   *
105   * Returns: true if an object's memory region, specified by @virt and @size,
106   * intersects with the region specified by @begin and @end, false otherwise.
107   */
memory_intersects(void * begin,void * end,void * virt,size_t size)108  static inline bool memory_intersects(void *begin, void *end, void *virt,
109  				     size_t size)
110  {
111  	void *vend = virt + size;
112  
113  	if (virt < end && vend > begin)
114  		return true;
115  
116  	return false;
117  }
118  
119  /**
120   * init_section_contains - checks if an object is contained within the init
121   *                         section
122   * @virt: virtual address of the memory object
123   * @size: size of the memory object
124   *
125   * Returns: true if the object specified by @virt and @size is entirely
126   * contained within the init section, false otherwise.
127   */
init_section_contains(void * virt,size_t size)128  static inline bool init_section_contains(void *virt, size_t size)
129  {
130  	return memory_contains(__init_begin, __init_end, virt, size);
131  }
132  
133  /**
134   * init_section_intersects - checks if the region occupied by an object
135   *                           intersects with the init section
136   * @virt: virtual address of the memory object
137   * @size: size of the memory object
138   *
139   * Returns: true if an object's memory region, specified by @virt and @size,
140   * intersects with the init section, false otherwise.
141   */
init_section_intersects(void * virt,size_t size)142  static inline bool init_section_intersects(void *virt, size_t size)
143  {
144  	return memory_intersects(__init_begin, __init_end, virt, size);
145  }
146  
147  /**
148   * is_kernel_core_data - checks if the pointer address is located in the
149   *			 .data or .bss section
150   *
151   * @addr: address to check
152   *
153   * Returns: true if the address is located in .data or .bss, false otherwise.
154   * Note: On some archs it may return true for core RODATA, and false
155   *       for others. But will always be true for core RW data.
156   */
is_kernel_core_data(unsigned long addr)157  static inline bool is_kernel_core_data(unsigned long addr)
158  {
159  	if (addr >= (unsigned long)_sdata && addr < (unsigned long)_edata)
160  		return true;
161  
162  	if (addr >= (unsigned long)__bss_start &&
163  	    addr < (unsigned long)__bss_stop)
164  		return true;
165  
166  	return false;
167  }
168  
169  /**
170   * is_kernel_rodata - checks if the pointer address is located in the
171   *                    .rodata section
172   *
173   * @addr: address to check
174   *
175   * Returns: true if the address is located in .rodata, false otherwise.
176   */
is_kernel_rodata(unsigned long addr)177  static inline bool is_kernel_rodata(unsigned long addr)
178  {
179  	return addr >= (unsigned long)__start_rodata &&
180  	       addr < (unsigned long)__end_rodata;
181  }
182  
is_kernel_ro_after_init(unsigned long addr)183  static inline bool is_kernel_ro_after_init(unsigned long addr)
184  {
185  	return addr >= (unsigned long)__start_ro_after_init &&
186  	       addr < (unsigned long)__end_ro_after_init;
187  }
188  /**
189   * is_kernel_inittext - checks if the pointer address is located in the
190   *                      .init.text section
191   *
192   * @addr: address to check
193   *
194   * Returns: true if the address is located in .init.text, false otherwise.
195   */
is_kernel_inittext(unsigned long addr)196  static inline bool is_kernel_inittext(unsigned long addr)
197  {
198  	return addr >= (unsigned long)_sinittext &&
199  	       addr < (unsigned long)_einittext;
200  }
201  
202  /**
203   * __is_kernel_text - checks if the pointer address is located in the
204   *                    .text section
205   *
206   * @addr: address to check
207   *
208   * Returns: true if the address is located in .text, false otherwise.
209   * Note: an internal helper, only check the range of _stext to _etext.
210   */
__is_kernel_text(unsigned long addr)211  static inline bool __is_kernel_text(unsigned long addr)
212  {
213  	return addr >= (unsigned long)_stext &&
214  	       addr < (unsigned long)_etext;
215  }
216  
217  /**
218   * __is_kernel - checks if the pointer address is located in the kernel range
219   *
220   * @addr: address to check
221   *
222   * Returns: true if the address is located in the kernel range, false otherwise.
223   * Note: an internal helper, check the range of _stext to _end,
224   *       and range from __init_begin to __init_end, which can be outside
225   *       of the _stext to _end range.
226   */
__is_kernel(unsigned long addr)227  static inline bool __is_kernel(unsigned long addr)
228  {
229  	return ((addr >= (unsigned long)_stext &&
230  	         addr < (unsigned long)_end) ||
231  		(addr >= (unsigned long)__init_begin &&
232  		 addr < (unsigned long)__init_end));
233  }
234  
235  #endif /* _ASM_GENERIC_SECTIONS_H_ */
236