cmake: userspace: A stab at USERSPACE + CMAKE_LINKER_GENERATOR

All in all this makes cmake linker generator able to work for at least
most of the kernel tests and samples, on cortex m4.

Make the cmake linker generator have a file-structure more similar to
the ld-skeletons.

Add or edit groups, sections and logic to make the generator reflect
what the ld-skeletons do, esp. for kobjects and APP_SMEM, nonint and
some other details are also effected.

Use the new zephyr_linker_include_generated() and
zephyr_linker_include_var() functions to to handle
${DEVICE_API_LINKER_SECTIONS_CMAKE}, the kobject-prebuilt-*.h files and
APP_SMEM partition. Essentially the output from gen_app_partitions.py,
gen_kobject_placeholders.py.

Add ALIGN_WITH_INPUT on sections being put into DATA_REGION. This makes
the init layout work for ld.

This leverages the updates in gen_app_partitions.py to generate its
output as cmake linker generator sections too, and puts them into a
group defined in linker.cmake

Setup generator variables for alignment of APP_SMEM. Note that this does
not yet handle MPU_ALIGN which depends on the size of the section...

Fix broken k_object_assignment iterable section

Signed-off-by: Björn Bergman <bjorn.bergman@iar.com>
This commit is contained in:
Björn Bergman 2025-02-04 16:58:24 +01:00 committed by Benjamin Cabé
commit 128698fd36
23 changed files with 354 additions and 72 deletions

View file

