blob: 228c17f3f79eec038e5c24d8ca5ab991ee33a4a6 [file]
/*
* Copyright (c) 2026 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/llext/llext.h>
#include <zephyr/sys/mem_blocks.h>
#include "llext_mem.h"
#include "llext_memblk.h"
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(llext, CONFIG_LLEXT_LOG_LEVEL);
Z_HEAP_DEFINE_IN_SECT(llext_metadata_heap, (CONFIG_LLEXT_METADATA_HEAP_SIZE * KB(1)),
__attribute__((section(".llext_metadata_heap"))));
#ifdef CONFIG_HARVARD
BUILD_ASSERT(CONFIG_LLEXT_INSTR_HEAP_SIZE * KB(1) % CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE == 0,
"CONFIG_LLEXT_INSTR_HEAP_SIZE must be multiple of "
"CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE");
BUILD_ASSERT(CONFIG_LLEXT_DATA_HEAP_SIZE * KB(1) % CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE == 0,
"CONFIG_LLEXT_DATA_HEAP_SIZE must be multiple of "
"CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE");
#if defined(CONFIG_MMU) || defined(CONFIG_MPU)
BUILD_ASSERT(CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE % LLEXT_PAGE_SIZE == 0,
"CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE must be multiple of LLEXT_PAGE_SIZE");
#endif
uint8_t llext_instr_heap_buf[CONFIG_LLEXT_INSTR_HEAP_SIZE * KB(1)]
__aligned(CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE)
__attribute__((section(".llext_instr_heap")));
uint8_t llext_data_heap_buf[CONFIG_LLEXT_DATA_HEAP_SIZE * KB(1)]
__aligned(CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE) __attribute__((section(".llext_data_heap")));
SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(llext_instr_heap, CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE,
CONFIG_LLEXT_INSTR_HEAP_SIZE * KB(1) /
CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE,
llext_instr_heap_buf);
SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(llext_data_heap, CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE,
CONFIG_LLEXT_DATA_HEAP_SIZE * KB(1) /
CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE,
llext_data_heap_buf);
#else /* !CONFIG_HARVARD */
BUILD_ASSERT(CONFIG_LLEXT_EXT_HEAP_SIZE * KB(1) % CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE == 0,
"CONFIG_LLEXT_EXT_HEAP_SIZE must be multiple of "
"CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE");
#if defined(CONFIG_MMU) || defined(CONFIG_MPU)
BUILD_ASSERT(CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE % LLEXT_PAGE_SIZE == 0,
"CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE must be multiple of LLEXT_PAGE_SIZE");
#endif
uint8_t llext_ext_heap_buf[CONFIG_LLEXT_EXT_HEAP_SIZE * KB(1)]
__aligned(CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE) __attribute__((section(".llext_ext_heap")));
SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(llext_ext_heap, CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE,
CONFIG_LLEXT_EXT_HEAP_SIZE * KB(1) /
CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE,
llext_ext_heap_buf);
#endif /* CONFIG_HARVARD */
static inline struct llext_alloc *get_llext_alloc(struct llext_alloc_map *map, void *alloc_ptr)
{
for (int i = 0; i < map->idx; i++) {
if (map->map[i].memblk_ptr == alloc_ptr) {
return &map->map[i];
}
}
return NULL;
}
void *llext_memblk_aligned_alloc_data_instr(struct llext *ext, sys_mem_blocks_t *memblk_heap,
size_t align, size_t bytes)
{
if (ext->mem_alloc_map.idx >= LLEXT_MEM_COUNT) {
return NULL;
}
if (CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE % align != 0) {
LOG_ERR("Requested alignment %zu not possible with block alignment %d", align,
CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE);
return NULL;
}
struct llext_alloc *mem_alloc = &ext->mem_alloc_map.map[ext->mem_alloc_map.idx];
mem_alloc->num_blocks = DIV_ROUND_UP(bytes, CONFIG_LLEXT_HEAP_MEMBLK_BLOCK_SIZE);
int ret = sys_mem_blocks_alloc_contiguous(memblk_heap, mem_alloc->num_blocks,
&mem_alloc->memblk_ptr);
if (ret != 0) {
return NULL;
}
ext->mem_alloc_map.idx++;
return mem_alloc->memblk_ptr;
}
void llext_memblk_free_data_instr(struct llext *ext, sys_mem_blocks_t *memblk_heap, void *ptr)
{
struct llext_alloc *mem_alloc = get_llext_alloc(&ext->mem_alloc_map, ptr);
if (!mem_alloc) {
LOG_ERR("Could not find sys_mem_blocks alloc to free pointer %p", ptr);
return;
}
sys_mem_blocks_free_contiguous(memblk_heap, mem_alloc->memblk_ptr, mem_alloc->num_blocks);
mem_alloc->num_blocks = 0;
mem_alloc->memblk_ptr = NULL;
}