1 /*
2  * Copyright (c) 2020 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_KERNEL_MM_H
8 #define ZEPHYR_INCLUDE_KERNEL_MM_H
9 
10 #include <zephyr/sys/util.h>
11 #include <zephyr/toolchain.h>
12 #if defined(CONFIG_ARM_MMU) && defined(CONFIG_ARM64)
13 #include <zephyr/arch/arm64/arm_mem.h>
14 #endif /* CONFIG_ARM_MMU && CONFIG_ARM64 */
15 
16 #include <zephyr/kernel/internal/mm.h>
17 
18 /**
19  * @brief Kernel Memory Management
20  * @defgroup kernel_memory_management Kernel Memory Management
21  * @ingroup kernel_apis
22  * @{
23  */
24 
25 /**
26  * @name Caching mode definitions.
27  *
28  * These are mutually exclusive.
29  *
30  * @{
31  */
32 
33 /** No caching. Most drivers want this. */
34 #define K_MEM_CACHE_NONE	2
35 
36 /** Write-through caching. Used by certain drivers. */
37 #define K_MEM_CACHE_WT		1
38 
39 /** Full write-back caching. Any RAM mapped wants this. */
40 #define K_MEM_CACHE_WB		0
41 
42 /*
43  * ARM64 Specific flags are defined in arch/arm64/arm_mem.h,
44  * pay attention to be not conflicted when updating these flags.
45  */
46 
47 /** Reserved bits for cache modes in k_map() flags argument */
48 #define K_MEM_CACHE_MASK	(BIT(3) - 1)
49 
50 /** @} */
51 
52 /**
53  * @name Region permission attributes.
54  *
55  * Default is read-only, no user, no exec
56  *
57  * @{
58  */
59 
60 /** Region will have read/write access (and not read-only) */
61 #define K_MEM_PERM_RW		BIT(3)
62 
63 /** Region will be executable (normally forbidden) */
64 #define K_MEM_PERM_EXEC		BIT(4)
65 
66 /** Region will be accessible to user mode (normally supervisor-only) */
67 #define K_MEM_PERM_USER		BIT(5)
68 
69 /** @} */
70 
71 /**
72  * @name Region mapping behaviour attributes
73  *
74  * @{
75  */
76 
77 /** Region will be mapped to 1:1 virtual and physical address */
78 #define K_MEM_DIRECT_MAP	BIT(6)
79 
80 /** @} */
81 
82 #ifndef _ASMLANGUAGE
83 #include <stdint.h>
84 #include <stddef.h>
85 #include <inttypes.h>
86 
87 #ifdef __cplusplus
88 extern "C" {
89 #endif
90 
91 /**
92  * @name k_mem_map() control flags
93  *
94  * @{
95  */
96 
97 /**
98  * @brief The mapped region is not guaranteed to be zeroed.
99  *
100  * This may improve performance. The associated page frames may contain
101  * indeterminate data, zeroes, or even sensitive information.
102  *
103  * This may not be used with K_MEM_PERM_USER as there are no circumstances
104  * where this is safe.
105  */
106 #define K_MEM_MAP_UNINIT	BIT(16)
107 
108 /**
109  * Region will be pinned in memory and never paged
110  *
111  * Such memory is guaranteed to never produce a page fault due to page-outs
112  * or copy-on-write once the mapping call has returned. Physical page frames
113  * will be pre-fetched as necessary and pinned.
114  */
115 #define K_MEM_MAP_LOCK		BIT(17)
116 
117 /**
118  * Region will be unpaged i.e. not mapped into memory
119  *
120  * This is meant to be used by kernel code and not by application code.
121  *
122  * Corresponding memory address range will be set so no actual memory will
123  * be allocated initially. Allocation will happen through demand paging when
124  * addresses in that range are accessed. This is incompatible with
125  * K_MEM_MAP_LOCK.
126  *
127  * When this flag is specified, the phys argument to arch_mem_map()
128  * is interpreted as a backing store location value not a physical address.
129  * This is very similar to arch_mem_page_out() in that regard.
130  * Two special location values are defined: ARCH_UNPAGED_ANON_ZERO and
131  * ARCH_UNPAGED_ANON_UNINIT. Those are to be used with anonymous memory
132  * mappings for zeroed and uninitialized pages respectively.
133  */
134 #define K_MEM_MAP_UNPAGED	BIT(18)
135 
136 /** @} */
137 
138 /**
139  * Return the amount of free memory available
140  *
141  * The returned value will reflect how many free RAM page frames are available.
142  * If demand paging is enabled, it may still be possible to allocate more.
143  *
144  * The information reported by this function may go stale immediately if
145  * concurrent memory mappings or page-ins take place.
146  *
147  * @return Free physical RAM, in bytes
148  */
149 size_t k_mem_free_get(void);
150 
151 /**
152  * Map anonymous memory into Zephyr's address space
153  *
154  * This function effectively increases the data space available to Zephyr.
155  * The kernel will choose a base virtual address and return it to the caller.
156  * The memory will have access permissions for all contexts set per the
157  * provided flags argument.
158  *
159  * If user thread access control needs to be managed in any way, do not enable
160  * K_MEM_PERM_USER flags here; instead manage the region's permissions
161  * with memory domain APIs after the mapping has been established. Setting
162  * K_MEM_PERM_USER here will allow all user threads to access this memory
163  * which is usually undesirable.
164  *
165  * Unless K_MEM_MAP_UNINIT is used, the returned memory will be zeroed.
166  *
167  * The mapped region is not guaranteed to be physically contiguous in memory.
168  * Physically contiguous buffers should be allocated statically and pinned
169  * at build time.
170  *
171  * Pages mapped in this way have write-back cache settings.
172  *
173  * The returned virtual memory pointer will be page-aligned. The size
174  * parameter, and any base address for re-mapping purposes must be page-
175  * aligned.
176  *
177  * Note that the allocation includes two guard pages immediately before
178  * and after the requested region. The total size of the allocation will be
179  * the requested size plus the size of these two guard pages.
180  *
181  * Many K_MEM_MAP_* flags have been implemented to alter the behavior of this
182  * function, with details in the documentation for these flags.
183  *
184  * @param size Size of the memory mapping. This must be page-aligned.
185  * @param flags K_MEM_PERM_*, K_MEM_MAP_* control flags.
186  * @return The mapped memory location, or NULL if insufficient virtual address
187  *         space, insufficient physical memory to establish the mapping,
188  *         or insufficient memory for paging structures.
189  */
k_mem_map(size_t size,uint32_t flags)190 static inline void *k_mem_map(size_t size, uint32_t flags)
191 {
192 	return k_mem_map_phys_guard((uintptr_t)NULL, size, flags, true);
193 }
194 
195 #ifdef CONFIG_DEMAND_MAPPING
196 /**
197  * Create an unpaged mapping
198  *
199  * This maps backing-store "location" tokens into Zephyr's address space.
200  * Corresponding memory address range will be set so no actual memory will
201  * be allocated initially. Allocation will happen through demand paging when
202  * addresses in the mapped range are accessed.
203  *
204  * The kernel will choose a base virtual address and return it to the caller.
205  * The memory access permissions for all contexts will be set per the
206  * provided flags argument.
207  *
208  * If user thread access control needs to be managed in any way, do not enable
209  * K_MEM_PERM_USER flags here; instead manage the region's permissions
210  * with memory domain APIs after the mapping has been established. Setting
211  * K_MEM_PERM_USER here will allow all user threads to access this memory
212  * which is usually undesirable.
213  *
214  * This is incompatible with K_MEM_MAP_LOCK.
215  *
216  * The provided backing-store "location" token must be linearly incrementable
217  * by a page size across the entire mapping.
218  *
219  * Allocated pages will have write-back cache settings.
220  *
221  * The returned virtual memory pointer will be page-aligned. The size
222  * parameter, and any base address for re-mapping purposes must be page-
223  * aligned.
224  *
225  * Note that the allocation includes two guard pages immediately before
226  * and after the requested region. The total size of the allocation will be
227  * the requested size plus the size of these two guard pages.
228  *
229  * @param location Backing store initial location token
230  * @param size Size of the memory mapping. This must be page-aligned.
231  * @param flags K_MEM_PERM_*, K_MEM_MAP_* control flags.
232  * @return The mapping location, or NULL if insufficient virtual address
233  *         space to establish the mapping, or insufficient memory for paging
234  *         structures.
235  */
k_mem_map_unpaged(uintptr_t location,size_t size,uint32_t flags)236 static inline void *k_mem_map_unpaged(uintptr_t location, size_t size, uint32_t flags)
237 {
238 	flags |= K_MEM_MAP_UNPAGED;
239 	return k_mem_map_phys_guard(location, size, flags, false);
240 }
241 #endif
242 
243 /**
244  * Un-map mapped memory
245  *
246  * This removes a memory mapping for the provided page-aligned region.
247  * Associated page frames will be free and the kernel may re-use the associated
248  * virtual address region. Any paged out data pages may be discarded.
249  *
250  * Calling this function on a region which was not mapped to begin with is
251  * undefined behavior.
252  *
253  * @param addr Page-aligned memory region base virtual address
254  * @param size Page-aligned memory region size
255  */
k_mem_unmap(void * addr,size_t size)256 static inline void k_mem_unmap(void *addr, size_t size)
257 {
258 	k_mem_unmap_phys_guard(addr, size, true);
259 }
260 
261 /**
262  * Modify memory mapping attribute flags
263  *
264  * This updates caching, access and control flags for the provided
265  * page-aligned memory region.
266  *
267  * Calling this function on a region which was not mapped to begin with is
268  * undefined behavior. However system memory implicitly mapped at boot time
269  * is supported.
270  *
271  * @param addr Page-aligned memory region base virtual address
272  * @param size Page-aligned memory region size
273  * @param flags K_MEM_PERM_*, K_MEM_MAP_* control flags.
274  * @return 0 for success, negative error code otherwise.
275  */
276 int k_mem_update_flags(void *addr, size_t size, uint32_t flags);
277 
278 /**
279  * Given an arbitrary region, provide a aligned region that covers it
280  *
281  * The returned region will have both its base address and size aligned
282  * to the provided alignment value.
283  *
284  * @param[out] aligned_addr Aligned address
285  * @param[out] aligned_size Aligned region size
286  * @param[in]  addr Region base address
287  * @param[in]  size Region size
288  * @param[in]  align What to align the address and size to
289  * @retval offset between aligned_addr and addr
290  */
291 size_t k_mem_region_align(uintptr_t *aligned_addr, size_t *aligned_size,
292 			  uintptr_t addr, size_t size, size_t align);
293 
294 #ifdef __cplusplus
295 }
296 #endif
297 
298 /** @} */
299 
300 #endif /* !_ASMLANGUAGE */
301 #endif /* ZEPHYR_INCLUDE_KERNEL_MM_H */
302