The Protection Unit driver provides an API to configure the Memory Protection Units (MPU), Shared Memory Protection Units (SMPU), and Peripheral Protection Units (PPU).
These are separate from the ARM Core MPUs and provide additional mechanisms for securing resource accesses. The Protection units address the following concerns in an embedded design:
The functions and other declarations used in this driver are in cy_prot.h. You can include cy_pdl.h to get access to all functions and declarations in the PDL.
Protection units are hardware configuration structures that control bus accesses to the resources that they protect. By combining these individual configuration structures, a system is built to allow strict restrictions on the capabilities of individual bus masters (e.g. CM0+, CM4, Crypt) and their operating modes. This architecture can then be integrated into the overall security system of the end application. To build this system, 3 main protection unit types are available; MPU, SMPU and PPU. When a resource is accessed (memory/register), it must pass the evaluation performed for each category. These access evaluations are prioritized, where MPU has the highest priority, followed by SMPU, followed by PPU. i.e. if an SMPU and a PPU protect the same resource and if access is denied by the SMPU, then the PPU access evaluation is skipped. This can lead to a denial-of-service scenario and the application should pay special attention in taking ownership of the protection unit configurations.
Memory access control for a bus master is controlled using an MPU. These are most often used to distinguish user and privileged accesses from a single bus master such as task switching in an OS/kernel. For ARM cores (CM0+, CM4), the core MPUs are used to perform this task. For other non-ARM bus masters such as Crypto, MPU structs are available, which can be used in a similar manner as the ARM core MPUs. These MPUs however must be configured by the ARM cores. Other bus masters that do not have an MPU, such as DMA (DW), inherit the access control attributes of the bus master that configured the channel. Also note that unlike other protection units, MPUs do not support protection context evaluation. MPU structs have a descending priority, where larger index struct has higher priority access evaluation over lower index structs. E.g. MPU_STRUCT15 has higher priority than MPU_STRUCT14 and its access will be evaluated before MPU_STRUCT14. If both target the same memory, then the higher index (MPU_STRUCT15) will be used, and the lower index (MPU_STRUCT14) will be ignored.
In order to protect a region of memory from all bus masters, an SMPU is used. This protection effectively allows only those with correct bus master access settings to read/write/execute the memory region. This type of protection is used in general memory such as Flash and SRAM. Peripheral registers are best configured using the peripheral protection units instead. SMPU structs have a descending priority, where larger index struct has higher priority access evaluation over lower index structs. E.g. SMPU_STRUCT15 has higher priority than SMPU_STRUCT14 and its access will be evaluated before SMPU_STRUCT14. If both target the same memory, then the higher index (MPU_STRUCT15) will be used, and the lower index (SMPU_STRUCT14) will be ignored.
Peripheral protection is provided by PPUs and allow control of peripheral register accesses by bus masters. Four types of PPUs are available.
Protection context (PC) attribute is present in all bus masters and is evaluated when accessing memory protected by an SMPU or a PPU. There are no limitations to how the PC values are allocated to the bus masters and this makes it possible for multiple bus masters to essentially share protection context values. The exception to this rule is the PC value 0.
Protection context 0 is a hardware controlled protection context update mechanism that allows only a single entry point for transitioning into PC=0 value. This mechanism is only present for the secure CM0+ core and is a fundamental feature in defining a security solution. While all bus masters are configured to PC=0 at device boot, it is up to the security solution to transition these bus masters to PC!=0 values. Once this is done, those bus masters can no longer revert back to PC=0 and can no longer access resources protected at PC=0.
In order to enter PC=0, the CM0+ core must assign an interrupt vector or an exception handler address to the CPUSS.CM0_PC0_HANDLER register. This allows the hardware to check whether the executing code address matches the value in this register. If they match, the current PC value is saved and the CM0+ bus master automatically transitions to PC=0. It is then up to the executing code to decide if and when it will revert to a PC!=0 value. At that point, the only way to re-transition to PC=0 is through the defined exception/interrupt handler.
The example of using of the single entry point mechanism is shown below.
Each protection unit is capable of evaluating several access types. These can be used to build a system of logical evaluations for different kinds of bus master modes of operations. These access types can be divided into three broad access categories.
Each protection unit is comprised of a master struct and a slave struct pair. The exception to this rule is MPU structs, which only have the slave struct equivalent. The protection units apply their access evaluations in a decreasing index order. For example, if SMPU1 and SMPU2 both protect a specific memory region, the the higher index (SMPU2) will be evaluated first. In a secure system, the higher index protection structs would then provide the high level of security and the lower indexes would provide the lower level of security. Refer to the Protection Types section for more information.
The slave struct is used to configure the protection settings for the resource of interest (memory/registers). Depending on the type of protection unit, the available attributes differ. However all Slave protection units have the following general format.
The master struct protects its slave struct in the protection unit. This architecture makes possible for the slave configuration to be protected from reconfiguration by an unauthorized bus master. The configuration attributes and the format are similar to that of the slave structs.
Setting up and using protection units can be summed up in four stages:
For example, by configuring the CM0+ bus master configuration to allow only protection contexts 2 and 3, the bus master will be able to set its protection context only to 2 or 3. During runtime, the CM0+ core can set its protection context to 2 by calling Cy_Prot_SetActivePC() and access all regions of protected memory that allow PC=2. A fault will be triggered if a resource is protected with different protection settings.
Note that each protection unit is distinguished by its type (e.g. PROT_MPU_MPU_STRUCT_Type). The list of supported protection units can be obtained from the device definition header file. Choose a protection unit of interest, and call its corresponding Cy_Prot_Config<X>Struct() function with its software protection unit configuration structure populated. Then enable the protection unit by calling the Cy_Prot_Enable<X>Struct() function.
Note that the bus master ID (en_prot_master_t) is defined in the device config header file.
When a resource (memory/register) is accessed, it must pass evaluation of all three protection unit categories in the following order: MPU->SMPU->PPU. The application should ensure that a denial-of-service attack cannot be made on the PPU by the SMPU. For this reason, it is recommended that the application's security policy limit the ability for the non-secure client from configuring the SMPUs.
Within each category, the priority hierarchy must be carefully considered to ensure that a higher priority protection unit cannot be configured to override the security configuration of a lower index protection unit. Therefore if a lower index protection unit is configured, relevant higher priority indexes should be configured (or protected from unwanted reconfiguration). E.g. If a PPU_SL is configured, PPU_RG and PPU_GR that overlaps with the protected registers should also be configured. SImilar to SMPUs, it is recommended that the configuration of PPU_PROG be limited. Otherwise they can be used to override the protection settings of PPU_RG and PPU_SL structs.
All bus masters are set to PC=0 value at device reset and therefore have full access to all resources. It is up to the security solution to implement what privileges each bus master has. Once transitioned to a PC!=0 value, only the CM0+ core is capable of re-entering the PC=0 via the user-defined exception entry in the CPUSS.CM0_PC0_HANDLER register.
Refer to Technical Reference Manual (TRM) and the device datasheet.
Version | Changes | Reason for Change |
---|---|---|
1.100 | Updating implementation of internal function that configures attributes. | Defect fix. |
1.90 | Added support for TRAVEO™ II Body Entry devices. Updated conditions in pre-processor check for if the device has a CM4 to also check for for MXPERI ver. 1. Cleaned up redundant code. Bug fix: Updates some API availability based on the PERI version. Some devices may have a reduced set of functions available. If code called APIs not appropriate for the version of PERI, that code will not build without updating to reflect new API availability. Please note, however, that if code was calling those APIs and the functions are no longer available, there will be no functional difference as the calls were available before but did nothing if the device hardware didn't support the function. This change makes the API accurately reflect hardware capability. | Code enhancement and support for new devices. |
1.80 | Cy_Prot_ConfigPpuProgSlaveAddr(), Cy_Prot_EnablePpuProgSlaveRegion() Cy_Prot_DisablePpuProgSlaveRegion() APIs are only available for PSoC6 devices | MISRA C-2012 compliance and Move PERI version-1 APIs to supported devices |
1.70 | Added support for CAT1C devices. | New device added. |
1.60 | Modified Cy_Prot_ConfigPpuProgMasterAtt() & Cy_Prot_ConfigPpuFixedMasterAtt() functions to ignore unavailable protection context. | Defect fix. |
1.50 | Updated implementation of the Cy_Prot_ConfigPpuProgMasterAtt(), Cy_Prot_ConfigPpuProgSlaveAtt(), Cy_Prot_ConfigPpuFixedMasterAtt(), and Cy_Prot_ConfigPpuFixedSlaveAtt() to start registers update from the higher-numbered PCs in order to prevent lockup for the case when registers are configured to read-only. | Defect fix. |
Added macros for memory region size setting in cy_en_prot_size_t initialization. | The macros can be useful for the pre-processor checks. | |
Fixed/Documented MISRA 2012 violations. | MISRA 2012 compliance. | |
1.40 |
| Added PSoC 64 devices support. |
1.30.3 | Minor documentation updates. | Documentation enhancement. |
1.30.2 | Clarified the description of the next API functions: Cy_Prot_ConfigPpuProgMasterAtt, Cy_Prot_ConfigPpuProgSlaveAtt, Cy_Prot_ConfigPpuFixedMasterAtt, Cy_Prot_ConfigPpuFixedSlaveAtt. | API enhancement based on usability feedback. |
1.30.1 | Snippet updated. | Old snippet outdated. |
1.30 | Defect in Cy_Prot_GetPpuProgStruct() function due to faulty defines is fixed. | Defect fixing. |
1.20 | Flattened the organization of the driver source code into the single source directory and the single include directory. | Driver library directory-structure simplification. |
Added functions for CPUSS ver_2: | Added support for CPUSS ver_2. | |
Added register access layer. Use register access macros instead of direct register access using dereferenced pointers. | Makes register access device-independent, so that the PDL does not need to be recompiled for each supported part number. | |
1.10 | Added input parameter validation to the API functions. cy_en_prot_pcmask_t, cy_en_prot_subreg_t and cy_en_prot_pc_t types are set to typedef enum | Improved debugging capability |
Expanded documentation | ||
1.0 | Initial version |
API Reference | |
Macros | |
Functions | |
Data Structures | |
Enumerated Types | |