Skip to content

Reduce SVCall priority on ARMv8-M - #1481

Open
jefftenney wants to merge 6 commits into
FreeRTOS:mainfrom
jefftenney:reduce-SVC-priority-ARMv8M
Open

jefftenney wants to merge 6 commits into
FreeRTOS:mainfrom
jefftenney:reduce-SVC-priority-ARMv8M

Conversation

@jefftenney

@jefftenney jefftenney commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Description

Instead of using the maximum priority for SVCall, use a priority just sufficient for:

  1. Preemption wherever SVCall may be used
  2. Automatic critical section for SVC execution

This PR sets the SVCall priority slightly above configMAX_SYSCALL_INTERRUPT_PRIORITY when starting the scheduler, then reduces the priority to be equal to configMAX_SYSCALL_INTERRUPT_PRIORITY afterward.

After this change, the developer can now assign some interrupts to higher priorities than SVC. This change aligns the ARMv8-M port more closely with FreeRTOS documentation about Cortex M ports. Specifically, the documentation indicates that these ports do not mask interrupts at priorities above configMAX_SYSCALL_INTERRUPT_PRIORITY.

Additional Change

Also require configMAX_SYSCALL_INTERRUPT_PRIORITY to have a zero in the least-significant implemented preemption-priority bit in TrustZone applications. This change prevents confusion caused by the hardware de-prioritizing non-secure interrupts, which coalesces neighboring preemption priority groups. This additional change also simplifies the determination of the optimal priority setting for SVCall during OS startup. Even with de-prioritizing, the optimal priority setting still preempts the critical section from which FreeRTOS starts.

How SVCall is Used in the ARMv8-M Port

The ARMv8-M port uses SVCall to:

  • Start the scheduler
  • Allocate/Free Secure Contexts in TZ applications
  • Raise MPU privilege for system calls in MPU applications (only in unprivileged tasks)
  • Task Yield (but not from an ISR) in MPU applications

Sufficient SVCall Priority

The only time SVCall needs a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY is when starting the scheduler. By design, the scheduler starts from within a critical section. The SVC instruction must preempt execution immediately, so its priority must be higher than the level masked for FreeRTOS critical sections in order to start the scheduler.

The other uses of SVCall occur only in task code, not from ISRs, and not from critical sections either. So there is no further need for SVCall to have a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY after FreeRTOS starts. ISRs don't allocate/free secure contexts, and ISRs already have MPU privilege, and ISRs don't use the yield call intended for task code. Further, users don't allocate/free secure contexts from critical sections, and they don't try to raise MPU privilege from critical sections either. That's because unprivileged tasks can't create a critical section. Finally, any attempt to yield from a critical section doesn't really make sense, MPU enabled or not. If a privileged task in an MPU application attempts to yield from within a critical section, they will rightly encounter the Hard Fault that comes when SVC cannot preempt execution. And if that user actually intended the yield to be delayed until after the critical section, that user has plenty of trivial workarounds.

Automatic Critical Section for SVCall execution

Setting the SVCall priority at configMAX_SYSCALL_INTERRUPT_PRIORITY allows the SVCall handler(s) to forgo creating a critical section manually. This slightly reduces execution time for any SVCall execution that actually needs a critical section. And by nature, SVCall executions are very fast, so any SVCall executions that don't need a critical section won't impact the system very much by effectively executing within one. And finally, future authors of SVCall services may unknowingly assume their code is already running with interrupts masked. With all of these considerations, we don't feel motivated to reduce the SVCall priority even further, for example to the minimum interrupt priority like PendSV uses.

Test Steps

Tested two existing applications - one TZ and one non-TZ. (Neither uses the MPU though.)

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

#1470

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

After this commit, configMAX_SYSCALL_INTERRUPT_PRIORITY must have a zero
in the least-significant implemented preemption-priority bit in
Trustzone applications.

This change ensures that interrupts of higher priority are not masked
as a result of non-secure interrupt de-prioritization.  For example,
consider a PE with 4 preemption-priority bits implemented.  If
configMAX_SYSCALL_INTERRUPT_PRIORITY is 0x50, then non-secure interrupts
that use priority 0x40 would also be masked by FreeRTOS critical
sections.  This is unexpected because 0x40 is a higher priority than
0x50.  De-prioritization changes both 0x50 and 0x40 into 0xA0.
@jefftenney jefftenney changed the title Reduce SV priority ar mv8 m Reduce SVCall priority on ARMv8-M Aug 26, 2026
@jefftenney

Copy link
Copy Markdown
Contributor Author

These changes test OK in some basic testing. One TZ application and one non-TZ application on STM32U585 (CM33).

Note that pre-existing TZ applications that have set configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY to an odd number now hit the new assert. That is probably a good thing. It will cause the developer to consider possible undesirable consequences of setting that least-significant bit.

@jefftenney
jefftenney marked this pull request as draft August 26, 2026 21:17
@sonarqubecloud

Copy link
Copy Markdown

@jefftenney

jefftenney commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

@aggarg We have a little more time on the ARMv8-M changes because we don't have a regression to fix like we did on the ARMv7-M MPU ports. The ARMv8-M ports have always used SVC priority 0. So we can take our time and do what we really think is best here.

Commit 27d34c7 shows the changes between a basic reduction in SVC priority and a more aggressive reduction that aligns better with FreeRTOS documentation regarding interrupt priorities above configMAX_SYSCALL_INTERRUPT_PRIORITY.

I think I like the more aggressive priority reduction.

@jefftenney
jefftenney marked this pull request as ready for review August 27, 2026 06:36
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.

1 participant