From cf24124efa253bfb387863d0efd094e4cc0ca4f1 Mon Sep 17 00:00:00 2001 From: Jaroslaw Stelter Date: Tue, 12 Jul 2022 12:09:29 +0200 Subject: [PATCH] mm: introduce update memory flags api There are cases when attributes of mapped virtual memory need to be updated. E.g. in case there is loadable library/module code loaded to the l2 memory then memory needs to be read-write. After the code is loaded and is ready to be executed then attributes of mapped memory should be updated to read-only/executable without loosing memory contents. Signed-off-by: Jaroslaw Stelter --- drivers/mm/mm_drv_common.c | 35 ++++++++++++++++++++ drivers/mm/mm_drv_common.h | 23 ++++++++++++++ drivers/mm/mm_drv_intel_adsp_tlb.c | 22 +++++++++++++ include/zephyr/drivers/mm/system_mm.h | 46 +++++++++++++++++++++++++++ 4 files changed, 126 insertions(+) diff --git a/drivers/mm/mm_drv_common.c b/drivers/mm/mm_drv_common.c index a1504e28243..b7c8bdc4c8a 100644 --- a/drivers/mm/mm_drv_common.c +++ b/drivers/mm/mm_drv_common.c @@ -434,3 +434,38 @@ out: __weak FUNC_ALIAS(sys_mm_drv_simple_move_array, sys_mm_drv_move_array, int); + +int sys_mm_drv_simple_update_region_flags(void *virt, size_t size, uint32_t flags) +{ + k_spinlock_key_t key; + int ret = 0; + size_t offset; + + CHECKIF(!sys_mm_drv_is_virt_addr_aligned(virt) || + !sys_mm_drv_is_size_aligned(size)) { + ret = -EINVAL; + goto out; + } + + key = k_spin_lock(&sys_mm_drv_common_lock); + + for (offset = 0; offset < size; offset += CONFIG_MM_DRV_PAGE_SIZE) { + uint8_t *va = (uint8_t *)virt + offset; + + int ret2 = sys_mm_drv_update_page_flags(va, flags); + + if (ret2 != 0) { + __ASSERT(false, "cannot update flags %p\n", va); + + ret = ret2; + } + } + + k_spin_unlock(&sys_mm_drv_common_lock, key); + +out: + return ret; +} + +__weak FUNC_ALIAS(sys_mm_drv_simple_update_region_flags, + sys_mm_drv_update_region_flags, int); diff --git a/drivers/mm/mm_drv_common.h b/drivers/mm/mm_drv_common.h index 6e2e44c06f3..ee29d6324f6 100644 --- a/drivers/mm/mm_drv_common.h +++ b/drivers/mm/mm_drv_common.h @@ -270,4 +270,27 @@ int sys_mm_drv_simple_move_array(void *virt_old, size_t size, void *virt_new, uintptr_t *phys_new, size_t phys_cnt); +/** + * @brief Update memory region flags + * + * This changes the attributes of physical memory which is already + * mapped to a virtual address. This is useful when use case of + * specific memory region changes. + * E.g. when the library/module code is copied to the memory then + * it needs to be read-write and after it has already + * been copied and library/module code is ready to be executed then + * attributes need to be changed to read-only/executable. + * Calling this API must not cause losing memory contents. + * + * @param virt Page-aligned virtual address to be updated + * @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 virtual addresses is not mapped + */ + +int sys_mm_drv_simple_update_region_flags(void *virt, size_t size, uint32_t flags); + #endif /* ZEPHYR_DRIVERS_SYSTEM_MM_DRV_COMMON_H_ */ diff --git a/drivers/mm/mm_drv_intel_adsp_tlb.c b/drivers/mm/mm_drv_intel_adsp_tlb.c index 62cbe1a594e..cd10c58c45a 100644 --- a/drivers/mm/mm_drv_intel_adsp_tlb.c +++ b/drivers/mm/mm_drv_intel_adsp_tlb.c @@ -261,6 +261,28 @@ int sys_mm_drv_page_flag_get(void *virt, uint32_t *flags) return 0; } +int sys_mm_drv_update_page_flags(void *virt, uint32_t flags) +{ + ARG_UNUSED(virt); + ARG_UNUSED(flags); + + /* + * There are no caching mode, or R/W, or eXecution (etc.) bits. + * So just return 0. + */ + + return 0; +} + +int sys_mm_drv_update_region_flags(void *virt, size_t size, + uint32_t flags) +{ + void *va = z_soc_cached_ptr(virt); + + return sys_mm_drv_simple_update_region_flags(va, size, flags); +} + + int sys_mm_drv_remap_region(void *virt_old, size_t size, void *virt_new) { diff --git a/include/zephyr/drivers/mm/system_mm.h b/include/zephyr/drivers/mm/system_mm.h index 0238d802f44..b478abeab72 100644 --- a/include/zephyr/drivers/mm/system_mm.h +++ b/include/zephyr/drivers/mm/system_mm.h @@ -293,6 +293,52 @@ int sys_mm_drv_move_region(void *virt_old, size_t size, void *virt_new, int sys_mm_drv_move_array(void *virt_old, size_t size, void *virt_new, uintptr_t *phys_new, size_t phys_cnt); + +/** + * @brief Update memory page flags + * + * This changes the attributes of physical memory page which is already + * mapped to a virtual address. This is useful when use case of + * specific memory region changes. + * E.g. when the library/module code is copied to the memory then + * it needs to be read-write and after it has already + * been copied and library/module code is ready to be executed then + * attributes need to be changed to read-only/executable. + * Calling this API must not cause losing memory contents. + * + * @param virt Page-aligned virtual address to be updated + * @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 addresses is not mapped + */ + +int sys_mm_drv_update_page_flags(void *virt, uint32_t flags); + +/** + * @brief Update memory region flags + * + * This changes the attributes of physical memory which is already + * mapped to a virtual address. This is useful when use case of + * specific memory region changes. + * E.g. when the library/module code is copied to the memory then + * it needs to be read-write and after it has already + * been copied and library/module code is ready to be executed then + * attributes need to be changed to read-only/executable. + * Calling this API must not cause losing memory contents. + * + * @param virt Page-aligned virtual address to be updated + * @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 virtual addresses is not mapped + */ + +int sys_mm_drv_update_region_flags(void *virt, size_t size, uint32_t flags); + /** * @} */