Skip to content

Commit bfae928

Browse files
author
Amanda Butler
authored
Merge pull request #811 from danny4478/development
Add PSA-SPM porting guide
2 parents d5263f4 + 4ca0bc5 commit bfae928

File tree

1 file changed

+260
-0
lines changed

1 file changed

+260
-0
lines changed

docs/porting/psa/spm.md

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
<h2 id="spm-port">PSA SPM</h2>
2+
3+
Secure Partition Manager (SPM) is a part of the PSA Firmware Framework that is responsible for isolating software in partitions, managing the execution of software within partitions and providing interprocessor communication (IPC) between partitions.
4+
5+
For more information about SPM, please refer to [the SPM overview page](/docs/development/apis/mbed-psa.html).
6+
7+
**This page gives guidelines for silicon partners wishing to have Secure Partition Manager capabilities**
8+
9+
### New target configuration
10+
11+
When adding a new target, a new root target node should be added to the `mbed-os/targets/targets.json` file. For PSA support, define specific PSA-related fields for this target:
12+
13+
1. Secure target must inherit from `SPE_Target` metatarget.
14+
2. Nonsecure target must inherit from `NSPE_Target`.
15+
3. Only for multicore architectures:
16+
- Both targets must add the `SPM_MAILBOX` component. You can read more about the mailbox mechanism in the [mailbox section](#mailbox).
17+
- Both targets must override the default configuration by specifying flash RAM and shared RAM regions. The [memory layout section](#memory-layout) explains this in more detail.
18+
- Secure target must declare its corresponding nonsecure target using the `deliver_to_target` field.
19+
20+
These is demonstrated in the example below:
21+
22+
```json
23+
"FUTURE_SEQUANA_M0_PSA": {
24+
"inherits": ["SPE_Target"],
25+
"components_add": ["SPM_MAILBOX"],
26+
"deliver_to_target": "FUTURE_SEQUANA_PSA",
27+
"overrides": {
28+
"secure-rom-start": "0x10000000",
29+
"secure-rom-size": "0x78000",
30+
"non-secure-rom-start": "0x10080000",
31+
"non-secure-rom-size": "0x78000",
32+
"secure-ram-start": "0x08000000",
33+
"secure-ram-size": "0x10000",
34+
"non-secure-ram-start": "0x08011000",
35+
"non-secure-ram-size": "0x36800",
36+
"shared-ram-start": "0x08010000",
37+
"shared-ram-size": "0x1000"
38+
}
39+
},
40+
"FUTURE_SEQUANA_PSA": {
41+
"inherits": ["NSPE_Target"],
42+
"components_add": ["SPM_MAILBOX"],
43+
"overrides": {
44+
"secure-rom-start": "0x10000000",
45+
"secure-rom-size": "0x78000",
46+
"non-secure-rom-start": "0x10080000",
47+
"non-secure-rom-size": "0x78000",
48+
"secure-ram-start": "0x08000000",
49+
"secure-ram-size": "0x10000",
50+
"non-secure-ram-start": "0x08011000",
51+
"non-secure-ram-size": "0x36800",
52+
"shared-ram-start": "0x08010000",
53+
"shared-ram-size": "0x1000"
54+
}
55+
}
56+
```
57+
58+
#### Memory layout
59+
60+
Typically, PSA platforms share the same RAM and flash between secure and nonsecure cores. To provide PSA isolation level 1 or higher, you need to partition both RAM and flash to secure and nonsecure parts, in a way the following image describes:
61+
62+
```text
63+
RAM
64+
+-----------+-------------+--------------------------------------------------+
65+
| Secure | Shared | Nonsecure |
66+
| RAM | RAM | RAM |
67+
+-----------+-------------+--------------------------------------------------+
68+
69+
Flash
70+
+-----------------------+----------------------------------------------------+
71+
| Secure | Nonsecure |
72+
| Flash | Flash |
73+
+-----------------------+----------------------------------------------------+
74+
75+
```
76+
77+
To achieve RAM and flash partitioning, you must add start and size values to a target configuration in `targets.json` as in the example above.
78+
79+
Note that for isolation levels higher than 1, on top of the partitioning between secure and nonsecure parts, secure flash and RAM must have an inner level of partitioning, creating sections per secure partition.
80+
81+
### Linker scripts
82+
83+
Linker scripts must include `MBED_ROM_START`, `MBED_ROM_SIZE`, `MBED_RAM_START` and `MBED_RAM_START` macros for defining memory regions. You can define a shared memory region by reserving RAM space for shared memory use. The shared memory location is target specific and depends on the memory protection scheme applied.
84+
85+
Typically, shared memory is located adjacent (before or after) to the nonsecure RAM, for saving MPU regions. The shared memory region is nonsecure memory that both cores use.
86+
87+
#### Linker script example for GCC_ARM compiler
88+
89+
```
90+
...
91+
#if !defined(MBED_ROM_START)
92+
#define MBED_ROM_START 0x10000000
93+
#endif
94+
95+
#if !defined(MBED_ROM_SIZE)
96+
#define MBED_ROM_SIZE 0x78000
97+
#endif
98+
99+
#if !defined(MBED_RAM_START)
100+
#define MBED_RAM_START 0x08000000
101+
#endif
102+
103+
#if !defined(MBED_RAM_SIZE)
104+
#define MBED_RAM_SIZE 0x10000
105+
#endif
106+
107+
/* The MEMORY section below describes the location and size of blocks of memory in the target.
108+
* Use this section to specify the memory regions available for allocation.
109+
*/
110+
MEMORY
111+
{
112+
ram (rwx) : ORIGIN = MBED_RAM_START, LENGTH = MBED_RAM_SIZE
113+
flash (rx) : ORIGIN = MBED_ROM_START, LENGTH = MBED_ROM_SIZE
114+
}
115+
...
116+
```
117+
118+
#### Linker script example for ARM compiler
119+
120+
```
121+
...
122+
#if !defined(MBED_ROM_START)
123+
#define MBED_ROM_START 0x10000000
124+
#endif
125+
126+
#if !defined(MBED_ROM_SIZE)
127+
#define MBED_ROM_SIZE 0x78000
128+
#endif
129+
130+
#if !defined(MBED_RAM_START)
131+
#define MBED_RAM_START 0x08000000
132+
#endif
133+
134+
#if !defined(MBED_RAM_SIZE)
135+
#define MBED_RAM_SIZE 0x10000
136+
#endif
137+
138+
#define MBED_RAM0_START MBED_RAM_START
139+
#define MBED_RAM0_SIZE 0x100
140+
#define MBED_RAM1_START (MBED_RAM_START + MBED_RAM0_SIZE)
141+
#define MBED_RAM1_SIZE (MBED_RAM_SIZE - MBED_RAM0_SIZE)
142+
143+
LR_IROM1 MBED_ROM_START MBED_ROM_SIZE {
144+
ER_IROM1 MBED_ROM_START MBED_ROM_SIZE {
145+
*.o (RESET, +First)
146+
*(InRoot$$Sections)
147+
.ANY (+RO)
148+
}
149+
RW_IRAM0 MBED_RAM0_START UNINIT MBED_RAM0_SIZE { ;no init section
150+
*(*nvictable)
151+
}
152+
RW_IRAM1 MBED_RAM1_START MBED_RAM1_SIZE {
153+
.ANY (+RW +ZI)
154+
}
155+
}
156+
...
157+
```
158+
159+
#### Linker script example for IAR compiler
160+
161+
```
162+
...
163+
if (!isdefinedsymbol(MBED_ROM_START)) {
164+
define symbol MBED_ROM_START = 0x10000000;
165+
}
166+
167+
if (!isdefinedsymbol(MBED_ROM_SIZE)) {
168+
define symbol MBED_ROM_SIZE = 0x78000;
169+
}
170+
171+
if (!isdefinedsymbol(MBED_RAM_START)) {
172+
define symbol MBED_RAM_START = 0x08000000;
173+
}
174+
175+
if (!isdefinedsymbol(MBED_RAM_SIZE)) {
176+
define symbol MBED_RAM_SIZE = 0x10000;
177+
}
178+
179+
/* RAM */
180+
define symbol __ICFEDIT_region_IRAM1_start__ = MBED_RAM_START;
181+
define symbol __ICFEDIT_region_IRAM1_end__ = (MBED_RAM_START + MBED_RAM_SIZE);
182+
183+
/* Flash */
184+
define symbol __ICFEDIT_region_IROM1_start__ = MBED_ROM_START;
185+
define symbol __ICFEDIT_region_IROM1_end__ = (MBED_ROM_START + MBED_ROM_SIZE);
186+
...
187+
```
188+
189+
### Mailbox
190+
191+
Mailbox is the mechanism used to implement Inter Processor Communication and **only relevant for multicore systems**. Mailbox is used by SPM for communicating with secure partitions from nonsecure processing environment.
192+
193+
#### Concepts
194+
195+
The mailbox mechanism is based on message queues and dispatcher threads. Each core has a single dispatcher thread and a single message queue. The dispatcher thread waits on a mailbox event. Once this event occurs, the dispatcher thread reads and runs "tasks" accumulated on its local message queue.
196+
197+
#### Requirements
198+
199+
The SPM mailbox mechanism requires the platform to have the following capabilities:
200+
201+
- IPC capabilities - The ability to notify the peer processor about an event (usually implemented with interrupts).
202+
- Ability to set a RAM section shared between the cores.
203+
204+
#### Porting
205+
206+
These are the guidelines you should follow if you have multicore systems:
207+
208+
- For each core, initialize, configure and enable the a mailbox event (usually an interrupt) at `SystemInit()`.
209+
- For each core, implement the IPC event handler (usually interrupt handler):
210+
- The handler must call an Arm callback function. Refer to [HAL functions section](#hal-functions) for more details.
211+
- For each core, implement the HAL function that notifies the peer processor about a mailbox event occurrence. This is a part of the HAL, and the section below explains this in more detail.
212+
- For each core, add the `SPM_MAILBOX` component field for its target node in the `mbed-os/targets/targets.json` file.
213+
214+
### HAL functions
215+
216+
Target specific code of silicon partners who wish to have SPM capabilities must:
217+
218+
- Implement a list of functions which are being called by SPM code.
219+
- Call Arm callback functions declared and documented in the HAL header files.
220+
221+
The HAL can be logically divided into two different fields:
222+
223+
#### Mailbox
224+
225+
This part of HAL allows you to implement a thin layer of the mailbox mechanism that is specific to your platform. You must only implement it if you have multicore systems.
226+
227+
#### Secure Processing Environment
228+
229+
This part of HAL allows you to apply your specific memory protection scheme. You can find a list of [these functions](https://os.mbed.com/docs/development/mbed-os-api-doxy/group___s_p_m.html).
230+
231+
### Memory protection
232+
233+
Target-specific code must implement the function *spm_hal_memory_protection_init()* called in SPM initialization. This function should apply memory protection schemes to ensure secure memory can only be accessed from secure-state.
234+
235+
The implementation of this function must be aligned with the SPM general guidelines, as the table below describes. This table describes the allowed operations (Read, Write and Execute) on the secure and nonsecure RAM and FLASH by each core:
236+
237+
- X means No access.
238+
- V means Must be able to access.
239+
- ? means it is up to the target.
240+
- X? means it is up to the target, preferably No access.
241+
242+
Processor access |Secure RAM |Secure FLASH|Nonsecure RAM |Nonsecure FLASH
243+
--------------------|------------------|------------|-------------------|----------------
244+
`Non Secure Read` | X | X | V | V
245+
`Non Secure Write` | X | X | V | ?
246+
`Non Secure Execute`| X | X | X? | V
247+
`Secure Read` | V | V | V | V
248+
`Secure Write` | V | V | V | ?
249+
`Secure Execute` | X? | V | X | ?
250+
251+
### Testing
252+
253+
Arm provides a list of tests to make sure the HAL functions are implemented according to requirements, and the porting is done correctly.
254+
255+
After finalizing the porting, execute the following tests:
256+
257+
- **tests-psa-spm_smoke:** This test will make sure that the porting of the mailbox mechanism (for dual core systems) is successful.
258+
- **tests-mbed_hal-spm:** This test will make sure the porting of the memory protection (*spm_hal_memory_protection_init()* implementation) makes the correct partitioning between secure RAM/Flash and nonsecure RAM/Flash.
259+
260+
We recommended you leave the memory protection part (*spm_hal_memory_protection_init()* implementation) to the end of the porting. First, implement and test other HAL functions. After these tests pass, implement *spm_hal_memory_protection_init()*, and run the entire test suite again, including the memory protection related tests.

0 commit comments

Comments
 (0)