diff --git a/app/boards/intel_adsp_ace15_mtpm.conf b/app/boards/intel_adsp_ace15_mtpm.conf index e3d36ba7c35c..4084a6b5d2b3 100644 --- a/app/boards/intel_adsp_ace15_mtpm.conf +++ b/app/boards/intel_adsp_ace15_mtpm.conf @@ -88,6 +88,7 @@ CONFIG_MEMORY_WIN_2_SIZE=12288 CONFIG_LLEXT=y CONFIG_LLEXT_STORAGE_WRITABLE=y CONFIG_MODULES=y +CONFIG_LIBRARY_BASE_ADDRESS=0xa0688000 # Temporary disabled options CONFIG_TRACE=n diff --git a/app/boards/intel_adsp_ace20_lnl.conf b/app/boards/intel_adsp_ace20_lnl.conf index 8a9e4b295f5d..e2d92511d336 100644 --- a/app/boards/intel_adsp_ace20_lnl.conf +++ b/app/boards/intel_adsp_ace20_lnl.conf @@ -82,7 +82,7 @@ CONFIG_MEMORY_WIN_2_SIZE=12288 CONFIG_LLEXT=y CONFIG_LLEXT_STORAGE_WRITABLE=y CONFIG_MODULES=y - +CONFIG_LIBRARY_BASE_ADDRESS=0xa0688000 # Temporary disabled options CONFIG_TRACE=n diff --git a/scripts/llext_link_helper.py b/scripts/llext_link_helper.py index b1674e523784..98514c35a6cd 100755 --- a/scripts/llext_link_helper.py +++ b/scripts/llext_link_helper.py @@ -28,6 +28,8 @@ def parse_args(): help='Object file name') parser.add_argument("-t", "--text-addr", required=True, type=str, help='.text section address') + parser.add_argument("-s", "--size-file", required=True, type=str, + help='File with stored accumulated size') args = parser.parse_args() @@ -43,11 +45,20 @@ def max_alignment(addr, align1, align2): return upper - (upper % align1) def main(): + global args + parse_args() - elf = ELFFile(open(args.file, 'rb')) + # Get the size of the previous module, if this isn't the first one. + # It is used to automatically calculate starting address of the current + # module. + try: + with open(args.size_file, 'r') as f_size: + size = int(f_size.read().strip(), base = 0) + except OSError: + size = 0 - text_addr = int(args.text_addr, 0) + text_addr = int(args.text_addr, 0) + size text_size = 0 # File names differ when building shared or relocatable objects @@ -65,6 +76,8 @@ def main(): writable = [] readonly = [] + elf = ELFFile(open(args.file, 'rb')) + # Create an object file with sections grouped by their properties, # similar to how program segments are created: all executable sections, # then all read-only data sections, and eventually all writable data diff --git a/scripts/llext_offset_calc.py b/scripts/llext_offset_calc.py new file mode 100755 index 000000000000..cef0662449bf --- /dev/null +++ b/scripts/llext_offset_calc.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-3-Clause + +# Add rounded new file size to accumulated module size cache + +import argparse +import pathlib +import os + +args = None + +def parse_args(): + global args + + parser = argparse.ArgumentParser(description='Add a file size to a sum in a file') + + parser.add_argument("-i", "--input", required=True, type=str, + help='Object file name') + parser.add_argument("-s", "--size-file", required=True, type=str, + help='File to store accumulated size') + + args = parser.parse_args() + +def main(): + global args + + parse_args() + + f_output = pathlib.Path(args.size_file) + + try: + with open(f_output, 'r') as f_size: + size = int(f_size.read().strip(), base = 0) + except OSError: + size = 0 + + # Failure will raise an exception + f_size = open(f_output, "w") + + # align to a page border + size += os.path.getsize(args.input) + 0xfff + size &= ~0xfff + + f_size.write(f'0x{size:x}\n') + +if __name__ == "__main__": + main() diff --git a/src/audio/drc/llext/CMakeLists.txt b/src/audio/drc/llext/CMakeLists.txt index 5a59b9bade98..e658c3acfe0b 100644 --- a/src/audio/drc/llext/CMakeLists.txt +++ b/src/audio/drc/llext/CMakeLists.txt @@ -1,7 +1,6 @@ # Copyright (c) 2024 Intel Corporation. # SPDX-License-Identifier: Apache-2.0 -# Hard-coded .text address to be moved to a common place sof_llext_build("drc" SOURCES ../drc.c ../drc_generic.c @@ -9,5 +8,4 @@ sof_llext_build("drc" ../drc_hifi3.c ../drc_hifi4.c ../drc_math_hifi3.c - TEXT_ADDR 0xa068a000 ) diff --git a/src/audio/eq_iir/llext/CMakeLists.txt b/src/audio/eq_iir/llext/CMakeLists.txt index 9bf8a4b4e7ef..535455105515 100644 --- a/src/audio/eq_iir/llext/CMakeLists.txt +++ b/src/audio/eq_iir/llext/CMakeLists.txt @@ -1,10 +1,8 @@ # Copyright (c) 2024 Intel Corporation. # SPDX-License-Identifier: Apache-2.0 -# Hard-coded .text address to be moved to a common place sof_llext_build("eq_iir" SOURCES ../eq_iir.c ../eq_iir_ipc4.c ../eq_iir_generic.c - TEXT_ADDR 0xa06ea000 ) diff --git a/src/audio/mixin_mixout/llext/CMakeLists.txt b/src/audio/mixin_mixout/llext/CMakeLists.txt index a9743e379d54..fc5278dc47b0 100644 --- a/src/audio/mixin_mixout/llext/CMakeLists.txt +++ b/src/audio/mixin_mixout/llext/CMakeLists.txt @@ -1,11 +1,9 @@ # Copyright (c) 2024 Intel Corporation. # SPDX-License-Identifier: Apache-2.0 -# Hard-coded .text address to be moved to a common place sof_llext_build("mixin_mixout" SOURCES ../mixin_mixout.c ../mixin_mixout_hifi3.c ../mixin_mixout_hifi5.c ../mixin_mixout_generic.c - TEXT_ADDR 0xa06aa000 ) diff --git a/src/library_manager/Kconfig b/src/library_manager/Kconfig index d0657aefc9fb..7791e8839ac2 100644 --- a/src/library_manager/Kconfig +++ b/src/library_manager/Kconfig @@ -41,4 +41,13 @@ config LIBRARY_DEFAULT_MODULAR code has tristate Kconfig entries, they will default to "m" if this option is selected. +config LIBRARY_BASE_ADDRESS + hex "Base address for memory, dedicated to loadable modules" + default 0 + help + When initializing modules SOF will allocate memory for them and map + it to a predefined per-module address. Those addresses are calculated + automatically but the beginning of that area is platform-specific and + should be set by this option. + endmenu diff --git a/src/samples/audio/smart_amp_test_llext/CMakeLists.txt b/src/samples/audio/smart_amp_test_llext/CMakeLists.txt index 873eb61de81b..2218f41423b5 100644 --- a/src/samples/audio/smart_amp_test_llext/CMakeLists.txt +++ b/src/samples/audio/smart_amp_test_llext/CMakeLists.txt @@ -1,8 +1,6 @@ # Copyright (c) 2023 Intel Corporation. # SPDX-License-Identifier: Apache-2.0 -# Hard-coded .text address to be moved to a common place sof_llext_build("smart_amp_test" SOURCES ../smart_amp_test_ipc4.c - TEXT_ADDR 0xa06ca000 ) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index c131492f0f8d..80c055e90fb1 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -38,6 +38,13 @@ function(sof_append_relative_path_definitions target) endforeach() endfunction() +define_property(GLOBAL PROPERTY SOF_LLEXT_LAST_TARGET + BRIEF_DOCS "Last LLEXT target" + FULL_DOCS "\ +Building LLEXT targets must be serialized. This property contains the \ +previously added LLEXT module for the establishment of a dependency chain." +) + # Used by LLEXT modules to create a file with module UUIDs function(sof_llext_write_uuids module) file(STRINGS ${CMAKE_CURRENT_LIST_DIR}/../${module}.toml uuids REGEX "^[ \t]*uuid *=") @@ -54,7 +61,6 @@ endfunction() # Build an LLEXT module. Provice a module name, a list of sources and an address # of the .text section as arguments. function(sof_llext_build module) - set(single_args TEXT_ADDR) set(multi_args SOURCES) cmake_parse_arguments(PARSE_ARGV 1 SOF_LLEXT "${options}" "${single_args}" "${multi_args}") @@ -91,13 +97,29 @@ function(sof_llext_build module) get_target_property(proc_in_file ${module} lib_output) get_target_property(proc_out_file ${module} pkg_input) + get_target_property(proc_pkg_file ${module} pkg_output) + set(size_file ${PROJECT_BINARY_DIR}/module_size) + + get_property(last_target GLOBAL PROPERTY SOF_LLEXT_LAST_TARGET) + if(NOT "${last_target}" STREQUAL "") + add_dependencies(${module}_llext_proc ${last_target}) + endif() + set_property(GLOBAL PROPERTY SOF_LLEXT_LAST_TARGET ${module}) + add_llext_command(TARGET ${module} POST_BUILD - COMMAND ${PYTHON_EXECUTABLE} ${SOF_BASE}scripts/llext_link_helper.py - --text-addr="${SOF_LLEXT_TEXT_ADDR}" -f ${proc_in_file} ${CMAKE_C_COMPILER} -- + COMMAND ${PYTHON_EXECUTABLE} ${SOF_BASE}scripts/llext_link_helper.py -s ${size_file} + --text-addr=${CONFIG_LIBRARY_BASE_ADDRESS} + -f ${proc_in_file} ${CMAKE_C_COMPILER} -- -o ${proc_out_file} ${EXTRA_LINKER_PARAMS} $ ) + + add_llext_command(TARGET ${module} + POST_PKG + COMMAND ${PYTHON_EXECUTABLE} ${SOF_BASE}scripts/llext_offset_calc.py + -i ${proc_pkg_file} -s ${size_file} + ) endfunction() # Initial SOF module will contain