@ -1,14 +1,38 @@
set(COMMON_ZEPHYR_LINKER_DIR ${ZEPHYR_BASE}/cmake/linker_script/common)
set_ifndef(region_min_align CONFIG_CUSTOM_SECTION_MIN_ALIGN_SIZE)
# This should be different for cortex_r or cortex_a....
# cut from zephyr/include/zephyr/arch/arm/cortex_m/scripts/linker.ld
if(DEFINED CONFIG_CUSTOM_SECTION_MIN_ALIGN_SIZE)
set_ifndef(region_min_align ${CONFIG_CUSTOM_SECTION_MIN_ALIGN_SIZE})
endif()
# Set alignment to CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE if not set above
# to make linker section alignment comply with MPU granularity.
set_ifndef(region_min_align CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE)
if(DEFINED CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE)
set_ifndef(region_min_align ${CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE})
endif()
# If building without MPU support, use default 4-byte alignment.. if not set above.
set_ifndef(region_min_align 4)
zephyr_linker_include_var(VAR region_min_align)
if((NOT DEFINED CONFIG_CUSTOM_SECTION_ALIGN) AND DEFINED CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT)
# define MPU_ALIGN(region_size) \
# . = ALIGN(_region_min_align); \
# . = ALIGN( 1 << LOG2CEIL(region_size))
# Handling this requires us to handle log2ceil() in iar linker since the size
# isn't known until then.
set(MPU_ALIGN_BYTES ${region_min_align})
#message(WARNING "We can not handle . = ALIGN( 1 << LOG2CEIL(region_size)) ")
else()
set(MPU_ALIGN_BYTES ${region_min_align})
endif()
# The APP_SHARED_ALIGN and SMEM_PARTITION_ALIGN macros are defined as
# ". = ALIGN(...)" things.
# the cmake generator stuff needs an align-size in bytes so:
zephyr_linker_include_var(VAR APP_SHARED_ALIGN_BYTES VALUE ${region_min_align})
zephyr_linker_include_var(VAR SMEM_PARTITION_ALIGN_BYTES VALUE ${MPU_ALIGN_BYTES})
# Note, the `+ 0` in formulas below avoids errors in cases where a Kconfig
# variable is undefined and thus expands to nothing.
math(EXPR FLASH_ADDR
@ -59,6 +83,7 @@ zephyr_linker_group(NAME RAM_REGION VMA RAM LMA ROM_REGION)
zephyr_linker_group(NAME TEXT_REGION GROUP ROM_REGION SYMBOL SECTION)
zephyr_linker_group(NAME RODATA_REGION GROUP ROM_REGION)
zephyr_linker_group(NAME DATA_REGION GROUP RAM_REGION SYMBOL SECTION)
zephyr_linker_group(NAME NOINIT_REGION GROUP RAM_REGION SYMBOL SECTION)
# should go to a relocation.cmake - from include/linker/rel-sections.ld - start
zephyr_linker_section(NAME .rel.plt HIDDEN)
@ -82,6 +107,8 @@ zephyr_linker_section(NAME .text GROUP TEXT_REGION)
zephyr_linker_section_configure(SECTION .rel.plt INPUT ".rel.iplt")
zephyr_linker_section_configure(SECTION .rela.plt INPUT ".rela.iplt")
include(${COMMON_ZEPHYR_LINKER_DIR}/kobject-text.cmake)
zephyr_linker_section_configure(SECTION .text INPUT ".TEXT.*")
zephyr_linker_section_configure(SECTION .text INPUT ".gnu.linkonce.t.*")
@ -107,9 +134,9 @@ include(${COMMON_ZEPHYR_LINKER_DIR}/thread-local-storage.cmake)
zephyr_linker_section(NAME .rodata GROUP RODATA_REGION)
zephyr_linker_section_configure(SECTION .rodata INPUT ".gnu.linkonce.r.*")
if(CONFIG_USERSPACE AND CONFIG_XIP)
zephyr_linker_section_configure(SECTION .rodata INPUT ".kobject_data.rodata*")
endif()
include(${COMMON_ZEPHYR_LINKER_DIR}/kobject-rom.cmake)
zephyr_linker_section_configure(SECTION .rodata ALIGN 4)
# ToDo - . = ALIGN(_region_min_align);
@ -119,13 +146,33 @@ zephyr_linker_section_configure(SECTION .rodata ALIGN 4)
zephyr_linker_section(NAME .ramfunc GROUP RAM_REGION SUBALIGN 8)
# Todo: handle MPU_ALIGN(_ramfunc_size);
# ToDo - handle if(CONFIG_USERSPACE)
if(CONFIG_USERSPACE)
# This is where the app_mem_partition stuff is going to be placed, once it
# is generated by gen_app_partitions.py. _app_smem has its own init-copy
# handling in z_data_copy, so put it in RAM_REGIOM rather than DATA_REGION
zephyr_linker_group(NAME APP_SMEM_GROUP GROUP RAM_REGION SYMBOL SECTION)
zephyr_linker_symbol(SYMBOL "_app_smem_size" EXPR "@__app_smem_group_size@")
zephyr_linker_symbol(SYMBOL "_app_smem_rom_start" EXPR "@__app_smem_group_load_start@")
zephyr_linker_section(NAME .data GROUP DATA_REGION)
zephyr_linker_section(NAME .bss VMA RAM LMA FLASH TYPE BSS)
zephyr_linker_section_configure(SECTION .bss INPUT COMMON)
zephyr_linker_section_configure(SECTION .bss INPUT ".kernel_bss.*")
#TODO: the skeletons includes <linker_sram_bss_relocate.ld> here
# As memory is cleared in words only, it is simpler to ensure the BSS
# section ends on a 4 byte boundary. This wastes a maximum of 3 bytes.
zephyr_linker_section_configure(SECTION .bss ALIGN 4)
include(${COMMON_ZEPHYR_LINKER_DIR}/common-noinit.cmake)
endif()
zephyr_linker_section(NAME .data GROUP DATA_REGION ALIGN_WITH_INPUT)
zephyr_linker_section_configure(SECTION .data INPUT ".kernel.*")
include(${COMMON_ZEPHYR_LINKER_DIR}/common-ram.cmake)
#include(kobject.ld)
include(${COMMON_ZEPHYR_LINKER_DIR}/kobject-data.cmake)
if(NOT CONFIG_USERSPACE)
zephyr_linker_section(NAME .bss VMA RAM LMA FLASH TYPE BSS)
@ -135,7 +182,7 @@ if(NOT CONFIG_USERSPACE)
# section ends on a 4 byte boundary. This wastes a maximum of 3 bytes.
zephyr_linker_section_configure(SECTION .bss ALIGN 4)
zephyr_linker_section(NAME .noinit GROUP RAM_REGION TYPE NOLOAD NOINIT)
zephyr_linker_section(NAME .noinit GROUP NOINIT_REGION TYPE NOLOAD NOINIT)
# This section is used for non-initialized objects that
# will not be cleared during the boot process.
zephyr_linker_section_configure(SECTION .noinit INPUT ".kernel_noinit.*")