| /* |
| * Copyright (c) 2021 Intel Corporation. |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| /** |
| * @file |
| * @brief Memory Management Driver APIs |
| * |
| * This contains APIs for a system-wide memory management |
| * driver. Only one instance is permitted on the system. |
| */ |
| |
| #ifndef ZEPHYR_INCLUDE_DRIVERS_SYSTEM_MM_H_ |
| #define ZEPHYR_INCLUDE_DRIVERS_SYSTEM_MM_H_ |
| |
| #include <kernel.h> |
| |
| #ifndef _ASMLANGUAGE |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /** |
| * @brief Memory Management Driver APIs |
| * @defgroup mm_drv_apis Memory Management Driver APIs |
| * @{ |
| */ |
| |
| /* |
| * Caching mode definitions. These are mutually exclusive. |
| */ |
| |
| /** No caching */ |
| #define SYS_MM_MEM_CACHE_NONE 2 |
| |
| /** Write-through caching */ |
| #define SYS_MM_MEM_CACHE_WT 1 |
| |
| /** Full write-back caching */ |
| #define SYS_MM_MEM_CACHE_WB 0 |
| |
| /** Reserved bits for cache modes */ |
| #define SYS_MM_MEM_CACHE_MASK (BIT(3) - 1) |
| |
| /* |
| * Region permission attributes. |
| * Default should be read-only, no user, no exec. |
| */ |
| |
| /** Region will have read/write access (and not read-only) */ |
| #define SYS_MM_MEM_PERM_RW BIT(3) |
| |
| /** Region will be executable (normally forbidden) */ |
| #define SYS_MM_MEM_PERM_EXEC BIT(4) |
| |
| /** Region will be accessible to user mode (normally supervisor-only) */ |
| #define SYS_MM_MEM_PERM_USER BIT(5) |
| |
| /** |
| * @brief Map one physical page into the virtual address space |
| * |
| * This maps one physical page into the virtual address space. |
| * Behavior when providing unaligned address is undefined, this |
| * is assumed to be page aligned. |
| * |
| * The memory range itself is never accessed by this operation. |
| * |
| * This API must be safe to call in ISRs or exception handlers. Calls |
| * to this API are assumed to be serialized. |
| * |
| * @param virt Page-aligned destination virtual address to map |
| * @param phys Page-aligned source physical address to map |
| * @param flags Caching, access and control flags, see SYS_MM_MEM_* macros |
| * |
| * @retval 0 if successful |
| * @retval -EINVAL if invalid arguments are provided |
| * @retval -EFAULT if virtual address has already been mapped |
| */ |
| int sys_mm_drv_map_page(void *virt, uintptr_t phys, uint32_t flags); |
| |
| /** |
| * @brief Map a region of physical memory into the virtual address space |
| * |
| * This maps a region of physical memory into the virtual address space. |
| * Behavior when providing unaligned addresses/sizes is undefined, these |
| * are assumed to be page aligned. |
| * |
| * The memory range itself is never accessed by this operation. |
| * |
| * This API must be safe to call in ISRs or exception handlers. Calls |
| * to this API are assumed to be serialized. |
| * |
| * @param virt Page-aligned destination virtual address to map |
| * @param phys Page-aligned source physical address to map |
| * @param size Page-aligned size of the mapped memory region in bytes |
| * @param flags Caching, access and control flags, see SYS_MM_MEM_* macros |
| * |
| * @retval 0 if successful |
| * @retval -EINVAL if invalid arguments are provided |
| * @retval -EFAULT if any virtual addresses have already been mapped |
| */ |
| int sys_mm_drv_map_region(void *virt, uintptr_t phys, |
| size_t size, uint32_t flags); |
| |
| /** |
| * @brief Map an array of physical memory into the virtual address space |
| * |
| * This maps an array of physical pages into a continuous virtual address |
| * space. Behavior when providing unaligned addresses is undefined, these |
| * are assumed to be page aligned. |
| * |
| * The physical memory pages are never accessed by this operation. |
| * |
| * This API must be safe to call in ISRs or exception handlers. Calls |
| * to this API are assumed to be serialized. |
| * |
| * @param virt Page-aligned destination virtual address to map |
| * @param phys Array of pge-aligned source physical address to map |
| * @param cnt Number of elements in the physical page array |
| * @param flags Caching, access and control flags, see SYS_MM_MEM_* macros |
| * |
| * @retval 0 if successful |
| * @retval -EINVAL if invalid arguments are provided |
| * @retval -EFAULT if any virtual addresses have already been mapped |
| */ |
| int sys_mm_drv_map_array(void *virt, uintptr_t *phys, |
| size_t cnt, uint32_t flags); |
| |
| /** |
| * @brief Remove mapping for one page of the provided virtual address |
| * |
| * This unmaps one page from the virtual address space. |
| * |
| * When this completes, the relevant translation table entries will be |
| * updated as if no mapping was ever made for that memory page. No previous |
| * context needs to be preserved. This function must update mapping in |
| * all active translation tables. |
| * |
| * Behavior when providing unaligned address is undefined, this |
| * is assumed to be page aligned. |
| * |
| * Implementations must invalidate translation caching as necessary. |
| * |
| * @param virt Page-aligned virtual address to un-map |
| * |
| * @retval 0 if successful |
| * @retval -EINVAL if invalid arguments are provided |
| * @retval -EFAULT if virtual address is not mapped |
| */ |
| int sys_mm_drv_unmap_page(void *virt); |
| |
| /** |
| * @brief Remove mappings for a provided virtual address range |
| * |
| * This unmaps pages in the provided virtual address range. |
| * |
| * When this completes, the relevant translation table entries will be |
| * updated as if no mapping was ever made for that memory range. No previous |
| * context needs to be preserved. This function must update mappings in |
| * all active translation tables. |
| * |
| * Behavior when providing unaligned address is undefined, this |
| * is assumed to be page aligned. |
| * |
| * Implementations must invalidate translation caching as necessary. |
| * |
| * @param virt Page-aligned base virtual address to un-map |
| * @param size Page-aligned region size |
| * |
| * @retval 0 if successful |
| * @retval -EINVAL if invalid arguments are provided |
| * @retval -EFAULT if virtual addresses have already been mapped |
| */ |
| int sys_mm_drv_unmap_region(void *virt, size_t size); |
| |
| /** |
| * @brief Get the mapped physical memory address from virtual address. |
| * |
| * The function queries the translation tables to find the physical |
| * memory address of a mapped virtual address. |
| * |
| * Behavior when providing unaligned address is undefined, this |
| * is assumed to be page aligned. |
| * |
| * @param virt Page-aligned virtual address |
| * @param[out] phys Mapped physical address (can be NULL if only checking |
| * if virtual address is mapped) |
| * |
| * @retval 0 if mapping is found and valid |
| * @retval -EINVAL if invalid arguments are provided |
| * @retval -EFAULT if virtual address is not mapped |
| */ |
| int sys_mm_drv_page_phys_get(void *virt, uintptr_t *phys); |
| |
| /** |
| * @brief Remap virtual pages into new address |
| * |
| * This remaps a virtual memory region starting at @p virt_old |
| * of size @p size into a new virtual memory region starting at |
| * @p virt_new. In other words, physical memory at @p virt_old is |
| * remapped to appear at @p virt_new. Both addresses must be page |
| * aligned and valid. |
| * |
| * Note that the virtual memory at both the old and new addresses |
| * must be unmapped in the memory domains of any runnable Zephyr |
| * thread as this does not deal with memory domains. |
| * |
| * Note that overlapping of old and new virtual memory regions |
| * is usually not supported for simpler implementation. Refer to |
| * the actual driver to make sure if overlapping is allowed. |
| * |
| * @param virt_old Page-aligned base virtual address of existing memory |
| * @param size Page-aligned size of the mapped memory region in bytes |
| * @param virt_new Page-aligned base virtual address to which to remap |
| * the memory |
| * |
| * @retval 0 if successful |
| * @retval -EINVAL if invalid arguments are provided |
| * @retval -EFAULT if old virtual addresses are not all mapped or |
| * new virtual addresses are not all unmapped |
| */ |
| int sys_mm_drv_remap_region(void *virt_old, size_t size, void *virt_new); |
| |
| /** |
| * @brief Physically move memory, with copy |
| * |
| * This maps a region of physical memory into the new virtual address space |
| * (@p virt_new), and copy region of size @p size from the old virtual |
| * address space (@p virt_old). The new virtual memory region is mapped |
| * from physical memory starting at @p phys_new of size @p size. |
| * |
| * Behavior when providing unaligned addresses/sizes is undefined, these |
| * are assumed to be page aligned. |
| * |
| * Note that the virtual memory at both the old and new addresses |
| * must be unmapped in the memory domains of any runnable Zephyr |
| * thread as this does not deal with memory domains. |
| * |
| * Note that overlapping of old and new virtual memory regions |
| * is usually not supported for simpler implementation. Refer to |
| * the actual driver to make sure if overlapping is allowed. |
| * |
| * @param virt_old Page-aligned base virtual address of existing memory |
| * @param size Page-aligned size of the mapped memory region in bytes |
| * @param virt_new Page-aligned base virtual address to which to map |
| * new physical pages |
| * @param phys_new Page-aligned base physical address to contain |
| * the moved memory |
| * |
| * @retval 0 if successful |
| * @retval -EINVAL if invalid arguments are provided |
| * @retval -EFAULT if old virtual addresses are not all mapped or |
| * new virtual addresses are not all unmapped |
| */ |
| int sys_mm_drv_move_region(void *virt_old, size_t size, void *virt_new, |
| uintptr_t phys_new); |
| |
| /** |
| * @brief Physically move memory, with copy |
| * |
| * This maps a region of physical memory into the new virtual address space |
| * (@p virt_new), and copy region of size @p size from the old virtual |
| * address space (@p virt_old). The new virtual memory region is mapped |
| * from an array of physical pages. |
| * |
| * Behavior when providing unaligned addresses/sizes is undefined, these |
| * are assumed to be page aligned. |
| * |
| * Note that the virtual memory at both the old and new addresses |
| * must be unmapped in the memory domains of any runnable Zephyr |
| * thread as this does not deal with memory domains. |
| * |
| * Note that overlapping of old and new virtual memory regions |
| * is usually not supported for simpler implementation. Refer to |
| * the actual driver to make sure if overlapping is allowed. |
| * |
| * @param virt_old Page-aligned base virtual address of existing memory |
| * @param size Page-aligned size of the mapped memory region in bytes |
| * @param virt_new Page-aligned base virtual address to which to map |
| * new physical pages |
| * @param phys_new Array of page-aligned physical address to contain |
| * the moved memory |
| * @param phys_cnt Number of elements in the physical page array |
| * |
| * @retval 0 if successful |
| * @retval -EINVAL if invalid arguments are provided |
| * @retval -EFAULT if old virtual addresses are not all mapped or |
| * new virtual addresses are not all unmapped |
| */ |
| int sys_mm_drv_move_array(void *virt_old, size_t size, void *virt_new, |
| uintptr_t *phys_new, size_t phys_cnt); |
| |
| /** |
| * @} |
| */ |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* _ASMLANGUAGE */ |
| |
| #endif /* ZEPHYR_INCLUDE_DRIVERS_SYSTEM_MM_H_ */ |