Part IV: Memory Protection
QuantumRT integrates robust Memory Protection capabilities designed to enhance system stability, security, and reliability by isolating threads and system resources. Utilizing the hardware MPU available on ARM Cortex processors, QuantumRT provides key capabilities described in this chapter.
Privileged and Unprivileged Modes
QuantumRT operates using two execution levels:
Privileged Mode - Full access to system memory, peripherals, and kernel functions
Unprivileged Mode - Restricted access enforced by the MPU
Threads in QuantumRT can run in either mode, while the kernel, idle thread, and ISRs execute in privileged mode. This ensures user threads cannot directly modify critical system resources, significantly enhancing system stability and security.
Stack Isolation
QuantumRT isolates individual thread stacks, preventing unprivileged threads from inadvertently accessing or corrupting each other’s memory. Unprivileged threads have no access to kernel memory.
Memory Regions
QuantumRT defines a fixed set of memory regions configured at thread creation. These regions isolate ROM, RAM, and threads. Total of six memory regions are defined as follows:
Region Type |
Memory Type |
Shareable |
Execute |
Privileged Access |
Unprivileged Access |
|---|---|---|---|---|---|
ROM |
Normal, Write-Through |
No |
Yes |
Read-Only |
Read-Only |
RAM |
Normal, Write-Back Write-Allocate¹ |
Yes |
No |
Read/Write |
Read/Write |
QRT ROM |
Normal, Write-Through |
No |
Yes |
Read-Only |
No Access |
QRT RAM |
Normal, Write-Back Write-Allocate¹ |
No |
No |
Read/Write |
No Access |
Thread Metadata |
Device / Device-nGnRE |
No |
No |
Read/Write², Read-Only³ |
Read-Only |
Thread Stack |
Normal, Write-Back¹ |
No |
No |
Read/Write |
Read/Write |
Note
Privileged threads have the architectures default memory map with the regions overridden as defined in the table Memory Map above. Unprivileged threads have no peripheral access by default.
Any unprivileged peripheral access must be performed with the use of System Call Extension (see qrt_syscall_register() and qrt_syscall_invoke()) or the thread memory region must be explicitly added.
Additional thread memory regions can be added with qrt_mpu_threadregionadd() and removed with qrt_mpu_threadregionremove() as needed.
Adding and removing regions is only permitted from privileged threads.
Memory Fault Reporting
QuantumRT provides detailed memory fault reporting to assist developers in diagnosing and resolving MPU violations efficiently. When an MPU fault occurs, QuantumRT captures and reports the following critical details:
Faulting Thread - The identifier of the thread that caused the violation
Fault Address - The memory address that triggered the fault
Faulting Instruction - The Program Counter (PC) at the time of the fault
Fault Status Code - The raw Configurable Fault Status Register (CFSR) value for full debugging insight
The most recent fault details are passed to the custom fault callback if set using qrt_mpu_faultcallbackset().
Upon detection, the violating thread is terminated, and all mutexes it holds are unlocked to prevent deadlocks.
Note
Memory Fault reporting is not available on ARMv6-M and ARMv8-M Baseline.
Configuration
Memory Protection can be enabled or disabled using the configuration option QRT_CFG_MPU_ENABLE.
The number of regions is defined with the configuration option QRT_CFG_MPU_ENTRIES.
QuantumRT requires a correctly configured linker script to define memory regions and ensure proper task and kernel placement. The following symbols must be defined in the linker script:
__ROM_BASE- Start address of the ROM region__ROM_SIZE- Size of the ROM region__RAM_BASE- Start address of the RAM region__RAM_SIZE- Size of the RAM region__QRT_ROM_BASE- Start address of the QuantumRT kernel ROM region__QRT_ROM_SIZE- Size of the QuantumRT kernel ROM region__QRT_RAM_BASE- Start address of the QuantumRT kernel RAM region__QRT_RAM_SIZE- Size of the QuantumRT kernel RAM region
Due to hardware requirements memory region alignment and sizes must conform to MPU specifications:
Region sizes must be a power of two (e.g., 32B, 64B, 128B, etc.)
Regions must be aligned to their size (e.g., a 4KB region must be aligned to a 4KB boundary) for ARMv6 and ARMv7
Regions must be aligned to 32 bytes for ARMv8
These requirements apply to the symbols introduced above as well.
Users are encouraged to refer to the demo application for a working example of a linker script configuration. The linker script should be modified as needed to match the hardware requirements.