Skip to content

arch: arm: cortex_m: Allow relocation of vector table in RAM #87468

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

Merged

Conversation

Martinhoff-maker
Copy link
Collaborator

@Martinhoff-maker Martinhoff-maker commented Mar 21, 2025

The goal of this PR is to add the support of vector table relocation for cortex_m architecture in case the symbol CONFIG_SRAM_VECTOR_TABLE is set to yes and VTOR register is present.

Actually, as said in the current Kconfig.zephyr, the symbol CONFIG_SRAM_VECTOR_TABLE should place the vector table at the start of the SRAM (which indirectly place the irq_vector_table in the SRAM too).

CONFIG_SRAM_VECTOR_TABLE is currently only used by some boards/soc:

  • Nuvoton/npcm400_evb -> activate by default but don't see any use of the symbol? (might add maxdog988 NUVOTON NPCM platform maintainer on the review)
  • adi/max32 -> activate by default on all the max32 boards but no use of it as I see ? (might add MaureenHelm ADI maintener on the review) (edit : confirmation that this is not used by adi/max32)
  • renesas/smartbond/da1469x -> It has an m33 then have a VTOR register. Actually, it's set to yes by default in the defconfig file of the soc. The symbol is not used at all, but they do unconditionnaly reserve some space at the start of the SRAM (might add ioannis-karachalios RENESAS smartbond maintainer on the review) (edit : PR to remove the symbol)
  • st/stm32f0x -> they didn't have VTOR for the specific board that uses CONFIG_SRAM_VECTOR_TABLE (but it's where I take inspiration for this PR) so it should not enter into conflict. (might add erwango ST maintainer on the review) (edit : no problem, seen with mathieuchopstm)

It's hence not generic at all and would like to make this more generic for arm/cortex_m architecture which have VTOR register.

Considerations:

  • Vector table is not necessarily at the start of the ram region: in the case that you also use code relocation, it will place the vector table after the relocated code. Relocated code will always be at the start of the RAM SECTION because of the hard coded generated value in file with "gen_relocate_app.py". It can create quite big gaps and lose about the size of alignment of the vector table section (which is 0x200 for siwx917). Either we consider to not have the vector table at the start of the SRAM section while using code_relocation (what is done is my code actually), or we need to modify the script that relocates the code.
  • MPU is handled for the code relocation strategies and I think I need to handle this for the small ram section that I reserved for the Vector table. I have tried something concerning this consideration.
  • VTOR register can be modified in HAL files so this modification can be discarded later in the code execution.
  • VTOR can also be modified by MCU_BOOT with the software relay vector table and I did not handle that part for the moment.

@JarmouniA JarmouniA added area: ARM ARM (32-bit) Architecture RFC Request For Comments: want input from the community labels Mar 21, 2025
@Martinhoff-maker Martinhoff-maker force-pushed the siwx917_ram_execution branch 2 times, most recently from 92b1ec4 to b999504 Compare April 7, 2025 16:25
Copy link
Collaborator

@andyross andyross left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notes and nitpicks. Nothing fatal, feature is definitely useful. Though ideally I guess we'd want to combine this with a "dynamic direct interrupts" feature with an app-visible API. As it stands it requires an app to poke values directly into the table?


#define VECTOR_ADDRESS ((uintptr_t)_sram_vector_start)

static inline void relocate_vector_table(void)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any particular reason you can't just leave this in .data and rely on the pre-existing copy code?

Copy link
Collaborator Author

@Martinhoff-maker Martinhoff-maker Apr 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have some specific alignment constraint over the vector table. We would also like to have the _vector_table section at the start of the SRAM.

(void) memcpy(_sram_vector_start, _vector_start, vector_size);
SCB->VTOR = VECTOR_ADDRESS & VTOR_MASK;
barrier_dsync_fence_full();
barrier_isync_fence_full();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The barrier instructions shouldn't be needed. Interrupts don't get enabled until the switch to main, which involves a full context switch and implicit barriers from the PendSV. And we absolutely shouldn't be tossing exceptions out of early init code. :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with what you are saying. I have placed the barrier because of the arm documentation concerning the VTOR register (ARM doc). But I imagine that this is necessary when we would like to modify VTOR register at runtime ? Nevertheless, I've tried without the barrier and it works well.

