diff --git a/app/boards/intel_adsp_ace15_mtpm.conf b/app/boards/intel_adsp_ace15_mtpm.conf index 288410192b81..f05f2d97d20b 100644 --- a/app/boards/intel_adsp_ace15_mtpm.conf +++ b/app/boards/intel_adsp_ace15_mtpm.conf @@ -83,6 +83,7 @@ CONFIG_WATCHDOG=y CONFIG_TIMESLICE_PER_THREAD=y CONFIG_THREAD_RUNTIME_STATS=y CONFIG_SCHED_THREAD_USAGE=y +CONFIG_MM_DRV_INTEL_VIRTUAL_REGION_COUNT=2 # Zephyr / device drivers CONFIG_CLOCK_CONTROL=y diff --git a/app/boards/intel_adsp_ace20_lnl.conf b/app/boards/intel_adsp_ace20_lnl.conf index 2d264293f66f..53cc9e1a1b0b 100644 --- a/app/boards/intel_adsp_ace20_lnl.conf +++ b/app/boards/intel_adsp_ace20_lnl.conf @@ -63,6 +63,7 @@ CONFIG_LLEXT_STORAGE_WRITABLE=y CONFIG_LLEXT_EXPERIMENTAL=y CONFIG_MODULES=y CONFIG_TIMING_FUNCTIONS=y +CONFIG_MM_DRV_INTEL_VIRTUAL_REGION_COUNT=2 # Zephyr / device drivers CONFIG_CLOCK_CONTROL=y diff --git a/app/boards/intel_adsp_ace30_ptl.conf b/app/boards/intel_adsp_ace30_ptl.conf index 6eac290aa74e..f84fff54b51d 100644 --- a/app/boards/intel_adsp_ace30_ptl.conf +++ b/app/boards/intel_adsp_ace30_ptl.conf @@ -63,6 +63,7 @@ CONFIG_LLEXT=y CONFIG_LLEXT_STORAGE_WRITABLE=y CONFIG_LLEXT_EXPERIMENTAL=y CONFIG_MODULES=y +CONFIG_MM_DRV_INTEL_VIRTUAL_REGION_COUNT=2 # Zephyr / device drivers CONFIG_CLOCK_CONTROL=y diff --git a/app/boards/intel_adsp_ace30_wcl.conf b/app/boards/intel_adsp_ace30_wcl.conf index 8776c099fa24..f96bfa913677 100644 --- a/app/boards/intel_adsp_ace30_wcl.conf +++ b/app/boards/intel_adsp_ace30_wcl.conf @@ -50,6 +50,7 @@ CONFIG_LLEXT=y CONFIG_LLEXT_STORAGE_WRITABLE=y CONFIG_LLEXT_EXPERIMENTAL=y CONFIG_MODULES=y +CONFIG_MM_DRV_INTEL_VIRTUAL_REGION_COUNT=2 # Zephyr / device drivers CONFIG_CLOCK_CONTROL=y diff --git a/src/library_manager/Kconfig b/src/library_manager/Kconfig index 598551a6c650..8eac39e59970 100644 --- a/src/library_manager/Kconfig +++ b/src/library_manager/Kconfig @@ -58,4 +58,10 @@ config LIBRARY_BASE_ADDRESS automatically but the beginning of that area is platform-specific and should be set by this option. +config LIBRARY_REGION_SIZE + hex "Size of memory region dedicated to loadable modules" + default 0x100000 + help + Size of the virtual memory region dedicated for loadable modules + endmenu diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c index 1ec0dd598db7..9c032319f82d 100644 --- a/src/library_manager/llext_manager.c +++ b/src/library_manager/llext_manager.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ #include #include +#include #include #include #include @@ -55,13 +57,13 @@ static int llext_manager_update_flags(void __sparse_cache *vma, size_t size, uin ALIGN_UP(pre_pad_size + size, PAGE_SZ), flags); } -static int llext_manager_align_map(void __sparse_cache *vma, size_t size, uint32_t flags) +static int llext_manager_align_map(const struct sys_mm_drv_region *virtual_region, + void __sparse_cache *vma, size_t size, uint32_t flags) { size_t pre_pad_size = (uintptr_t)vma & (PAGE_SZ - 1); void *aligned_vma = (__sparse_force uint8_t *)vma - pre_pad_size; - - return sys_mm_drv_map_region(aligned_vma, POINTER_TO_UINT(NULL), - ALIGN_UP(pre_pad_size + size, PAGE_SZ), flags); + return sys_mm_drv_map_region_safe(virtual_region, aligned_vma, POINTER_TO_UINT(NULL), + ALIGN_UP(pre_pad_size + size, PAGE_SZ), flags); } static int llext_manager_align_unmap(void __sparse_cache *vma, size_t size) @@ -91,7 +93,8 @@ static void llext_manager_detached_update_flags(void __sparse_cache *vma, * sections that belong to the specified 'region' and are contained in the * memory range, then remap the same area according to the 'flags' parameter. */ -static int llext_manager_load_data_from_storage(const struct llext_loader *ldr, +static int llext_manager_load_data_from_storage(const struct sys_mm_drv_region *virtual_region, + const struct llext_loader *ldr, const struct llext *ext, enum llext_mem region, void __sparse_cache *vma, @@ -99,7 +102,12 @@ static int llext_manager_load_data_from_storage(const struct llext_loader *ldr, { unsigned int i; const void *region_addr; - int ret = llext_manager_align_map(vma, size, SYS_MM_MEM_PERM_RW); + + /* check if there region to be mapped exists */ + if (size == 0) + return 0; + + int ret = llext_manager_align_map(virtual_region, vma, size, SYS_MM_MEM_PERM_RW); if (ret < 0) { tr_err(&lib_manager_tr, "cannot map %u of %p", size, (__sparse_force void *)vma); @@ -238,14 +246,25 @@ static int llext_manager_load_module(struct lib_manager_module *mctx) const struct llext_loader *ldr = &mctx->ebl->loader; const struct llext *ext = mctx->llext; + /* find dedicated virtual memory zone */ + const struct sys_mm_drv_region *virtual_memory_regions = sys_mm_drv_query_memory_regions(); + const struct sys_mm_drv_region *virtual_region; + + SYS_MM_DRV_MEMORY_REGION_FOREACH(virtual_memory_regions, virtual_region) { + if (virtual_region->attr == VIRTUAL_REGION_LLEXT_LIBRARIES_ATTR) + break; + } + if (!virtual_region || !virtual_region->size) + return -EFAULT; + /* Copy Code */ - ret = llext_manager_load_data_from_storage(ldr, ext, LLEXT_MEM_TEXT, + ret = llext_manager_load_data_from_storage(virtual_region, ldr, ext, LLEXT_MEM_TEXT, va_base_text, text_size, SYS_MM_MEM_PERM_EXEC); if (ret < 0) return ret; /* Copy read-only data */ - ret = llext_manager_load_data_from_storage(ldr, ext, LLEXT_MEM_RODATA, + ret = llext_manager_load_data_from_storage(virtual_region, ldr, ext, LLEXT_MEM_RODATA, va_base_rodata, rodata_size, 0); if (ret < 0) goto e_text; @@ -256,7 +275,7 @@ static int llext_manager_load_module(struct lib_manager_module *mctx) * spans over the BSS area as well, so the mapping will cover * both, but only LLEXT_MEM_DATA sections will be copied. */ - ret = llext_manager_load_data_from_storage(ldr, ext, LLEXT_MEM_DATA, + ret = llext_manager_load_data_from_storage(virtual_region, ldr, ext, LLEXT_MEM_DATA, va_base_data, data_size, SYS_MM_MEM_PERM_RW); if (ret < 0) goto e_rodata; @@ -806,3 +825,17 @@ bool comp_is_llext(struct comp_dev *comp) return mod && module_is_llext(mod); } + +static int llext_memory_region_init(void) +{ + int ret; + + /* add a region for loadable libraries */ + ret = adsp_add_virtual_memory_region(CONFIG_LIBRARY_BASE_ADDRESS, + CONFIG_LIBRARY_REGION_SIZE, + VIRTUAL_REGION_LLEXT_LIBRARIES_ATTR); + + return ret; +} + +SYS_INIT(llext_memory_region_init, POST_KERNEL, 1); diff --git a/west.yml b/west.yml index 16418517069e..c428ba32bb74 100644 --- a/west.yml +++ b/west.yml @@ -43,7 +43,7 @@ manifest: - name: zephyr repo-path: zephyr - revision: c99605126cd9cce5684ddd9ad56aed5292004867 + revision: 8843fd9fe1800164fbb5221d95d1eba7d0699458 remote: zephyrproject # Import some projects listed in zephyr/west.yml@revision diff --git a/zephyr/include/sof/lib/regions_mm.h b/zephyr/include/sof/lib/regions_mm.h index 6c93a2521a93..757094e32fcf 100644 --- a/zephyr/include/sof/lib/regions_mm.h +++ b/zephyr/include/sof/lib/regions_mm.h @@ -19,6 +19,7 @@ /* Attributes for memory regions */ #define VIRTUAL_REGION_SHARED_HEAP_ATTR 1U /*< region dedicated for shared virtual heap */ +#define VIRTUAL_REGION_LLEXT_LIBRARIES_ATTR 2U /*< region dedicated for LLEXT libraries */ /* Dependency on ipc/topology.h created due to memory capability definitions * that are defined there diff --git a/zephyr/lib/alloc.c b/zephyr/lib/alloc.c index ff5551881125..baf93ed159f1 100644 --- a/zephyr/lib/alloc.c +++ b/zephyr/lib/alloc.c @@ -289,25 +289,6 @@ static const struct vmh_heap_config static_hp_buffers = { }, }; -/* WA Stubs begin - * - * in order to merge a PR that moves initialization of virtual regions from Zephyr to SOF, - * we need to create weak stubs for 2 functions that will need to be called once the PR is merged - */ - -__weak -uintptr_t adsp_mm_get_unused_l2_start_aligned(void) -{ - return 0; -} - -__weak -int adsp_add_virtual_memory_region(uintptr_t region_address, uint32_t region_size, uint32_t attr) -{ - return 0; -} -/* WA Stubs end */ - static int virtual_heap_init(void) { int ret; diff --git a/zephyr/lib/regions_mm.c b/zephyr/lib/regions_mm.c index 500f751de96d..c9b307b8f298 100644 --- a/zephyr/lib/regions_mm.c +++ b/zephyr/lib/regions_mm.c @@ -49,7 +49,10 @@ struct vmh_heap { */ struct vmh_heap *vmh_init_heap(const struct vmh_heap_config *cfg, bool allocating_continuously) { + const struct sys_mm_drv_region *virtual_memory_regions = + sys_mm_drv_query_memory_regions(); int i; + struct vmh_heap *new_heap = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, sizeof(*new_heap)); @@ -58,13 +61,14 @@ struct vmh_heap *vmh_init_heap(const struct vmh_heap_config *cfg, bool allocatin k_mutex_init(&new_heap->lock); struct vmh_heap_config new_config = {0}; + const struct sys_mm_drv_region *region; - /* Workaround - use the very first virtual memory region because of virt addresses - * collision. - * Fix will be provided ASAP, but removing MEM_REG_ATTR_SHARED_HEAP from SOF is required - * to merge Zephyr changes - */ - new_heap->virtual_region = sys_mm_drv_query_memory_regions(); + SYS_MM_DRV_MEMORY_REGION_FOREACH(virtual_memory_regions, region) { + if (region->attr == VIRTUAL_REGION_SHARED_HEAP_ATTR) { + new_heap->virtual_region = region; + break; + } + } if (!new_heap->virtual_region || !new_heap->virtual_region->size) goto fail; @@ -323,7 +327,8 @@ static void vmh_get_mapped_size(void *addr, size_t *size) * * @retval 0 on success, error code otherwise. */ -static int vmh_map_region(struct sys_mem_blocks *region, void *ptr, size_t size) +static int vmh_map_region(const struct sys_mm_drv_region *virtual_region, + struct sys_mem_blocks *region, void *ptr, size_t size) { const size_t block_size = 1 << region->info.blk_sz_shift; uintptr_t begin; @@ -336,8 +341,8 @@ static int vmh_map_region(struct sys_mem_blocks *region, void *ptr, size_t size) if (!vmh_get_map_region_boundaries(region, ptr, size, &begin, &size)) return 0; } - - ret = sys_mm_drv_map_region(UINT_TO_POINTER(begin), 0, size, SYS_MM_MEM_PERM_RW); + ret = sys_mm_drv_map_region_safe(virtual_region, UINT_TO_POINTER(begin), 0, size, + SYS_MM_MEM_PERM_RW); /* In case of an error, the pages that were successfully mapped must be manually released */ if (ret) @@ -491,7 +496,8 @@ static void *_vmh_alloc(struct vmh_heap *heap, uint32_t alloc_size) if (!ptr) return NULL; - allocation_error_code = vmh_map_region(heap->physical_blocks_allocators[mem_block_iterator], + allocation_error_code = vmh_map_region(heap->virtual_region, + heap->physical_blocks_allocators[mem_block_iterator], ptr, alloc_size); if (allocation_error_code) { sys_mem_blocks_free_contiguous(heap->physical_blocks_allocators[mem_block_iterator],