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