#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
. = ALIGN( 1 << LOG2CEIL(4 * 64) );
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
. = ALIGN( 1 << LOG2CEIL(4 * 32) );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's generally preferred to put the alignment onto the chunk in the object file instead of manually here. Is that not already done?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally, the vector table alignment is already done in the linker script (vector_table.ld) and not in the object file (from vector_table.S and isr_table.c). That's why I still do the alignment here. But I wonder why it's not done before, will try to figure it out.

.attr = K_MEM_PARTITION_P_R_U_RX,
#else
.attr = K_MEM_PARTITION_P_RX_U_RX,
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels wrong. You're burning a whole MPU register to support this feature when kernel .data is already walled off from userspace threads.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking also to reuse an already configured MPU section like code relocation section (and it can also make sense to link CONFIG_CODE_DATA_RELOCATION_SRAM and CONFIG_SRAM_VECTOR_TABLE)

@Martinhoff-maker
Copy link
Collaborator Author

Thanks for the early feedback @andyross. Yes combining with "dynamic direct interrupts" was in my mind since I'm going later (in another PR) to make use of "dynamic interrupt" to place sw_isr_table also in RAM. I'm currently trying to resolve the compilations problem with mps3 and will update the PR with your feedback.

@@ -39,22 +39,40 @@ Z_GENERIC_SECTION(.vt_pointer_section) __attribute__((used)) void *_vector_table

#ifdef CONFIG_CPU_CORTEX_M_HAS_VTOR
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does CONFIG_SRAM_VECTOR_TABLE depend on CONFIG_CPU_CORTEX_M_HAS_VTOR? If yes, maybe the declaration of CONFIG_SRAM_VECTOR_TABLE should be updated.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No CONFIG_SRAM_VECTOR_TABLE can be used when CONFIG_CPU_CORTEX_M_HAS_VTOR is not set but it is a special case with STM32f0 board

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added a commit concerning this discussion.

#if defined(CONFIG_ARM_MPU_PXN) && defined(CONFIG_USERSPACE)
.attr = K_MEM_PARTITION_P_R_U_RX,
#else
.attr = K_MEM_PARTITION_P_RX_U_RX,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe _sram_vector_start only contains data. So, maybe K_MEM_PARTITION_P_RO_U_RO is sufficient? (unless it is strategy to coalesce the MPU segments)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually that's right, will change it to RO and will see if CI fails.

@ioannis-karachalios
Copy link
Collaborator

Hi @Martinhoff-maker,
There is a recent PR that drops the usage of CONFIG_SRAM_VECTOR_TABLE for the Smartbond devices. In fact, the SoC supports a custom mechanism for remapping IVT to SYSRAM. VTOR is implemented in M33 but not used, at all.

arch/Kconfig Outdated
depends on XIP
help
The option specifies that the vector table should be placed at the
start of SRAM instead of the start of flash.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The help should clarify further that this is a modification of a behavior resulting from eXecute in Place.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree, added.

arch/Kconfig Outdated
Comment on lines 581 to 582
The option specifies that the vector table will be placed at the
start of SRAM instead of the start of the flash when XIP is enabled.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The option specifies that the vector table will be placed at the
start of SRAM instead of the start of the flash when XIP is enabled.
When XiP is enabled, this option will result in the vector table being
relocated from Flash to SRAM.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree changed

#define VECTOR_ADDRESS ((uintptr_t)_vector_start)
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#endif
#endif /* CONFIG_SRAM_VECTOR_TABLE */

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not fan of that kind of commentary since the #ifdef block is really small... IMO it just add noise in the code readability...

Copy link
Collaborator

@jerome-pouiller jerome-pouiller Apr 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, the Linux Coding Style says "at the end of non-trivial #if or #ifdef block"

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's inside another ifdef and comes after an else, that's why I thought it would be clearer to have the comment.

