Skip to content

Commit 128698f

Browse files
bjorniuppsalakartben
authored andcommitted
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 <[email protected]>
1 parent 6c197f8 commit 128698f

23 files changed

+357
-75
lines changed

CMakeLists.txt

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ set(ZEPHYR_CURRENT_LINKER_PASS 0)
7171
set(ZEPHYR_CURRENT_LINKER_CMD linker_zephyr_pre${ZEPHYR_CURRENT_LINKER_PASS}.cmd)
7272
set(ZEPHYR_LINK_STAGE_EXECUTABLE zephyr_pre${ZEPHYR_CURRENT_LINKER_PASS})
7373

74+
# Make kconfig variables available to the linker script generator
75+
zephyr_linker_include_generated(KCONFIG ${CMAKE_CURRENT_BINARY_DIR}/.config)
76+
77+
# The linker generator also needs sections.h to be able to access e.g. _APP_SMEM_SECTION_NAME
78+
# for linkerscripts that do not support c-preprocessing.
79+
zephyr_linker_include_generated(HEADER ${ZEPHYR_BASE}/include/zephyr/linker/sections.h)
80+
81+
zephyr_linker_include_var(VAR CMAKE_VERBOSE_MAKEFILE VALUE ${CMAKE_VERBOSE_MAKEFILE})
82+
7483
# ZEPHYR_PREBUILT_EXECUTABLE is used outside of this file, therefore keep the
7584
# existing variable to allow slowly cleanup of linking stage handling.
7685
# Three stage linking active: pre0 -> pre1 -> final, this will correspond to `pre1`
@@ -935,6 +944,8 @@ add_custom_target(${DEVICE_API_LD_TARGET}
935944
${DEVICE_API_LINKER_SECTIONS_CMAKE}
936945
)
937946

947+
zephyr_linker_include_generated(CMAKE ${DEVICE_API_LINKER_SECTIONS_CMAKE})
948+
938949
# Add a pseudo-target that is up-to-date when all generated headers
939950
# are up-to-date.
940951

@@ -1134,14 +1145,20 @@ if(NOT EXISTS ${LINKER_SCRIPT})
11341145
endif()
11351146

11361147
if(CONFIG_USERSPACE)
1137-
set(APP_SMEM_ALIGNED_LD "${PROJECT_BINARY_DIR}/include/generated/app_smem_aligned.ld")
1138-
set(APP_SMEM_UNALIGNED_LD "${PROJECT_BINARY_DIR}/include/generated/app_smem_unaligned.ld")
1148+
if(CONFIG_CMAKE_LINKER_GENERATOR)
1149+
set(APP_SMEM_LD_EXT "cmake")
1150+
else()
1151+
set(APP_SMEM_LD_EXT "ld")
1152+
endif()
1153+
1154+
set(APP_SMEM_ALIGNED_LD "${PROJECT_BINARY_DIR}/include/generated/app_smem_aligned.${APP_SMEM_LD_EXT}")
1155+
set(APP_SMEM_UNALIGNED_LD "${PROJECT_BINARY_DIR}/include/generated/app_smem_unaligned.${APP_SMEM_LD_EXT}")
11391156

11401157
if(CONFIG_LINKER_USE_PINNED_SECTION)
11411158
set(APP_SMEM_PINNED_ALIGNED_LD
1142-
"${PROJECT_BINARY_DIR}/include/generated/app_smem_pinned_aligned.ld")
1159+
"${PROJECT_BINARY_DIR}/include/generated/app_smem_pinned_aligned.${APP_SMEM_LD_EXT}")
11431160
set(APP_SMEM_PINNED_UNALIGNED_LD
1144-
"${PROJECT_BINARY_DIR}/include/generated/app_smem_pinned_unaligned.ld")
1161+
"${PROJECT_BINARY_DIR}/include/generated/app_smem_pinned_unaligned.${APP_SMEM_LD_EXT}")
11451162

11461163
if(NOT CONFIG_LINKER_GENERIC_SECTIONS_PRESENT_AT_BOOT)
11471164
# The libc partition may hold symbols that are required during boot process,
@@ -1206,9 +1223,11 @@ if(CONFIG_USERSPACE)
12061223

