Skip to content

Reduce SVCall priority on ARMv7-M with MPU - #1470

Open
jefftenney wants to merge 2 commits into
FreeRTOS:mainfrom
jefftenney:reduce-SVCall-priority
Open

Reduce SVCall priority on ARMv7-M with MPU#1470
jefftenney wants to merge 2 commits into
FreeRTOS:mainfrom
jefftenney:reduce-SVCall-priority

Conversation

@jefftenney

@jefftenney jefftenney commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Description

Restore the original SVCall priority for the ARMv7-M MPU ports from before #832. This change reduces the SVCall preemption priority from zero (the highest) to a priority just higher than configMAX_SYSCALL_INTERRUPT_PRIORITY (numerically lower).

Make the same change to the ARMv8-M ports, even though those ports have always used zero (the highest priority) for SVCall until now. The corresponding changes to ARMv8-M should wait for a future effort.

After these changes, SVC no longer delays all interrupts. The developer can now assign some interrupts to higher priorities than SVC. This is important for MPU ports because they may use SVC to enter and exit system calls with MPU privilege.

Non-MPU ports don't need this change because SVC is used only to start FreeRTOS in those ports. The CM0 ports don't need this change because FreeRTOS masks all interrupts during kernel operations due to the lack of a BASEPRI register on that architecture. Those ports can't accommodate higher priority interrupts to interrupt kernel operations, so there's no need for them to accommodate higher priority interrupts to interrupt SVC executions.

Test Steps

Run any demo application on its target hardware or QEMU. Since SVC is used to start FreeRTOS, a successful startup indicates SVC is still working properly.

Checklist:

  • I have tested my changes. No regression in existing tests.
  • [N/A] I have modified and/or added unit-tests to cover the code changes in this Pull Request.

Related Issue

https://forums.freertos.org/t/cortex-m-mpu-ports-delay-high-priority-isrs/25115

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Restore the original SVCall priority for the ARMv7-M MPU ports from
before FreeRTOS#832.  This change reduces the SVCall preemption priority from
zero (the highest) to a priority just higher than
configMAX_SYSCALL_INTERRUPT_PRIORITY (numerically lower).

Make the same change to the ARMv8-M ports, even though those ports have
always used zero (the highest priority) for SVCall until now.
@sonarqubecloud

Copy link
Copy Markdown

@jefftenney jefftenney changed the title Reduce SVCall priority on ARMv7/8-M with MPU Reduce SVCall priority on ARMv7-M with MPU Aug 19, 2026
@jefftenney

Copy link
Copy Markdown
Contributor Author

@aggarg Here's the PR from the recent forum post.

