Skip to content

Commit

Permalink
FreeRTOS MPU: Add Privileged eXecute Never MPU attribute support (#1092)
Browse files Browse the repository at this point in the history
FreeRTOS MPU: Add privileged execute never MPU attribute

A new MPU region attribute Privileged eXecute Never (PXN)
is introduced in Armv8.1-M architecture, where if an MPU
region has PXN attribute set and the processor attempts
to execute the code inside with privileged level,
the Memory Management Fault exception would be triggered,
with IACCVIOL bit in MemManage Fault State Register set
to 1. The PXN feature allows privileged software to ensure
specific application tasks (threads) to execute in
unprivileged level only.

Signed-off-by: Ahmed Ismail <Ahmed.Ismail@arm.com>
  • Loading branch information
AhmedIsmail02 committed Jun 19, 2024
1 parent 0c79e74 commit 31419bf
Show file tree
Hide file tree
Showing 56 changed files with 1,309 additions and 936 deletions.
27 changes: 15 additions & 12 deletions include/task.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,30 +53,33 @@
* The tskKERNEL_VERSION_MAJOR, tskKERNEL_VERSION_MINOR, tskKERNEL_VERSION_BUILD
* values will reflect the last released version number.
*/
#define tskKERNEL_VERSION_NUMBER "V11.1.0+"
#define tskKERNEL_VERSION_MAJOR 11
#define tskKERNEL_VERSION_MINOR 1
#define tskKERNEL_VERSION_BUILD 0
#define tskKERNEL_VERSION_NUMBER "V11.1.0+"
#define tskKERNEL_VERSION_MAJOR 11
#define tskKERNEL_VERSION_MINOR 1
#define tskKERNEL_VERSION_BUILD 0

/* MPU region parameters passed in ulParameters
* of MemoryRegion_t struct. */
#define tskMPU_REGION_READ_ONLY ( 1U << 0U )
#define tskMPU_REGION_READ_WRITE ( 1U << 1U )
#define tskMPU_REGION_EXECUTE_NEVER ( 1U << 2U )
#define tskMPU_REGION_NORMAL_MEMORY ( 1U << 3U )
#define tskMPU_REGION_DEVICE_MEMORY ( 1U << 4U )
#define tskMPU_REGION_READ_ONLY ( 1U << 0U )
#define tskMPU_REGION_READ_WRITE ( 1U << 1U )
#define tskMPU_REGION_EXECUTE_NEVER ( 1U << 2U )
#define tskMPU_REGION_NORMAL_MEMORY ( 1U << 3U )
#define tskMPU_REGION_DEVICE_MEMORY ( 1U << 4U )
#if ( portARMV8M_MINOR_VERSION >= 1 )
#define tskMPU_REGION_PRIVILEGED_EXECUTE_NEVER ( 1U << 5U )
#endif /* portARMV8M_MINOR_VERSION >= 1 */

/* MPU region permissions stored in MPU settings to
* authorize access requests. */
#define tskMPU_READ_PERMISSION ( 1U << 0U )
#define tskMPU_WRITE_PERMISSION ( 1U << 1U )
#define tskMPU_READ_PERMISSION ( 1U << 0U )
#define tskMPU_WRITE_PERMISSION ( 1U << 1U )

/* The direct to task notification feature used to have only a single notification
* per task. Now there is an array of notifications per task that is dimensioned by
* configTASK_NOTIFICATION_ARRAY_ENTRIES. For backward compatibility, any use of the
* original direct to task notification defaults to using the first index in the
* array. */
#define tskDEFAULT_INDEX_TO_NOTIFY ( 0 )
#define tskDEFAULT_INDEX_TO_NOTIFY ( 0 )

/**
* task. h
Expand Down
104 changes: 60 additions & 44 deletions portable/ARMv8M/non_secure/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,73 +166,79 @@ typedef void ( * portISR_t )( void );
/**
* @brief Constants required to manipulate the MPU.
*/
#define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) )
#define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) )
#define portMPU_RNR_REG ( *( ( volatile uint32_t * ) 0xe000ed98 ) )
#define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) )
#define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) )
#define portMPU_RNR_REG ( *( ( volatile uint32_t * ) 0xe000ed98 ) )

#define portMPU_RBAR_REG ( *( ( volatile uint32_t * ) 0xe000ed9c ) )
#define portMPU_RLAR_REG ( *( ( volatile uint32_t * ) 0xe000eda0 ) )
#define portMPU_RBAR_REG ( *( ( volatile uint32_t * ) 0xe000ed9c ) )
#define portMPU_RLAR_REG ( *( ( volatile uint32_t * ) 0xe000eda0 ) )

#define portMPU_RBAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda4 ) )
#define portMPU_RLAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda8 ) )
#define portMPU_RBAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda4 ) )
#define portMPU_RLAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda8 ) )

#define portMPU_RBAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edac ) )
#define portMPU_RLAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edb0 ) )
#define portMPU_RBAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edac ) )
#define portMPU_RLAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edb0 ) )

#define portMPU_RBAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb4 ) )
#define portMPU_RLAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb8 ) )
#define portMPU_RBAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb4 ) )
#define portMPU_RLAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb8 ) )

#define portMPU_MAIR0_REG ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
#define portMPU_MAIR1_REG ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
#define portMPU_MAIR0_REG ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
#define portMPU_MAIR1_REG ( *( ( volatile uint32_t * ) 0xe000edc4 ) )

#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */

#define portMPU_RBAR_ACCESS_PERMISSIONS_MASK ( 3UL << 1UL )
#define portMPU_RBAR_ACCESS_PERMISSIONS_MASK ( 3UL << 1UL )

#define portMPU_MAIR_ATTR0_POS ( 0UL )
#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff )
#define portMPU_MAIR_ATTR0_POS ( 0UL )
#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff )

#define portMPU_MAIR_ATTR1_POS ( 8UL )
#define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 )
#define portMPU_MAIR_ATTR1_POS ( 8UL )
#define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 )

#define portMPU_MAIR_ATTR2_POS ( 16UL )
#define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 )
#define portMPU_MAIR_ATTR2_POS ( 16UL )
#define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 )

#define portMPU_MAIR_ATTR3_POS ( 24UL )
#define portMPU_MAIR_ATTR3_MASK ( 0xff000000 )
#define portMPU_MAIR_ATTR3_POS ( 24UL )
#define portMPU_MAIR_ATTR3_MASK ( 0xff000000 )

#define portMPU_MAIR_ATTR4_POS ( 0UL )
#define portMPU_MAIR_ATTR4_MASK ( 0x000000ff )
#define portMPU_MAIR_ATTR4_POS ( 0UL )
#define portMPU_MAIR_ATTR4_MASK ( 0x000000ff )

#define portMPU_MAIR_ATTR5_POS ( 8UL )
#define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 )
#define portMPU_MAIR_ATTR5_POS ( 8UL )
#define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 )

#define portMPU_MAIR_ATTR6_POS ( 16UL )
#define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 )
#define portMPU_MAIR_ATTR6_POS ( 16UL )
#define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 )

#define portMPU_MAIR_ATTR7_POS ( 24UL )
#define portMPU_MAIR_ATTR7_MASK ( 0xff000000 )
#define portMPU_MAIR_ATTR7_POS ( 24UL )
#define portMPU_MAIR_ATTR7_MASK ( 0xff000000 )

#define portMPU_RLAR_ATTR_INDEX0 ( 0UL << 1UL )
#define portMPU_RLAR_ATTR_INDEX1 ( 1UL << 1UL )
#define portMPU_RLAR_ATTR_INDEX2 ( 2UL << 1UL )
#define portMPU_RLAR_ATTR_INDEX3 ( 3UL << 1UL )
#define portMPU_RLAR_ATTR_INDEX4 ( 4UL << 1UL )
#define portMPU_RLAR_ATTR_INDEX5 ( 5UL << 1UL )
#define portMPU_RLAR_ATTR_INDEX6 ( 6UL << 1UL )
#define portMPU_RLAR_ATTR_INDEX7 ( 7UL << 1UL )
#define portMPU_RLAR_ATTR_INDEX0 ( 0UL << 1UL )
#define portMPU_RLAR_ATTR_INDEX1 ( 1UL << 1UL )
#define portMPU_RLAR_ATTR_INDEX2 ( 2UL << 1UL )
#define portMPU_RLAR_ATTR_INDEX3 ( 3UL << 1UL )
#define portMPU_RLAR_ATTR_INDEX4 ( 4UL << 1UL )
#define portMPU_RLAR_ATTR_INDEX5 ( 5UL << 1UL )
#define portMPU_RLAR_ATTR_INDEX6 ( 6UL << 1UL )
#define portMPU_RLAR_ATTR_INDEX7 ( 7UL << 1UL )

#define portMPU_RLAR_REGION_ENABLE ( 1UL )
#define portMPU_RLAR_REGION_ENABLE ( 1UL )

#if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
#endif /* portARMV8M_MINOR_VERSION >= 1 */

/* Enable privileged access to unmapped region. */
#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL )
#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL )

/* Enable MPU. */
#define portMPU_ENABLE_BIT ( 1UL << 0UL )
#define portMPU_ENABLE_BIT ( 1UL << 0UL )

/* Expected value of the portMPU_TYPE register. */
#define portEXPECTED_MPU_TYPE_VALUE ( configTOTAL_MPU_REGIONS << 8UL )
#define portEXPECTED_MPU_TYPE_VALUE ( configTOTAL_MPU_REGIONS << 8UL )

/* Extract first address of the MPU region as encoded in the
* RBAR (Region Base Address Register) value. */
Expand Down Expand Up @@ -1880,6 +1886,16 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) |
( portMPU_RLAR_REGION_ENABLE );