12071224
set(APP_SMEM_UNALIGNED_LIB app_smem_unaligned_output_obj_renamed_lib)
12081225
list(APPEND LINKER_PASS_${ZEPHYR_CURRENT_LINKER_PASS}_DEFINE "LINKER_APP_SMEM_UNALIGNED")
1209-
endif()
12101226

1211-
if (CONFIG_USERSPACE)
1227+
foreach(dep ${APP_SMEM_UNALIGNED_LD} ${APP_SMEM_PINNED_UNALIGNED_LD})
1228+
zephyr_linker_include_generated(CMAKE ${dep} PASS LINKER_APP_SMEM_UNALIGNED)
1229+
endforeach()
1230+
12121231
add_custom_command(
12131232
OUTPUT ${APP_SMEM_ALIGNED_LD} ${APP_SMEM_PINNED_ALIGNED_LD}
12141233
COMMAND ${PYTHON_EXECUTABLE}
@@ -1228,6 +1247,9 @@ if (CONFIG_USERSPACE)
12281247
COMMAND_EXPAND_LISTS
12291248
COMMENT "Generating app_smem_aligned linker section"
12301249
)
1250+
foreach(dep ${APP_SMEM_ALIGNED_LD} ${APP_SMEM_PINNED_ALIGNED_LD})
1251+
zephyr_linker_include_generated(CMAKE ${dep} PASS NOT LINKER_APP_SMEM_UNALIGNED)
1252+
endforeach()
12311253
endif()
12321254

12331255
if(CONFIG_USERSPACE)
@@ -1335,6 +1357,13 @@ if(CONFIG_USERSPACE)
13351357
DEPENDS
13361358
${KOBJECT_LINKER_HEADER_DATA}
13371359
)
1360+
1361+
# gen_kobject_placeholders.py generates linker-kobject-prebuild-data.h,
1362+
# linker-kobject-prebuild-priv-stacks.h and linker-kobject-prebuild-rodata.h
1363+
foreach(ext "-data.h" "-priv-stacks.h" "-rodata.h")
1364+
string(REGEX REPLACE "-data.h$" ${ext} file ${KOBJECT_LINKER_HEADER_DATA})
1365+
zephyr_linker_include_generated(HEADER ${file} PASS LINKER_ZEPHYR_PREBUILT LINKER_ZEPHYR_FINAL)
1366+
endforeach()
13381367
endif()
13391368

13401369
if(CONFIG_USERSPACE OR CONFIG_DEVICE_DEPS)

cmake/linker/armlink/target.cmake

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ macro(configure_linker_script linker_script_gen linker_pass_define)
3636
${STEERING_FILE}
3737
${STEERING_C}
3838
COMMAND ${CMAKE_COMMAND}
39-
-C ${DEVICE_API_LINKER_SECTIONS_CMAKE}
4039
-C ${cmake_linker_script_settings}
4140
-DPASS="${linker_pass_define}"
4241
${STEERING_FILE_ARG}

cmake/linker/ld/target.cmake

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,12 @@ macro(configure_linker_script linker_script_gen linker_pass_define)
3131
DEPENDS
3232
${extra_dependencies}
3333
${cmake_linker_script_settings}
34+
${DEVICE_API_LD_TARGET}
3435
COMMAND ${CMAKE_COMMAND}
35-
-C ${DEVICE_API_LINKER_SECTIONS_CMAKE}
3636
-C ${cmake_linker_script_settings}
3737
-DPASS="${linker_pass_define}"
3838
-DOUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/${linker_script_gen}
3939
-P ${ZEPHYR_BASE}/cmake/linker/ld/ld_script.cmake
40-
DEPENDS ${DEVICE_API_LD_TARGET}
4140
)
4241
else()
4342
set(template_script_defines ${linker_pass_define})

cmake/linker/linker_script_common.cmake

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,10 @@ function(do_var_replace_in res_ptr src)
733733
# can't warn here because we can't check for what is relevant in this pass
734734
# message(WARNING "Missing definition for ${match}")
735735
endif()
736-
message("Replacing ${match} with ${value}")
736+
737+
if(CMAKE_VERBOSE_MAKEFILE)
738+
message("Using variable ${match} with value ${value}")
739+
endif()
737740
string(REPLACE "${match}" "${value}" src "${src}")
738741
endforeach()
739742
set(${res_ptr} "${src}" PARENT_SCOPE)

