-
Notifications
You must be signed in to change notification settings - Fork 178
Add PSA-SPM porting guide #811
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
Changes from 4 commits
a9d4851
460e631
0f65576
333c7c9
3a82ffe
7b1a526
9457e5e
fe5fcb3
4ca0bc5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,257 @@ | ||
<h2 id="spm-port">PSA SPM</h2> | ||
|
||
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. | ||
|
||
For more information about SPM, please refer to [the SPM overview page](/docs/development/apis/mbed-psa.html). | ||
|
||
**This page gives guidelines for silicon partners wishing to have Secure Partition Manager capabilities** | ||
|
||
### Memory layout | ||
|
||
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 in a way the following image describes: | ||
|
||
```text | ||
RAM | ||
+-----------+-------------+--------------------------------------------------+ | ||
| Secure | Shared | Non-Secure | | ||
| RAM | RAM | RAM | | ||
+-----------+-------------+--------------------------------------------------+ | ||
|
||
Flash | ||
+-----------------------+----------------------------------------------------+ | ||
| Secure | Non-Secure | | ||
| Flash | Flash | | ||
+-----------------------+----------------------------------------------------+ | ||
|
||
``` | ||
|
||
To achieve RAM and flash partitioning, you must add start and size values to a target configuration in `targets.json`. You can do this with the following steps: | ||
|
||
1. Secure target must inherit from `SPE_Target` meta-target. | ||
2. Nonsecure target must inherit from `NSPE_Target`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @AnotherButler what is the right way of writing, |
||
3. Both targets must override the default configuration by specifying flash RAM and shared RAM regions. | ||
|
||
```json | ||
"FUTURE_SEQUANA_M0_PSA": { | ||
"inherits": ["SPE_Target", "FUTURE_SEQUANA_M0"], | ||
"extra_labels_add": ["PSOC6_PSA"], | ||
"components_add": ["SPM_MAILBOX"], | ||
"macros_add": ["PSOC6_DYNSRM_DISABLE=1"], | ||
"deliver_to_target": "FUTURE_SEQUANA_PSA", | ||
"overrides": { | ||
"secure-rom-start": "0x10000000", | ||
"secure-rom-size": "0x78000", | ||
"non-secure-rom-start": "0x10080000", | ||
"non-secure-rom-size": "0x78000", | ||
"secure-ram-start": "0x08000000", | ||
"secure-ram-size": "0x10000", | ||
"non-secure-ram-start": "0x08011000", | ||
"non-secure-ram-size": "0x36800", | ||
"shared-ram-start": "0x08010000", | ||
"shared-ram-size": "0x1000" | ||
} | ||
}, | ||
"FUTURE_SEQUANA_PSA": { | ||
"inherits": ["NSPE_Target", "FUTURE_SEQUANA"], | ||
"sub_target": "FUTURE_SEQUANA_M0_PSA", | ||
"extra_labels_remove": ["CORDIO"], | ||
"extra_labels_add": ["PSOC6_PSA"], | ||
"components_add": ["SPM_MAILBOX"], | ||
"macros_add": ["PSOC6_DYNSRM_DISABLE=1"], | ||
"overrides": { | ||
"secure-rom-start": "0x10000000", | ||
"secure-rom-size": "0x78000", | ||
"non-secure-rom-start": "0x10080000", | ||
"non-secure-rom-size": "0x78000", | ||
"secure-ram-start": "0x08000000", | ||
"secure-ram-size": "0x10000", | ||
"non-secure-ram-start": "0x08011000", | ||
"non-secure-ram-size": "0x36800", | ||
"shared-ram-start": "0x08010000", | ||
"shared-ram-size": "0x1000" | ||
} | ||
} | ||
``` | ||
|
||
<span class="notes">**Note:** Only multicore architectures require a shared memory region.</span> | ||
|
||
### Linker scripts | ||
|
||
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. | ||
|
||
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. | ||
|
||
#### Linker script example for GCC_ARM | ||
|
||
``` | ||
... | ||
#if !defined(MBED_ROM_START) | ||
#define MBED_ROM_START 0x10000000 | ||
#endif | ||
|
||
#if !defined(MBED_ROM_SIZE) | ||
#define MBED_ROM_SIZE 0x78000 | ||
#endif | ||
|
||
#if !defined(MBED_RAM_START) | ||
#define MBED_RAM_START 0x08000000 | ||
#endif | ||
|
||
#if !defined(MBED_RAM_SIZE) | ||
#define MBED_RAM_SIZE 0x10000 | ||
#endif | ||
|
||
/* The MEMORY section below describes the location and size of blocks of memory in the target. | ||
* Use this section to specify the memory regions available for allocation. | ||
*/ | ||
MEMORY | ||
{ | ||
ram (rwx) : ORIGIN = MBED_RAM_START, LENGTH = MBED_RAM_SIZE | ||
flash (rx) : ORIGIN = MBED_ROM_START, LENGTH = MBED_ROM_SIZE | ||
} | ||
... | ||
``` | ||
|
||
#### Linker script example for ARM | ||
|
||
``` | ||
... | ||
#if !defined(MBED_ROM_START) | ||
#define MBED_ROM_START 0x10000000 | ||
#endif | ||
|
||
#if !defined(MBED_ROM_SIZE) | ||
#define MBED_ROM_SIZE 0x78000 | ||
#endif | ||
|
||
#if !defined(MBED_RAM_START) | ||
#define MBED_RAM_START 0x08000000 | ||
#endif | ||
|
||
#if !defined(MBED_RAM_SIZE) | ||
#define MBED_RAM_SIZE 0x10000 | ||
#endif | ||
|
||
#define MBED_RAM0_START MBED_RAM_START | ||
#define MBED_RAM0_SIZE 0x100 | ||
#define MBED_RAM1_START (MBED_RAM_START + MBED_RAM0_SIZE) | ||
#define MBED_RAM1_SIZE (MBED_RAM_SIZE - MBED_RAM0_SIZE) | ||
|
||
LR_IROM1 MBED_ROM_START MBED_ROM_SIZE { | ||
ER_IROM1 MBED_ROM_START MBED_ROM_SIZE { | ||
*.o (RESET, +First) | ||
*(InRoot$$Sections) | ||
.ANY (+RO) | ||
} | ||
RW_IRAM0 MBED_RAM0_START UNINIT MBED_RAM0_SIZE { ;no init section | ||
*(*nvictable) | ||
} | ||
RW_IRAM1 MBED_RAM1_START MBED_RAM1_SIZE { | ||
.ANY (+RW +ZI) | ||
} | ||
} | ||
... | ||
``` | ||
|
||
#### Linker script example for IAR | ||
|
||
``` | ||
... | ||
if (!isdefinedsymbol(MBED_ROM_START)) { | ||
define symbol MBED_ROM_START = 0x10000000; | ||
} | ||
|
||
if (!isdefinedsymbol(MBED_ROM_SIZE)) { | ||
define symbol MBED_ROM_SIZE = 0x78000; | ||
} | ||
|
||
if (!isdefinedsymbol(MBED_RAM_START)) { | ||
define symbol MBED_RAM_START = 0x08000000; | ||
} | ||
|
||
if (!isdefinedsymbol(MBED_RAM_SIZE)) { | ||
define symbol MBED_RAM_SIZE = 0x10000; | ||
} | ||
|
||
/* RAM */ | ||
define symbol __ICFEDIT_region_IRAM1_start__ = MBED_RAM_START; | ||
define symbol __ICFEDIT_region_IRAM1_end__ = (MBED_RAM_START + MBED_RAM_SIZE); | ||
|
||
/* Flash */ | ||
define symbol __ICFEDIT_region_IROM1_start__ = MBED_ROM_START; | ||
define symbol __ICFEDIT_region_IROM1_end__ = (MBED_ROM_START + MBED_ROM_SIZE); | ||
... | ||
``` | ||
|
||
### Mailbox | ||
|
||
Mailbox is the SPM mechanism in charge of IPC, and is **relevant for multicore systems only**. | ||
danny4478 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
#### Concepts | ||
|
||
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. | ||
|
||
#### Requirements | ||
|
||
The SPM mailbox mechanism requires the platform to have the following capabilities: | ||
|
||
- IPC capabilities - The ability to notify the peer processor about an event (usually implemented with interrupts). | ||
- Ability to set a RAM section shared between the cores. | ||
|
||
#### Porting | ||
|
||
These are the guidelines you should follow if you have multicore systems: | ||
|
||
- For each core, initialize, configure and enable the a mailbox event (usually an interrupt) at `SystemInit()`. | ||
- For each core, implement the mailbox event handler (usually interrupt handler): | ||
danny4478 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- This handler must call an Arm callback function. The [HAL functions section](#hal-functions) explains this in more detail. | ||
danny4478 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- It is your responsibility to clear the mailbox event. You can do this in the event handler. | ||
danny4478 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- 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. | ||
|
||
### HAL functions | ||
|
||
Target specific code of silicon partners who wish to have SPM capabilities must: | ||
|
||
- Implement a list of functions which are being called by SPM code. | ||
- Call other functions supplied by ARM. | ||
danny4478 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
The HAL can be logically divided into two different fields: | ||
|
||
#### Mailbox | ||
|
||
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. | ||
|
||
#### Secure Processing Environment | ||
|
||
This part of HAL allows you to apply your specific memory protection scheme. You can find a list of [these functions]([TODO: WHEN READY, ADD LINK TO DOXYGEN FILES OF HAL FUNCTIONS]). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add this link. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can help find this link, but I'm not sure what you want to link to. Could you please elaborate? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @AnotherButler This Doxygen was not generated yet (at least its final version). We are waiting for some PRs to be merged into mbed-os, then I will send you the information to generate the Doxygen with, and you can generate them and send me the link. |
||
|
||
### Memory protection | ||
|
||
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. | ||
|
||
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: | ||
|
||
- X means No access. | ||
- V means Must be able to access. | ||
- ? means it is up to the target. | ||
- X? means it is up to the target, preferably No access. | ||
|
||
Processor access |Secure RAM |Secure FLASH|Nonsecure RAM |Nonsecure FLASH | ||
--------------------|------------------|------------|-------------------|---------------- | ||
`Non Secure Read` | X | X | V | V | ||
`Non Secure Write` | X | X | V | ? | ||
`Non Secure Execute`| X | X | X? | V | ||
`Secure Read` | V | V | V | V | ||
`Secure Write` | V | V | V | ? | ||
`Secure Execute` | X? | V | X | ? | ||
|
||
### Testing | ||
|
||
Arm provides a list of tests to make sure the HAL functions are implemented according to requirements, and the porting is done correctly. | ||
|
||
After finalizing the porting, execute the following tests: | ||
|
||
- **tests-psa-spm_smoke:** This test will make sure that the porting of the mailbox mechanism (for dual core systems) is successful. | ||
- **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 non-secure RAM/Flash. | ||
|
||
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alzix:
Since silicon partners have to add a new target to targets.json, I think the section headline should be called targets.json editing (or something lie that).
In this section we will describe the targets.json required modification.
Memory addresses and sizes (the "overrides" part) are a part of this, and memory layout explanation can be a sub-section here.
Except for "overrides" and the "inherits" parts (which you have mentioned) we should mention:
What do you think?