/* PXN. */
#if ( portARMV8M_MINOR_VERSION >= 1 )
{
if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_PRIVILEGED_EXECUTE_NEVER ) != 0 )
{
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= ( portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER );
}
}
#endif /* portARMV8M_MINOR_VERSION >= 1 */

/* Normal memory/ Device memory. */
if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_DEVICE_MEMORY ) != 0 )
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
*/
#define portARCH_NAME "Cortex-M23"
#define portHAS_ARMV8M_MAIN_EXTENSION 0
#define portARMV8M_MINOR_VERSION 0
#define portDONT_DISCARD __attribute__( ( used ) )
/*-----------------------------------------------------------*/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
*/
#define portARCH_NAME "Cortex-M23"
#define portHAS_ARMV8M_MAIN_EXTENSION 0
#define portARMV8M_MINOR_VERSION 0
#define portDONT_DISCARD __attribute__( ( used ) )
/*-----------------------------------------------------------*/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
*/
#define portARCH_NAME "Cortex-M33"
#define portHAS_ARMV8M_MAIN_EXTENSION 1
#define portARMV8M_MINOR_VERSION 0
#define portDONT_DISCARD __attribute__( ( used ) )
/*-----------------------------------------------------------*/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
*/
#define portARCH_NAME "Cortex-M33"
#define portHAS_ARMV8M_MAIN_EXTENSION 1
#define portARMV8M_MINOR_VERSION 0
#define portDONT_DISCARD __attribute__( ( used ) )
/*-----------------------------------------------------------*/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
*/
#define portARCH_NAME "Cortex-M35P"
#define portHAS_ARMV8M_MAIN_EXTENSION 1
#define portARMV8M_MINOR_VERSION 0
#define portDONT_DISCARD __attribute__( ( used ) )
/*-----------------------------------------------------------*/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
*/
#define portARCH_NAME "Cortex-M55"
#define portHAS_ARMV8M_MAIN_EXTENSION 1
#define portARMV8M_MINOR_VERSION 1
#define portDONT_DISCARD __attribute__( ( used ) )
/*-----------------------------------------------------------*/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
*/
#define portARCH_NAME "Cortex-M85"
#define portHAS_ARMV8M_MAIN_EXTENSION 1
#define portARMV8M_MINOR_VERSION 1
#define portDONT_DISCARD __attribute__( ( used ) )
/*-----------------------------------------------------------*/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
*/
#define portARCH_NAME "Cortex-M23"
#define portHAS_ARMV8M_MAIN_EXTENSION 0
#define portARMV8M_MINOR_VERSION 0
#define portDONT_DISCARD __root
/*-----------------------------------------------------------*/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
*/
#define portARCH_NAME "Cortex-M23"
#define portHAS_ARMV8M_MAIN_EXTENSION 0
#define portARMV8M_MINOR_VERSION 0
#define portDONT_DISCARD __root
/*-----------------------------------------------------------*/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
*/
#define portARCH_NAME "Cortex-M33"
#define portHAS_ARMV8M_MAIN_EXTENSION 1
#define portARMV8M_MINOR_VERSION 0
#define portDONT_DISCARD __root
/*-----------------------------------------------------------*/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
*/
#define portARCH_NAME "Cortex-M33"
#define portHAS_ARMV8M_MAIN_EXTENSION 1
#define portARMV8M_MINOR_VERSION 0
#define portDONT_DISCARD __root
/*-----------------------------------------------------------*/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
*/
#define portARCH_NAME "Cortex-M35P"
#define portHAS_ARMV8M_MAIN_EXTENSION 1
#define portARMV8M_MINOR_VERSION 0
#define portDONT_DISCARD __root
/*-----------------------------------------------------------*/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
*/
#define portARCH_NAME "Cortex-M55"
#define portHAS_ARMV8M_MAIN_EXTENSION 1
#define portARMV8M_MINOR_VERSION 1
#define portDONT_DISCARD __root
/*-----------------------------------------------------------*/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
*/
#define portARCH_NAME "Cortex-M85"
#define portHAS_ARMV8M_MAIN_EXTENSION 1
#define portARMV8M_MINOR_VERSION 1
#define portDONT_DISCARD __root
/*-----------------------------------------------------------*/

Expand Down
Loading

0 comments on commit 31419bf

Please sign in to comment.