-
Notifications
You must be signed in to change notification settings - Fork 6.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LTO-compatible ISRs #66392
LTO-compatible ISRs #66392
Changes from all commits
2f6827f
d7fda08
6a3bde5
fb29ac6
9671738
cc081a3
bd18998
1325728
e1d1bcf
f5043e9
081cb45
a7e3985
753f61e
2f86480
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -213,6 +213,11 @@ endif() | |
# Apply the final optimization flag(s) | ||
zephyr_compile_options(${OPTIMIZATION_FLAG}) | ||
|
||
if(CONFIG_LTO) | ||
add_compile_options($<TARGET_PROPERTY:compiler,optimization_lto>) | ||
add_link_options($<TARGET_PROPERTY:linker,lto_arguments>) | ||
endif() | ||
|
||
# @Intent: Obtain compiler specific flags related to C++ that are not influenced by kconfig | ||
zephyr_compile_options($<$<COMPILE_LANGUAGE:CXX>:$<TARGET_PROPERTY:compiler-cpp,required>>) | ||
|
||
|
@@ -805,6 +810,10 @@ target_include_directories(${OFFSETS_LIB} PRIVATE | |
kernel/include | ||
${ARCH_DIR}/${ARCH}/include | ||
) | ||
|
||
# Make sure that LTO will never be enabled when compiling offsets.c | ||
set_source_files_properties(${OFFSETS_C_PATH} PROPERTIES COMPILE_OPTIONS $<TARGET_PROPERTY:compiler,prohibit_lto>) | ||
|
||
target_link_libraries(${OFFSETS_LIB} zephyr_interface) | ||
add_dependencies(zephyr_interface | ||
${SYSCALL_LIST_H_TARGET} | ||
|
@@ -1228,10 +1237,11 @@ if(CONFIG_GEN_ISR_TABLES) | |
# isr_tables.c is generated from ${ZEPHYR_LINK_STAGE_EXECUTABLE} by | ||
# gen_isr_tables.py | ||
add_custom_command( | ||
OUTPUT isr_tables.c | ||
OUTPUT isr_tables.c isr_tables_vt.ld isr_tables_swi.ld | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how will outputting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would export empty file with comment only that it is intentionally empty. Leaving it here is just to simplify the code later - just to be able to include it. |
||
COMMAND ${PYTHON_EXECUTABLE} | ||
${ZEPHYR_BASE}/scripts/build/gen_isr_tables.py | ||
--output-source isr_tables.c | ||
--linker-output-files isr_tables_vt.ld isr_tables_swi.ld | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this be depending on linker in use ? I tried a couple of samples, but all produced There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
answering my own question, in case others are wondering the same. It appears that in order to make use of this new feature, one must set: |
||
--kernel $<TARGET_FILE:${ZEPHYR_LINK_STAGE_EXECUTABLE}> | ||
--intlist-section .intList | ||
--intlist-section intList | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -391,6 +391,29 @@ config NOCACHE_MEMORY | |
|
||
menu "Interrupt Configuration" | ||
|
||
config ISR_TABLES_LOCAL_DECLARATION_SUPPORTED | ||
bool | ||
default y | ||
# Userspace is currently not supported | ||
depends on !USERSPACE | ||
# List of currently supported architectures | ||
depends on ARM || ARM64 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we have some more deps related to toolchain / linker ? or There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, I will add zephyr and gnuarmemb dependencies. I was not able to compile the code with llvm to test compatibility. |
||
# List of currently supported toolchains | ||
depends on "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "zephyr" || "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "gnuarmemb" | ||
|
||
config ISR_TABLES_LOCAL_DECLARATION | ||
bool "ISR tables created locally and placed by linker [EXPERIMENTAL]" | ||
depends on ISR_TABLES_LOCAL_DECLARATION_SUPPORTED | ||
select EXPERIMENTAL | ||
help | ||
Enable new scheme of interrupt tables generation. | ||
This is totally different generator that would create tables entries locally | ||
where the IRQ_CONNECT macro is called and then use the linker script to position it | ||
in the right place in memory. | ||
The most important advantage of such approach is that the generated interrupt tables | ||
are LTO compatible. | ||
The drawback is that the support on the architecture port is required. | ||
|
||
config DYNAMIC_INTERRUPTS | ||
bool "Installation of IRQs at runtime" | ||
help | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/* | ||
* Copyright (c) 2023 Nordic Semiconductor ASA | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
#if LINKER_ZEPHYR_FINAL | ||
INCLUDE zephyr/isr_tables_swi.ld | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nothing wrong, as it appears to me that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was trying to use include with preprocessor, the problem was that the file does not exist in a moment while the linker script is created. It will be created in build phase while it looks like the linker script is created during configuration phase of cmake. |
||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,3 +55,11 @@ if(CMAKE_C_COMPILER_ID STREQUAL "GNU") | |
endif() | ||
|
||
add_subdirectory_ifdef(CONFIG_XEN xen) | ||
|
||
if(CONFIG_GEN_SW_ISR_TABLE) | ||
if(CONFIG_DYNAMIC_INTERRUPTS) | ||
zephyr_linker_sources(RWDATA swi_tables.ld) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should sort key be used here and below ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think that the localization of the swi_tables in memory changes anything. Or maybe I do not get some nuanses? |
||
else() | ||
zephyr_linker_sources(RODATA swi_tables.ld) | ||
endif() | ||
endif() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/* | ||
* Copyright (c) 2023 Nordic Semiconductor ASA | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
#if LINKER_ZEPHYR_FINAL | ||
INCLUDE zephyr/isr_tables_swi.ld | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,15 +15,27 @@ | |
struct int_list_header { | ||
uint32_t table_size; | ||
uint32_t offset; | ||
#if IS_ENABLED(CONFIG_ISR_TABLES_LOCAL_DECLARATION) | ||
uint32_t swi_table_entry_size; | ||
uint32_t shared_isr_table_entry_size; | ||
uint32_t shared_isr_client_num_offset; | ||
#endif /* IS_ENABLED(CONFIG_ISR_TABLES_LOCAL_DECLARATION) */ | ||
}; | ||
|
||
/* These values are not included in the resulting binary, but instead form the | ||
* header of the initList section, which is used by gen_isr_tables.py to create | ||
* the vector and sw isr tables, | ||
*/ | ||
Z_GENERIC_SECTION(.irq_info) struct int_list_header _iheader = { | ||
Z_GENERIC_SECTION(.irq_info) __used struct int_list_header _iheader = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hopefully the compiler won't optimize out a global variable. So when exactly have you seen this var being optimized out, and did this change actually fix that ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We had an issue while enabling LTO during tests done by @LuDuda. The header was optimized out. This fix removes the issue. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That sounds more like an LTO toolchain bug then? As described, that's a gcc attribute that only controls whether or not the compiler will emit assembly for the object when it can prove it's unused (which it can't by definition here, since it's not static). Not necessarily worth a -1, but would be good to dig on this and try to get closer to a root cause. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know that using LTO can cause some surprising problems. In a matter of fact, with LTO, linker does some jobs that are more compiler related. Now it is linker job to prove that some functions, structures and others are not referenced. Note also, that we are adding -fffunction-sections and -fdata-sections - maybe this would help to remove this variable if unused. It surprises me a little as it is placed in predefined section anyway. But it is the effect we had and this was the fastest and simplest solution. |
||
.table_size = IRQ_TABLE_SIZE, | ||
.offset = CONFIG_GEN_IRQ_START_VECTOR, | ||
#if IS_ENABLED(CONFIG_ISR_TABLES_LOCAL_DECLARATION) | ||
.swi_table_entry_size = sizeof(struct _isr_table_entry), | ||
#if IS_ENABLED(CONFIG_SHARED_INTERRUPTS) | ||
.shared_isr_table_entry_size = sizeof(struct z_shared_isr_table_entry), | ||
.shared_isr_client_num_offset = offsetof(struct z_shared_isr_table_entry, client_num), | ||
#endif /* IS_ENABLED(CONFIG_SHARED_INTERRUPTS) */ | ||
#endif /* IS_ENABLED(CONFIG_ISR_TABLES_LOCAL_DECLARATION) */ | ||
}; | ||
|
||
/* These are placeholder tables. They will be replaced by the real tables | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This breaks old compilers:
@tejlmand how can we test this flag first, any good example to follow?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tentative fix submitted in #69058