Line data Source code
1 1 : /*
2 : * Copyright (c) 2021 Intel Corporation.
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : /**
8 : * @file
9 : * @brief Memory Management Driver APIs
10 : *
11 : * This contains APIs for a system-wide memory management
12 : * driver. Only one instance is permitted on the system.
13 : */
14 :
15 : #ifndef ZEPHYR_INCLUDE_DRIVERS_SYSTEM_MM_H_
16 : #define ZEPHYR_INCLUDE_DRIVERS_SYSTEM_MM_H_
17 :
18 : #include <zephyr/types.h>
19 :
20 : #ifndef _ASMLANGUAGE
21 :
22 : #ifdef __cplusplus
23 : extern "C" {
24 : #endif
25 :
26 : /**
27 : * @brief Memory Management Driver APIs
28 : * @defgroup mm_drv_apis Memory Management Driver APIs
29 : *
30 : * This contains APIs for a system-wide memory management
31 : * driver. Only one instance is permitted on the system.
32 : *
33 : * @ingroup memory_management
34 : * @{
35 : */
36 :
37 : /**
38 : * @name Caching mode definitions.
39 : *
40 : * These are mutually exclusive.
41 : *
42 : * @{
43 : */
44 :
45 : /** No caching */
46 1 : #define SYS_MM_MEM_CACHE_NONE 2
47 :
48 : /** Write-through caching */
49 1 : #define SYS_MM_MEM_CACHE_WT 1
50 :
51 : /** Full write-back caching */
52 1 : #define SYS_MM_MEM_CACHE_WB 0
53 :
54 : /** Reserved bits for cache modes */
55 1 : #define SYS_MM_MEM_CACHE_MASK (BIT(3) - 1)
56 :
57 : /**
58 : * @brief Represents an available memory region.
59 : *
60 : * A memory region that can be used by allocators. Driver defined
61 : * attributes can be used to guide the proper usage of each region.
62 : */
63 1 : struct sys_mm_drv_region {
64 1 : void *addr; /**< @brief Address of the memory region */
65 1 : size_t size; /**< @brief Size of the memory region */
66 1 : uint32_t attr; /**< @brief Driver defined attributes of the memory region */
67 : };
68 :
69 : /**
70 : * @}
71 : */
72 :
73 : /**
74 : * @name Region permission attributes.
75 : *
76 : * Default should be read-only, no user, no exec.
77 : *
78 : * @{
79 : */
80 :
81 : /** Region will have read/write access (and not read-only) */
82 1 : #define SYS_MM_MEM_PERM_RW BIT(3)
83 :
84 : /** Region will be executable (normally forbidden) */
85 1 : #define SYS_MM_MEM_PERM_EXEC BIT(4)
86 :
87 : /** Region will be accessible to user mode (normally supervisor-only) */
88 1 : #define SYS_MM_MEM_PERM_USER BIT(5)
89 :
90 : /**
91 : * @}
92 : */
93 :
94 : /**
95 : * @name Memory Mapping and Unmapping
96 : *
97 : * On mapping and unmapping of memory.
98 : *
99 : * @{
100 : */
101 :
102 : /**
103 : * @brief Map one physical page into the virtual address space
104 : *
105 : * This maps one physical page into the virtual address space.
106 : * Behavior when providing unaligned address is undefined, this
107 : * is assumed to be page aligned.
108 : *
109 : * The memory range itself is never accessed by this operation.
110 : *
111 : * This API must be safe to call in ISRs or exception handlers. Calls
112 : * to this API are assumed to be serialized.
113 : *
114 : * @param virt Page-aligned destination virtual address to map
115 : * @param phys Page-aligned source physical address to map
116 : * @param flags Caching, access and control flags, see SYS_MM_MEM_* macros
117 : *
118 : * @retval 0 if successful
119 : * @retval -EINVAL if invalid arguments are provided
120 : * @retval -EFAULT if virtual address has already been mapped
121 : */
122 1 : int sys_mm_drv_map_page(void *virt, uintptr_t phys, uint32_t flags);
123 :
124 : /**
125 : * @brief Map one physical page into the virtual address space with region check
126 : *
127 : * This maps one physical page into the virtual address space by calling
128 : * sys_mm_drv_map_page. Refer to sys_mm_drv_map_page for references
129 : *
130 : * Before call it performs a safety check by verifying if the mapped virtual memory page
131 : * fits into a given virtual region
132 : */
133 1 : int sys_mm_drv_map_page_safe(const struct sys_mm_drv_region *virtual_region,
134 : void *virt, uintptr_t phys, uint32_t flags);
135 :
136 : /**
137 : * @brief Map a region of physical memory into the virtual address space
138 : *
139 : * This maps a region of physical memory into the virtual address space.
140 : * Behavior when providing unaligned addresses/sizes is undefined, these
141 : * are assumed to be page aligned.
142 : *
143 : * The memory range itself is never accessed by this operation.
144 : *
145 : * This API must be safe to call in ISRs or exception handlers. Calls
146 : * to this API are assumed to be serialized.
147 : *
148 : * @param virt Page-aligned destination virtual address to map
149 : * @param phys Page-aligned source physical address to map
150 : * @param size Page-aligned size of the mapped memory region in bytes
151 : * @param flags Caching, access and control flags, see SYS_MM_MEM_* macros
152 : *
153 : * @retval 0 if successful
154 : * @retval -EINVAL if invalid arguments are provided
155 : * @retval -EFAULT if any virtual addresses have already been mapped
156 : */
157 1 : int sys_mm_drv_map_region(void *virt, uintptr_t phys,
158 : size_t size, uint32_t flags);
159 :
160 : /**
161 : * @brief Map a region of physical memory into the virtual address space with region check
162 : *
163 : * This maps a region of physical memory into the virtual address space by calling
164 : * sys_mm_drv_map_region. Refer to sys_mm_drv_map_region for references
165 : *
166 : * Before call it performs a safety check by verifying if the mapped virtual memory pages
167 : * fit into a given virtual region
168 : */
169 1 : int sys_mm_drv_map_region_safe(const struct sys_mm_drv_region *virtual_region,
170 : void *virt, uintptr_t phys, size_t size,
171 : uint32_t flags);
172 :
173 : /**
174 : * @brief Map an array of physical memory into the virtual address space
175 : *
176 : * This maps an array of physical pages into a continuous virtual address
177 : * space. Behavior when providing unaligned addresses is undefined, these
178 : * are assumed to be page aligned.
179 : *
180 : * The physical memory pages are never accessed by this operation.
181 : *
182 : * This API must be safe to call in ISRs or exception handlers. Calls
183 : * to this API are assumed to be serialized.
184 : *
185 : * @param virt Page-aligned destination virtual address to map
186 : * @param phys Array of pge-aligned source physical address to map
187 : * @param cnt Number of elements in the physical page array
188 : * @param flags Caching, access and control flags, see SYS_MM_MEM_* macros
189 : *
190 : * @retval 0 if successful
191 : * @retval -EINVAL if invalid arguments are provided
192 : * @retval -EFAULT if any virtual addresses have already been mapped
193 : */
194 1 : int sys_mm_drv_map_array(void *virt, uintptr_t *phys,
195 : size_t cnt, uint32_t flags);
196 :
197 : /**
198 : * @brief Remove mapping for one page of the provided virtual address
199 : *
200 : * This unmaps one page from the virtual address space.
201 : *
202 : * When this completes, the relevant translation table entries will be
203 : * updated as if no mapping was ever made for that memory page. No previous
204 : * context needs to be preserved. This function must update mapping in
205 : * all active translation tables.
206 : *
207 : * Behavior when providing unaligned address is undefined, this
208 : * is assumed to be page aligned.
209 : *
210 : * Implementations must invalidate translation caching as necessary.
211 : *
212 : * @param virt Page-aligned virtual address to un-map
213 : *
214 : * @retval 0 if successful
215 : * @retval -EINVAL if invalid arguments are provided
216 : * @retval -EFAULT if virtual address is not mapped
217 : */
218 1 : int sys_mm_drv_unmap_page(void *virt);
219 :
220 : /**
221 : * @brief Remove mappings for a provided virtual address range
222 : *
223 : * This unmaps pages in the provided virtual address range.
224 : *
225 : * When this completes, the relevant translation table entries will be
226 : * updated as if no mapping was ever made for that memory range. No previous
227 : * context needs to be preserved. This function must update mappings in
228 : * all active translation tables.
229 : *
230 : * Behavior when providing unaligned address is undefined, this
231 : * is assumed to be page aligned.
232 : *
233 : * Implementations must invalidate translation caching as necessary.
234 : *
235 : * @param virt Page-aligned base virtual address to un-map
236 : * @param size Page-aligned region size
237 : *
238 : * @retval 0 if successful
239 : * @retval -EINVAL if invalid arguments are provided
240 : * @retval -EFAULT if virtual address is not mapped
241 : */
242 1 : int sys_mm_drv_unmap_region(void *virt, size_t size);
243 :
244 : /**
245 : * @brief Remap virtual pages into new address
246 : *
247 : * This remaps a virtual memory region starting at @p virt_old
248 : * of size @p size into a new virtual memory region starting at
249 : * @p virt_new. In other words, physical memory at @p virt_old is
250 : * remapped to appear at @p virt_new. Both addresses must be page
251 : * aligned and valid.
252 : *
253 : * Note that the virtual memory at both the old and new addresses
254 : * must be unmapped in the memory domains of any runnable Zephyr
255 : * thread as this does not deal with memory domains.
256 : *
257 : * Note that overlapping of old and new virtual memory regions
258 : * is usually not supported for simpler implementation. Refer to
259 : * the actual driver to make sure if overlapping is allowed.
260 : *
261 : * @param virt_old Page-aligned base virtual address of existing memory
262 : * @param size Page-aligned size of the mapped memory region in bytes
263 : * @param virt_new Page-aligned base virtual address to which to remap
264 : * the memory
265 : *
266 : * @retval 0 if successful
267 : * @retval -EINVAL if invalid arguments are provided
268 : * @retval -EFAULT if old virtual addresses are not all mapped or
269 : * new virtual addresses are not all unmapped
270 : */
271 1 : int sys_mm_drv_remap_region(void *virt_old, size_t size, void *virt_new);
272 :
273 : /**
274 : * @}
275 : */
276 :
277 : /**
278 : * @name Memory Moving
279 : *
280 : * On moving already mapped memory.
281 : *
282 : * @{
283 : */
284 :
285 : /**
286 : * @brief Physically move memory, with copy
287 : *
288 : * This maps a region of physical memory into the new virtual address space
289 : * (@p virt_new), and copy region of size @p size from the old virtual
290 : * address space (@p virt_old). The new virtual memory region is mapped
291 : * from physical memory starting at @p phys_new of size @p size.
292 : *
293 : * Behavior when providing unaligned addresses/sizes is undefined, these
294 : * are assumed to be page aligned.
295 : *
296 : * Note that the virtual memory at both the old and new addresses
297 : * must be unmapped in the memory domains of any runnable Zephyr
298 : * thread as this does not deal with memory domains.
299 : *
300 : * Note that overlapping of old and new virtual memory regions
301 : * is usually not supported for simpler implementation. Refer to
302 : * the actual driver to make sure if overlapping is allowed.
303 : *
304 : * @param virt_old Page-aligned base virtual address of existing memory
305 : * @param size Page-aligned size of the mapped memory region in bytes
306 : * @param virt_new Page-aligned base virtual address to which to map
307 : * new physical pages
308 : * @param phys_new Page-aligned base physical address to contain
309 : * the moved memory
310 : *
311 : * @retval 0 if successful
312 : * @retval -EINVAL if invalid arguments are provided
313 : * @retval -EFAULT if old virtual addresses are not all mapped or
314 : * new virtual addresses are not all unmapped
315 : */
316 1 : int sys_mm_drv_move_region(void *virt_old, size_t size, void *virt_new,
317 : uintptr_t phys_new);
318 :
319 : /**
320 : * @brief Physically move memory, with copy
321 : *
322 : * This maps a region of physical memory into the new virtual address space
323 : * (@p virt_new), and copy region of size @p size from the old virtual
324 : * address space (@p virt_old). The new virtual memory region is mapped
325 : * from an array of physical pages.
326 : *
327 : * Behavior when providing unaligned addresses/sizes is undefined, these
328 : * are assumed to be page aligned.
329 : *
330 : * Note that the virtual memory at both the old and new addresses
331 : * must be unmapped in the memory domains of any runnable Zephyr
332 : * thread as this does not deal with memory domains.
333 : *
334 : * Note that overlapping of old and new virtual memory regions
335 : * is usually not supported for simpler implementation. Refer to
336 : * the actual driver to make sure if overlapping is allowed.
337 : *
338 : * @param virt_old Page-aligned base virtual address of existing memory
339 : * @param size Page-aligned size of the mapped memory region in bytes
340 : * @param virt_new Page-aligned base virtual address to which to map
341 : * new physical pages
342 : * @param phys_new Array of page-aligned physical address to contain
343 : * the moved memory
344 : * @param phys_cnt Number of elements in the physical page array
345 : *
346 : * @retval 0 if successful
347 : * @retval -EINVAL if invalid arguments are provided
348 : * @retval -EFAULT if old virtual addresses are not all mapped or
349 : * new virtual addresses are not all unmapped
350 : */
351 1 : int sys_mm_drv_move_array(void *virt_old, size_t size, void *virt_new,
352 : uintptr_t *phys_new, size_t phys_cnt);
353 :
354 : /**
355 : * @}
356 : */
357 :
358 : /**
359 : * @name Memory Mapping Attributes
360 : *
361 : * On manipulating attributes of already mapped memory.
362 : *
363 : * @{
364 : */
365 :
366 : /**
367 : * @brief Update memory page flags
368 : *
369 : * This changes the attributes of physical memory page which is already
370 : * mapped to a virtual address. This is useful when use case of
371 : * specific memory region changes.
372 : * E.g. when the library/module code is copied to the memory then
373 : * it needs to be read-write and after it has already
374 : * been copied and library/module code is ready to be executed then
375 : * attributes need to be changed to read-only/executable.
376 : * Calling this API must not cause losing memory contents.
377 : *
378 : * @param virt Page-aligned virtual address to be updated
379 : * @param flags Caching, access and control flags, see SYS_MM_MEM_* macros
380 : *
381 : * @retval 0 if successful
382 : * @retval -EINVAL if invalid arguments are provided
383 : * @retval -EFAULT if virtual addresses is not mapped
384 : */
385 :
386 1 : int sys_mm_drv_update_page_flags(void *virt, uint32_t flags);
387 :
388 : /**
389 : * @brief Update memory region flags
390 : *
391 : * This changes the attributes of physical memory which is already
392 : * mapped to a virtual address. This is useful when use case of
393 : * specific memory region changes.
394 : * E.g. when the library/module code is copied to the memory then
395 : * it needs to be read-write and after it has already
396 : * been copied and library/module code is ready to be executed then
397 : * attributes need to be changed to read-only/executable.
398 : * Calling this API must not cause losing memory contents.
399 : *
400 : * @param virt Page-aligned virtual address to be updated
401 : * @param size Page-aligned size of the mapped memory region in bytes
402 : * @param flags Caching, access and control flags, see SYS_MM_MEM_* macros
403 : *
404 : * @retval 0 if successful
405 : * @retval -EINVAL if invalid arguments are provided
406 : * @retval -EFAULT if virtual addresses is not mapped
407 : */
408 :
409 1 : int sys_mm_drv_update_region_flags(void *virt, size_t size, uint32_t flags);
410 :
411 : /**
412 : * @}
413 : */
414 :
415 : /**
416 : * @name Memory Mappings Query
417 : *
418 : * On querying information on memory mappings.
419 : *
420 : * @{
421 : */
422 :
423 : /**
424 : * @brief Get the mapped physical memory address from virtual address.
425 : *
426 : * The function queries the translation tables to find the physical
427 : * memory address of a mapped virtual address.
428 : *
429 : * Behavior when providing unaligned address is undefined, this
430 : * is assumed to be page aligned.
431 : *
432 : * @param virt Page-aligned virtual address
433 : * @param[out] phys Mapped physical address (can be NULL if only checking
434 : * if virtual address is mapped)
435 : *
436 : * @retval 0 if mapping is found and valid
437 : * @retval -EINVAL if invalid arguments are provided
438 : * @retval -EFAULT if virtual address is not mapped
439 : */
440 1 : int sys_mm_drv_page_phys_get(void *virt, uintptr_t *phys);
441 :
442 : /* TODO is it safe to assume no valid region has size == 0? */
443 : /**
444 : * @brief Iterates over an array of regions returned by #sys_mm_drv_query_memory_regions
445 : *
446 : * Note that a sentinel item marking the end of the array is expected for
447 : * this macro to work.
448 : */
449 1 : #define SYS_MM_DRV_MEMORY_REGION_FOREACH(regions, iter) \
450 : for (iter = regions; iter->size; iter++)
451 :
452 : /**
453 : * @brief Query available memory regions
454 : *
455 : * Returns an array of available memory regions. One can iterate over
456 : * the array using #SYS_MM_DRV_MEMORY_REGION_FOREACH. Note that the last
457 : * item of the array is a sentinel marking the end, and it's identified
458 : * by it's size attribute, which is zero.
459 : *
460 : * @retval regions A possibly empty array - i.e. containing only the sentinel
461 : * marking at the end - of memory regions.
462 : */
463 1 : const struct sys_mm_drv_region *sys_mm_drv_query_memory_regions(void);
464 :
465 : /**
466 : * @brief Free the memory array returned by #sys_mm_drv_query_memory_regions
467 : *
468 : * The driver may have dynamically allocated the memory for the array of
469 : * regions returned by #sys_mm_drv_query_memory_regions. This method provides
470 : * it the opportunity to free any related resources.
471 : *
472 : * @param regions Array of regions previously returned by
473 : * #sys_mm_drv_query_memory_regions
474 : */
475 1 : void sys_mm_drv_query_memory_regions_free(const struct sys_mm_drv_region *regions);
476 :
477 : /**
478 : * @}
479 : */
480 :
481 : /**
482 : * @}
483 : */
484 :
485 : #ifdef __cplusplus
486 : }
487 : #endif
488 :
489 : #endif /* _ASMLANGUAGE */
490 :
491 : #endif /* ZEPHYR_INCLUDE_DRIVERS_SYSTEM_MM_H_ */
|