I decided not to include ARMv8-M for now. I worry that non-secure interrupt deprioritization (see AIRCR.PRIS) can cause two neighboring preemption priorities to coalesce into one effective preemption priority. The simple method proposed in this PR for optimizing the preemption priority of SVC specifically chooses a priority that neighbors configMAX_SYSCALL_INTERRUPT_PRIORITY. If the least-significant implemented bit in configMAX_SYSCALL_INTERRUPT_PRIORITY happens to be set to 1, then the two neighboring preemption priorities would coalesce during deprioritization. Then SVC would fail to preempt an ISR it is supposed to preempt. I haven't actually tested that theory yet, but there's no need for it to hold up this PR. The ARMv8-M ports have always had SVC at priority zero (the max), so optimizing the SVC priority can be a future effort. The ARMv7-M MPU ports however, used to have an optimized SVC priority (before #832), so this PR restores that optimization.

Incidentally, if I'm right about preemption priorities coalescing, then even priority zero isn't completely safe for SVC. If the user sets configMAX_SYSCALL_INTERRUPT_PRIORITY to the maximum allowed priority (eg, 0x10 for four implemented bits), then it will coalesce during deprioritization. (Both will become preemption priority 0x80.) When I find some time I'll prove this one way or the other and report back.

@aggarg

aggarg commented Aug 20, 2026

Copy link
Copy Markdown
Member

Thank you for the change @jefftenney! What is the reason to keep SVC at configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL and not at configMAX_SYSCALL_INTERRUPT_PRIORITY?

Regarding the coalescing, the following table shows the mapping when 4-bits are implemented:

Non-Secure Firmware View Binary Representation Real Effective Hardware Priority
0x00 0000 0000 0x80
0x10 0001 0000 0x80 (Coalesced!)
0x20 0010 0000 0x90
0x30 0011 0000 0x90 (Coalesced!)
0x40 0100 0000 0xA0
0x50 0101 0000 0xA0 (Coalesced!)
0x60 0110 0000 0xB0
0x70 0111 0000 0xB0 (Coalesced!)
0x80 1000 0000 0xC0
0x90 1001 0000 0xC0 (Coalesced!)
0xA0 1010 0000 0xD0
0xB0 1011 0000 0xD0 (Coalesced!)
0xC0 1100 0000 0xE0
0xD0 1101 0000 0xE0 (Coalesced!)
0xE0 1110 0000 0xF0
0xF0 1111 0000 0xF0 (Coalesced!)

So priorities with the least significant implemented bit set must not be used, as they are equivalent to their counterparts with the least significant implemented bit cleared. May be we need to add an assert similar to this one to verify that configMAX_SYSCALL_INTERRUPT_PRIORITY does not have the least significant implemented bit set when Trust Zone is used. What do you think? This can certainly go in a different PR.

@ithinuel

Copy link
Copy Markdown

What is the reason to keep SVC at configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL and not at configMAX_SYSCALL_INTERRUPT_PRIORITY?

If my understanding of the FreeRTOS configuration is correct, if an interrupt running at configMAX_SYSCALL_INTERRUPT_PRIORITY makes a system call, SVCall at the same effective priority would be unable to pre-empt it and the SVC would escalate to HardFault. This is why SVC must be assigned a higher priority using configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL.

May be we need to add an assert similar to this one to verify that configMAX_SYSCALL_INTERRUPT_PRIORITY does not have the least significant implemented bit set when Trust Zone is used.

I would add that this assertion is needed only when TrustZone is used and AIRCR.PRIS is set. Otherwise, using those priorities is perfectly valid.

@aggarg

aggarg commented Aug 20, 2026

Copy link
Copy Markdown
Member

If my understanding of the FreeRTOS configuration is correct, if an interrupt running at configMAX_SYSCALL_INTERRUPT_PRIORITY makes a system call, SVCall at the same effective priority would be unable to pre-empt it and the SVC would escalate to HardFault. This is why SVC must be assigned a higher priority using configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL.

Right. Thanks for clarifying.

I would add that this assertion is needed only when TrustZone is used and AIRCR.PRIS is set.

We always set AIRCR.PRIS when TrustZone is used: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/portable/GCC/ARM_CM33/non_secure/port.c#L1189

@jefftenney

Copy link
Copy Markdown
Contributor Author

Thanks for that illustration table @aggarg. That's exactly what I had in my head. By any chance have you proven that it really happens as we suspect? It's surprising that the silicon offers to deprioritize the NS interrupts but then can't maintain relative preemption priorities among them. At the same time, I don't see how the silicon could do anything other than what we suspect.

May be we need to add an assert similar to this one to verify that configMAX_SYSCALL_INTERRUPT_PRIORITY does not have the least significant implemented bit set when Trust Zone is used. What do you think?

Yes, that would work nicely. But here's an alternative a little more backward compatible. We keep the existing rules for setting configMAX_SYSCALL_INTERRUPT_PRIORITY, but we modify the port code to choose an optimal priority for SVC during startup. That optimal priority would be either -1 or -2 from configMAX_SYSCALL_INTERRUPT_PRIORITY, to avoid coalescing with configMAX_SYSCALL_INTERRUPT_PRIORITY. Only if no suitable SVC priority exists would the port code assert. The assert would occur only if the developer set configMAX_SYSCALL_INTERRUPT_PRIORITY to the maximum allowed priority (eg, 0x10 for four bits). The developer would be forced to reduce configMAX_SYSCALL_INTERRUPT_PRIORITY (eg, 0x20) in this case.

This can certainly go in a different PR.

I don't have a strong opinion. The ARMv8-M stuff will take a little more consideration, but the ARMv7-M stuff is ready to go now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants