/* * 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 #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 entrie 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 simplier 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 simplier 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 simplier 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_ */