Skip to content

Commit d01c45b

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 d01c45b

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-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: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,28 @@ endif # BOOTARGS
11381138

11391139
endmenu
11401140

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