From 99a5236b4025557ff76f9106febfdbdbae883c95 Mon Sep 17 00:00:00 2001 From: Lauren Murphy Date: Wed, 11 Sep 2024 14:26:22 -0700 Subject: [PATCH] llext: add support for arc Adds compiler flag(s) and some architecture-specific relocations for ARC. No userspace support, doesn't support all relocations. Signed-off-by: Lauren Murphy --- arch/arc/core/CMakeLists.txt | 2 + arch/arc/core/elf.c | 79 +++++++++++++++++++ cmake/compiler/gcc/target_arc.cmake | 11 +++ doc/services/llext/index.rst | 2 +- .../simple/boards/qemu_arc_qemu_arc_em.conf | 6 ++ .../boards/qemu_arc_qemu_arc_em.overlay | 28 +++++++ .../llext/simple/no_mem_protection.conf | 1 + tests/subsys/llext/simple/testcase.yaml | 19 +++-- 8 files changed, 137 insertions(+), 11 deletions(-) create mode 100644 arch/arc/core/elf.c create mode 100644 tests/subsys/llext/simple/boards/qemu_arc_qemu_arc_em.conf create mode 100644 tests/subsys/llext/simple/boards/qemu_arc_qemu_arc_em.overlay diff --git a/arch/arc/core/CMakeLists.txt b/arch/arc/core/CMakeLists.txt index 00c9f775038..5b81f527480 100644 --- a/arch/arc/core/CMakeLists.txt +++ b/arch/arc/core/CMakeLists.txt @@ -34,3 +34,5 @@ add_subdirectory_ifdef(CONFIG_ARC_CORE_MPU mpu) add_subdirectory_ifdef(CONFIG_ARC_SECURE_FIRMWARE secureshield) zephyr_linker_sources(ROM_START SORT_KEY 0x0vectors vector_table.ld) + +zephyr_library_sources_ifdef(CONFIG_LLEXT elf.c) diff --git a/arch/arc/core/elf.c b/arch/arc/core/elf.c new file mode 100644 index 00000000000..7bdb5b08fcf --- /dev/null +++ b/arch/arc/core/elf.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +LOG_MODULE_REGISTER(elf, CONFIG_LLEXT_LOG_LEVEL); + +#define R_ARC_32 4 +#define R_ARC_B26 5 /* AKA R_ARC_64 */ +#define R_ARC_S25W_PCREL 17 +#define R_ARC_32_ME 27 + +/* ARCompact insns packed in memory have Middle Endian encoding */ +#define ME(x) ((x & 0xffff0000) >> 16) | ((x & 0xffff) << 16); + +/** + * @brief Architecture specific function for relocating shared elf + * + * Elf files contain a series of relocations described in multiple sections. + * These relocation instructions are architecture specific and each architecture + * supporting modules must implement this. + * + * The relocation codes are well documented: + * https://github.com/foss-for-synopsys-dwc-arc-processors/arc-ABI-manual/blob/master/ARCv2_ABI.pdf + * https://github.com/zephyrproject-rtos/binutils-gdb + */ +int arch_elf_relocate(elf_rela_t *rel, uintptr_t loc, uintptr_t sym_base_addr, const char *sym_name, + uintptr_t load_bias) +{ + int ret = 0; + uint32_t insn = *(uint32_t *)loc; + uint32_t value; + + sym_base_addr += rel->r_addend; + + int reloc_type = ELF32_R_TYPE(rel->r_info); + + switch (reloc_type) { + case R_ARC_32: + case R_ARC_B26: + *(uint32_t *)loc = sym_base_addr; + break; + case R_ARC_S25W_PCREL: + /* ((S + A) - P) >> 2 + * S = symbol address + * A = addend + * P = relative offset to PCL + */ + value = (sym_base_addr + rel->r_addend - (loc & ~0x3)) >> 2; + + insn = ME(insn); + + /* disp25w */ + insn = insn & ~0x7fcffcf; + insn |= ((value >> 0) & 0x01ff) << 18; + insn |= ((value >> 9) & 0x03ff) << 6; + insn |= ((value >> 19) & 0x000f) << 0; + + insn = ME(insn); + + *(uint32_t *)loc = insn; + break; + case R_ARC_32_ME: + *(uint32_t *)loc = ME(sym_base_addr); + break; + default: + LOG_ERR("unknown relocation: %u\n", reloc_type); + ret = -ENOEXEC; + break; + } + + return ret; +} diff --git a/cmake/compiler/gcc/target_arc.cmake b/cmake/compiler/gcc/target_arc.cmake index e18fa468f16..d306fe1550f 100644 --- a/cmake/compiler/gcc/target_arc.cmake +++ b/cmake/compiler/gcc/target_arc.cmake @@ -8,5 +8,16 @@ if(NOT DEFINED GCC_ARC_TUNED_CPU) set(GCC_ARC_TUNED_CPU ${GCC_M_CPU}) endif() +# Flags not supported by llext linker +# (regexps are supported and match whole word) +set(LLEXT_REMOVE_FLAGS + -fno-pic + -fno-pie + -ffunction-sections + -fdata-sections + -g.* + -Os +) + list(APPEND TOOLCHAIN_C_FLAGS -mcpu=${GCC_ARC_TUNED_CPU}) list(APPEND TOOLCHAIN_LD_FLAGS -mcpu=${GCC_ARC_TUNED_CPU}) diff --git a/doc/services/llext/index.rst b/doc/services/llext/index.rst index f626f1df1da..ebae211d16d 100644 --- a/doc/services/llext/index.rst +++ b/doc/services/llext/index.rst @@ -21,4 +21,4 @@ and introspected to some degree, as well as unloaded when no longer needed. .. note:: The LLEXT subsystem requires architecture-specific support. It is currently - available only on RISC-V, ARM, ARM64 and Xtensa cores. + available only on RISC-V, ARM, ARM64, ARC (experimental) and Xtensa cores. diff --git a/tests/subsys/llext/simple/boards/qemu_arc_qemu_arc_em.conf b/tests/subsys/llext/simple/boards/qemu_arc_qemu_arc_em.conf new file mode 100644 index 00000000000..85f52f80513 --- /dev/null +++ b/tests/subsys/llext/simple/boards/qemu_arc_qemu_arc_em.conf @@ -0,0 +1,6 @@ +CONFIG_FILE_SYSTEM=y +CONFIG_FILE_SYSTEM_LITTLEFS=y +CONFIG_FS_LITTLEFS_FMP_DEV=y +CONFIG_FLASH_MAP=y +CONFIG_FLASH=y +CONFIG_FLASH_SIMULATOR=y diff --git a/tests/subsys/llext/simple/boards/qemu_arc_qemu_arc_em.overlay b/tests/subsys/llext/simple/boards/qemu_arc_qemu_arc_em.overlay new file mode 100644 index 00000000000..3ec42970a9e --- /dev/null +++ b/tests/subsys/llext/simple/boards/qemu_arc_qemu_arc_em.overlay @@ -0,0 +1,28 @@ +/ { + sim_flash_controller: sim_flash_controller { + compatible = "zephyr,sim-flash"; + + #address-cells = <1>; + #size-cells = <1>; + erase-value = <0x00>; + + flash_sim0: flash_sim@0 { + compatible = "soc-nv-flash"; + reg = <0x00000000 0x2000>; + + erase-block-size = <1024>; + write-block-size = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + storage_partition: partition@0 { + label = "storage_partition"; + reg = <0x00000000 0x2000>; + }; + }; + }; + }; +}; diff --git a/tests/subsys/llext/simple/no_mem_protection.conf b/tests/subsys/llext/simple/no_mem_protection.conf index d45d7836d4d..6fbaeac79bb 100644 --- a/tests/subsys/llext/simple/no_mem_protection.conf +++ b/tests/subsys/llext/simple/no_mem_protection.conf @@ -6,3 +6,4 @@ CONFIG_ARM_MPU=n CONFIG_ARM_AARCH32_MMU=n CONFIG_RISCV_PMP=n +CONFIG_ARC_MPU_ENABLE=n diff --git a/tests/subsys/llext/simple/testcase.yaml b/tests/subsys/llext/simple/testcase.yaml index 901bd3d06ad..db84e7a129a 100644 --- a/tests/subsys/llext/simple/testcase.yaml +++ b/tests/subsys/llext/simple/testcase.yaml @@ -6,11 +6,6 @@ common: - s32z2xxdc2/s32z270/rtu0 # See commit 18a0660 - s32z2xxdc2/s32z270/rtu1 # See commit 18a0660 # platforms that are always skipped by the runtime filter - - qemu_arc/qemu_arc_em - - qemu_arc/qemu_arc_hs - - qemu_arc/qemu_arc_hs/xip - - qemu_arc/qemu_arc_hs5x - - qemu_arc/qemu_arc_hs6x - qemu_cortex_m0 - qemu_xtensa/dc233c/mmu integration_platforms: @@ -36,7 +31,7 @@ tests: # most tests include no_mem_protection.conf, which disables memory protection # hardware completely. llext.simple.readonly: - arch_allow: arm riscv # Xtensa needs writable storage + arch_allow: arm riscv arc # Xtensa needs writable storage filter: not CONFIG_MPU and not CONFIG_MMU extra_conf_files: ['no_mem_protection.conf'] extra_configs: @@ -57,7 +52,7 @@ tests: - CONFIG_LLEXT_HEAP_SIZE=128 # qemu_cortex_a9 requires larger heap - CONFIG_LLEXT_STORAGE_WRITABLE=n llext.simple.writable: - arch_allow: arm xtensa riscv + arch_allow: arm xtensa riscv arc integration_platforms: - qemu_xtensa/dc233c # Xtensa ISA filter: not CONFIG_MPU and not CONFIG_MMU @@ -65,7 +60,9 @@ tests: extra_configs: - CONFIG_LLEXT_STORAGE_WRITABLE=y llext.simple.writable_relocatable: - arch_allow: arm xtensa riscv + arch_allow: arm xtensa riscv arc + platform_exclude: + - qemu_arc/qemu_arc_hs5x # See #80949 integration_platforms: - qemu_xtensa/dc233c # Xtensa ISA filter: not CONFIG_MPU and not CONFIG_MMU @@ -77,7 +74,7 @@ tests: # Test the Symbol Link Identifier (SLID) linking feature on writable # storage to cover both ARM and Xtensa architectures on the same test. llext.simple.writable_slid_linking: - arch_allow: arm xtensa riscv + arch_allow: arm xtensa riscv arc integration_platforms: - qemu_xtensa/dc233c # Xtensa ISA filter: not CONFIG_MPU and not CONFIG_MMU @@ -86,7 +83,9 @@ tests: - CONFIG_LLEXT_STORAGE_WRITABLE=y - CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y llext.simple.writable_relocatable_slid_linking: - arch_allow: arm xtensa riscv + arch_allow: arm xtensa riscv arc + platform_exclude: + - qemu_arc/qemu_arc_hs5x # See #80949 integration_platforms: - qemu_xtensa/dc233c # Xtensa ISA filter: not CONFIG_MPU and not CONFIG_MMU