size_t vector_size = (size_t)_vector_end - (size_t)_vector_start;

z_early_memcpy(_sram_vector_start, _vector_start, vector_size);
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#endif
#endif /* CONFIG_SRAM_VECTOR_TABLE */

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as the other one

Comment on lines 7 to 11
/* Vector table is not necessarily at the start of the ram region: in the case that you also use
* code relocation, it will place the vector table after the relocated code. Relocated code
* will always be at the start of the RAM SECTION because of the hardcoded generated value in file
* with "gen_relocate_app.py". It can create quite big gap and lose about the size of alignment
* of RAM Space
Copy link
Collaborator

@JarmouniA JarmouniA Apr 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/* Vector table is not necessarily at the start of the ram region: in the case that you also use
* code relocation, it will place the vector table after the relocated code. Relocated code
* will always be at the start of the RAM SECTION because of the hardcoded generated value in file
* with "gen_relocate_app.py". It can create quite big gap and lose about the size of alignment
* of RAM Space
/* Vector table is not necessarily at the start of the RAM region: in the case where Zephyr code
* relocation is used, the vector table is placed after the relocated code.
* Relocated code is always placed at the start of the RAM SECTION because of the hard-coded value
* generated by "gen_relocate_app.py" in the file. It can create quite a big gap and lose about the
* size of alignment in RAM space.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed

@MaureenHelm
Copy link
Member

CONFIG_SRAM_VECTOR_TABLE is currently only used by some boards/soc:

  • adi/max32 -> activate by default on all the max32 boards but no use of it as I see ? (might add MaureenHelm ADI maintener on the review)

That's correct, it's not being used by the max32 port. I think it was incorrectly copied from another port when the max32 port was first done.

@github-actions github-actions bot added the Release Notes To be mentioned in the release notes label Apr 23, 2025
@Martinhoff-maker Martinhoff-maker force-pushed the siwx917_ram_execution branch 2 times, most recently from 10b19d9 to 1d301ec Compare April 23, 2025 13:16
Copy link
Collaborator

@JarmouniA JarmouniA left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

@JarmouniA JarmouniA requested a review from tejlmand April 23, 2025 19:11
Martinhoff-maker added a commit to Martinhoff-maker/zephyr that referenced this pull request Apr 24, 2025
The symbol SRAM_VECTOR_TABLE is not used in the adi/max32 soc. Removed
it in order to clean up the Kconfig file and avoid confusion with the
upcoming new definition of SRAM_VECTOR_TABLE symbol. (PR zephyrproject-rtos#87468)

Signed-off-by: Martin Hoff <[email protected]>
Move SRAM_VECTOR_TABLE symbol from general Kconfig to Arch Kconfig
because it depends on the architecture possibility to relocate the
vector table.

Signed-off-by: Martin Hoff <[email protected]>
Allow to place the vector table section in SRAM with
CONFIG_SRAM_VECTOR_TABLE option for all cortex-m architecture that
have VTOR register.

Signed-off-by: Martin Hoff <[email protected]>
Add a basic test for vector table relocation to SRAM. This test
verifies that the vector table can be relocated to SRAM and that
the VTOR register correctly points to the SRAM address range.

Signed-off-by: Martin Hoff <[email protected]>
Copy link
Collaborator

@bjarki-andreasen bjarki-andreasen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good :)

@jhedberg jhedberg removed the RFC Request For Comments: want input from the community label Apr 25, 2025
@kartben kartben merged commit 64d20cf into zephyrproject-rtos:main Apr 25, 2025
30 checks passed
kartben pushed a commit that referenced this pull request Apr 25, 2025
The symbol SRAM_VECTOR_TABLE is not used in the adi/max32 soc. Removed
it in order to clean up the Kconfig file and avoid confusion with the
upcoming new definition of SRAM_VECTOR_TABLE symbol. (PR #87468)

Signed-off-by: Martin Hoff <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Architectures area: ARM ARM (32-bit) Architecture area: Kconfig area: Linker Scripts Release Notes To be mentioned in the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.