cmake/linker_script/arm/linker.cmake

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,38 @@
11
set(COMMON_ZEPHYR_LINKER_DIR ${ZEPHYR_BASE}/cmake/linker_script/common)
22

3-
set_ifndef(region_min_align CONFIG_CUSTOM_SECTION_MIN_ALIGN_SIZE)
3+
# This should be different for cortex_r or cortex_a....
4+
# cut from zephyr/include/zephyr/arch/arm/cortex_m/scripts/linker.ld
5+
if(DEFINED CONFIG_CUSTOM_SECTION_MIN_ALIGN_SIZE)
6+
set_ifndef(region_min_align ${CONFIG_CUSTOM_SECTION_MIN_ALIGN_SIZE})
7+
endif()
48

59
# Set alignment to CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE if not set above
610
# to make linker section alignment comply with MPU granularity.
7-
set_ifndef(region_min_align CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE)
11+
if(DEFINED CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE)
12+
set_ifndef(region_min_align ${CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE})
13+
endif()
814

915
# If building without MPU support, use default 4-byte alignment.. if not set above.
1016
set_ifndef(region_min_align 4)
1117

18+
zephyr_linker_include_var(VAR region_min_align)
19+
if((NOT DEFINED CONFIG_CUSTOM_SECTION_ALIGN) AND DEFINED CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT)
20+
# define MPU_ALIGN(region_size) \
21+
# . = ALIGN(_region_min_align); \
22+
# . = ALIGN( 1 << LOG2CEIL(region_size))
23+
# Handling this requires us to handle log2ceil() in iar linker since the size
24+
# isn't known until then.
25+
set(MPU_ALIGN_BYTES ${region_min_align})
26+
#message(WARNING "We can not handle . = ALIGN( 1 << LOG2CEIL(region_size)) ")
27+
else()
28+
set(MPU_ALIGN_BYTES ${region_min_align})
29+
endif()
30+
# The APP_SHARED_ALIGN and SMEM_PARTITION_ALIGN macros are defined as
31+
# ". = ALIGN(...)" things.
32+
# the cmake generator stuff needs an align-size in bytes so:
33+
zephyr_linker_include_var(VAR APP_SHARED_ALIGN_BYTES VALUE ${region_min_align})
34+
zephyr_linker_include_var(VAR SMEM_PARTITION_ALIGN_BYTES VALUE ${MPU_ALIGN_BYTES})
35+
1236
# Note, the `+ 0` in formulas below avoids errors in cases where a Kconfig
1337
# variable is undefined and thus expands to nothing.
1438
math(EXPR FLASH_ADDR
@@ -59,6 +83,7 @@ zephyr_linker_group(NAME RAM_REGION VMA RAM LMA ROM_REGION)
5983
zephyr_linker_group(NAME TEXT_REGION GROUP ROM_REGION SYMBOL SECTION)
6084
zephyr_linker_group(NAME RODATA_REGION GROUP ROM_REGION)
6185
zephyr_linker_group(NAME DATA_REGION GROUP RAM_REGION SYMBOL SECTION)
86+
zephyr_linker_group(NAME NOINIT_REGION GROUP RAM_REGION SYMBOL SECTION)
6287

6388
# should go to a relocation.cmake - from include/linker/rel-sections.ld - start
6489
zephyr_linker_section(NAME .rel.plt HIDDEN)
@@ -82,6 +107,8 @@ zephyr_linker_section(NAME .text GROUP TEXT_REGION)
82107
zephyr_linker_section_configure(SECTION .rel.plt INPUT ".rel.iplt")
83108
zephyr_linker_section_configure(SECTION .rela.plt INPUT ".rela.iplt")
84109

110+
include(${COMMON_ZEPHYR_LINKER_DIR}/kobject-text.cmake)
111+
85112
zephyr_linker_section_configure(SECTION .text INPUT ".TEXT.*")
86113
zephyr_linker_section_configure(SECTION .text INPUT ".gnu.linkonce.t.*")
87114

@@ -107,9 +134,9 @@ include(${COMMON_ZEPHYR_LINKER_DIR}/thread-local-storage.cmake)
107134

108135
zephyr_linker_section(NAME .rodata GROUP RODATA_REGION)
109136
zephyr_linker_section_configure(SECTION .rodata INPUT ".gnu.linkonce.r.*")
110-
if(CONFIG_USERSPACE AND CONFIG_XIP)
111-
zephyr_linker_section_configure(SECTION .rodata INPUT ".kobject_data.rodata*")
112-
endif()
137+
138+
include(${COMMON_ZEPHYR_LINKER_DIR}/kobject-rom.cmake)
139+
113140
zephyr_linker_section_configure(SECTION .rodata ALIGN 4)
114141

115142
# ToDo - . = ALIGN(_region_min_align);
@@ -119,13 +146,33 @@ zephyr_linker_section_configure(SECTION .rodata ALIGN 4)
119146
zephyr_linker_section(NAME .ramfunc GROUP RAM_REGION SUBALIGN 8)
120147
# Todo: handle MPU_ALIGN(_ramfunc_size);
121148

122-
# ToDo - handle if(CONFIG_USERSPACE)
149+
if(CONFIG_USERSPACE)
150+
# This is where the app_mem_partition stuff is going to be placed, once it
151+
# is generated by gen_app_partitions.py. _app_smem has its own init-copy
152+
# handling in z_data_copy, so put it in RAM_REGIOM rather than DATA_REGION
153+
zephyr_linker_group(NAME APP_SMEM_GROUP GROUP RAM_REGION SYMBOL SECTION)
154+
zephyr_linker_symbol(SYMBOL "_app_smem_size" EXPR "@__app_smem_group_size@")
155+
zephyr_linker_symbol(SYMBOL "_app_smem_rom_start" EXPR "@__app_smem_group_load_start@")
156+
157+
158+
zephyr_linker_section(NAME .bss VMA RAM LMA FLASH TYPE BSS)
159+
zephyr_linker_section_configure(SECTION .bss INPUT COMMON)
160+
zephyr_linker_section_configure(SECTION .bss INPUT ".kernel_bss.*")
161+
162+
#TODO: the skeletons includes <linker_sram_bss_relocate.ld> here
163+
164+
# As memory is cleared in words only, it is simpler to ensure the BSS
165+
# section ends on a 4 byte boundary. This wastes a maximum of 3 bytes.
166+
zephyr_linker_section_configure(SECTION .bss ALIGN 4)
167+
168+
include(${COMMON_ZEPHYR_LINKER_DIR}/common-noinit.cmake)
169+
endif()
123170

124-
zephyr_linker_section(NAME .data GROUP DATA_REGION)
171+
zephyr_linker_section(NAME .data GROUP DATA_REGION ALIGN_WITH_INPUT)
125172
zephyr_linker_section_configure(SECTION .data INPUT ".kernel.*")
126173

127174
include(${COMMON_ZEPHYR_LINKER_DIR}/common-ram.cmake)
128-
#include(kobject.ld)
175+
include(${COMMON_ZEPHYR_LINKER_DIR}/kobject-data.cmake)
129176

130177
if(NOT CONFIG_USERSPACE)
131178
zephyr_linker_section(NAME .bss VMA RAM LMA FLASH TYPE BSS)
@@ -135,7 +182,7 @@ if(NOT CONFIG_USERSPACE)
135182
# section ends on a 4 byte boundary. This wastes a maximum of 3 bytes.
136183
zephyr_linker_section_configure(SECTION .bss ALIGN 4)
137184

138-
zephyr_linker_section(NAME .noinit GROUP RAM_REGION TYPE NOLOAD NOINIT)
185+
zephyr_linker_section(NAME .noinit GROUP NOINIT_REGION TYPE NOLOAD NOINIT)
139186
# This section is used for non-initialized objects that
140187
# will not be cleared during the boot process.
141188
zephyr_linker_section_configure(SECTION .noinit INPUT ".kernel_noinit.*")
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
# The contents of this file is based on include/zephyr/linker/common-noinit.ld
3+
# Please keep in sync
4+
5+
zephyr_linker_section(NAME .noinit GROUP NOINIT_REGION TYPE NOLOAD NOINIT)
6+
7+
if(CONFIG_USERSPACE)
8+
zephyr_linker_section_configure(
9+
SECTION .noinit
10+
INPUT ".user_stacks*"
11+
SYMBOLS z_user_stacks_start z_user_stacks_end)
12+
13+
endif()
14+
# TODO: #include <snippets-noinit.ld>
15+
include(${COMMON_ZEPHYR_LINKER_DIR}/kobject-priv-stacks.cmake)

0 commit comments

Comments
 (0)