diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 8906da2f62725..b9e0574ba3694 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -195,6 +195,11 @@ target_link_libraries(kernel zephyr_interface) endif() +# Optionally build kernel sources without LTO +if(CONFIG_KERNEL_NO_LTO) + include(${CMAKE_CURRENT_LIST_DIR}/kernel_no_lto.cmake) +endif() + add_dependencies(kernel zephyr_generated_headers) unset(libkernel) diff --git a/kernel/Kconfig b/kernel/Kconfig index 9e3be0b12abe4..f2cfdd62a3d59 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -1138,6 +1138,19 @@ endif # BOOTARGS endmenu +config KERNEL_NO_LTO + bool "Build selected kernel core files without LTO" + depends on LTO + depends on XIP + help + Some SoCs require kernel code to be placed in RAM, which makes link-time + optimization (LTO) unsuitable for these files (-fno-lto). 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. + rsource "Kconfig.device" rsource "Kconfig.vm" rsource "Kconfig.init" diff --git a/kernel/kernel_no_lto.cmake b/kernel/kernel_no_lto.cmake new file mode 100644 index 0000000000000..48b6abb47969e --- /dev/null +++ b/kernel/kernel_no_lto.cmake @@ -0,0 +1,50 @@ +# Copyright (c) 2025 ITE Corporation. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +# Optional script to disable LTO for kernel files + +message(STATUS "[no-LTO] Building kernel files without LTO") + +# Retrieve all source files from the kernel library target +if(TARGET kernel) + get_property(KERNEL_SRCS TARGET kernel PROPERTY SOURCES) +else() + message(WARNING "[no-LTO] kernel target not found, skipping") + return() +endif() + +# Check if there is a permitted kernel file that can enable LTO +if(COMMAND kernel_lto_allow_list) + kernel_lto_allow_list(ADDITIONAL_ALLOWLIST) +endif() + +# Default LTO allowlist +set(DEFAULT_LTO_ALLOWLIST init.c errno.c fatal.c) +# Append LTO allowlist +list(APPEND DEFAULT_LTO_ALLOWLIST ${ADDITIONAL_ALLOWLIST}) +# Setting LTO allowlist +set(LTO_ALLOWLIST ${DEFAULT_LTO_ALLOWLIST}) + +# Apply -fno-lto to all C source files, except for some initialization files +# (e.g. init.c, errno.c, fatal.c) and those that are less critical to be +# executed in RAM. These files can be excluded from -fno-lto by using +# ADDITIONAL_ALLOWLIST. +foreach(src ${KERNEL_SRCS}) + if(src MATCHES "\\.c$") + + # Skip if filename matches any in allowlist + set(skip FALSE) + foreach(allow ${LTO_ALLOWLIST}) + get_filename_component(basename ${src} NAME) + if("${basename}" STREQUAL "${allow}") + set(skip TRUE) + break() + endif() + endforeach() + + if(NOT skip) + set_source_files_properties(${src} PROPERTIES COMPILE_FLAGS "-fno-lto -g") + endif() + + endif() +endforeach() diff --git a/soc/ite/ec/it8xxx2/Kconfig b/soc/ite/ec/it8xxx2/Kconfig index 5531371682b57..a520104126ff9 100644 --- a/soc/ite/ec/it8xxx2/Kconfig +++ b/soc/ite/ec/it8xxx2/Kconfig @@ -228,6 +228,7 @@ config SOC_IT8XXX2_KERNEL_IN_RAM bool "Place kernel handling code in RAM" select SOC_IT8XXX2_USE_ILM select SOC_IT8XXX2_LIBRARY_TO_RAM + select KERNEL_NO_LTO if LTO help Place kernel handling code in ILM. This can significantly improve performance.