Skip to content

Commit 128fea2

Browse files
committed
kernel: Add Kconfig option to disable LTO for kernel sources
Some SoCs require kernel code to be placed in RAM, which makes link-time optimization (LTO) unsuitable for these files. Disabling LTO allows the affected code to be linked as separate objects and placed in specific memory regions. Running kernel code from RAM can improve execution performance, especially for timing-critical routines or context switch paths. Signed-off-by: Tim Lin <tim2.lin@ite.corp-partner.google.com>
1 parent feae716 commit 128fea2

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

kernel/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,11 @@ target_link_libraries(kernel zephyr_interface)
195195

196196
endif()
197197

198+
# Optionally build kernel sources without LTO
199+
if(CONFIG_KERNEL_NO_LTO)
200+
include(${CMAKE_CURRENT_LIST_DIR}/kernel_no_lto.cmake)
201+
endif()
202+
198203
add_dependencies(kernel zephyr_generated_headers)
199204

200205
unset(libkernel)

kernel/Kconfig

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,27 @@ endif # BOOTARGS
11381138

11391139
endmenu
11401140

1141+
config KERNEL_NO_LTO
1142+
bool "Build selected kernel core files without LTO"
1143+
help
1144+
Some SoCs require kernel code to be placed in RAM, which makes link-time
1145+
optimization (LTO) unsuitable for these files (-fno-lto). Disabling LTO
1146+
allows the affected code to be linked as separate objects and placed in
1147+
specific memory regions.
1148+
1149+
Running kernel code from RAM can improve execution performance, especially
1150+
for timing-critical routines or context switch paths.
1151+
1152+
if KERNEL_NO_LTO
1153+
config KERNEL_LTO_ALLOWLIST
1154+
string "List of kernel source files to keep LTO"
1155+
help
1156+
List of kernel source filenames that should retain LTO even when
1157+
CONFIG_KERNEL_NO_LTO is enabled.
1158+
Example: CONFIG_KERNEL_LTO_ALLOWLIST="timer.c xxx.c"
1159+
1160+
endif # KERNEL_NO_LTO
1161+
11411162
rsource "Kconfig.device"
11421163
rsource "Kconfig.vm"
11431164
rsource "Kconfig.init"

kernel/kernel_no_lto.cmake

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
# Optional script to disable LTO for kernel files
4+
5+
message(STATUS "[no-LTO] Building kernel files without LTO")
6+
7+
# Retrieve all source files from the kernel library target
8+
if(TARGET kernel)
9+
get_property(KERNEL_SRCS TARGET kernel PROPERTY SOURCES)
10+
else()
11+
message(WARNING "[no-LTO] kernel target not found, skipping")
12+
return()
13+
endif()
14+
15+
# Split allowlist string into list
16+
if(DEFINED CONFIG_KERNEL_LTO_ALLOWLIST)
17+
separate_arguments(LTO_ALLOWLIST NATIVE_COMMAND "${CONFIG_KERNEL_LTO_ALLOWLIST}")
18+
endif()
19+
20+
# Apply -fno-lto to all C source files, except for initialization
21+
# and error handling modules (e.g. init.c, errno.c, fatal.c) and
22+
# CONFIG_KERNEL_LTO_ALLOWLIST
23+
foreach(src ${KERNEL_SRCS})
24+
if(src MATCHES "\\.c$" AND
25+
NOT src MATCHES "errno\\.c$" AND
26+
NOT src MATCHES "fatal\\.c$" AND
27+
NOT src MATCHES "init\\.c$")
28+
29+
# Skip if filename matches any in allowlist
30+
set(skip FALSE)
31+
foreach(allow ${LTO_ALLOWLIST})
32+
get_filename_component(basename ${src} NAME)
33+
if("${basename}" STREQUAL "${allow}")
34+
set(skip TRUE)
35+
break()
36+
endif()
37+
endforeach()
38+
39+
if(NOT skip)
40+
set_source_files_properties(${src} PROPERTIES COMPILE_FLAGS "-fno-lto -g")
41+
endif()
42+
43+
endif()
44+
endforeach()

0 commit comments

Comments
 (0)