arm: core: mpu: Add core support to NXP MPU
This patch add arm core MPU support to NXP MPU driver. With this feature it is now possible to enable stack guarding on NXP MPUs. Signed-off-by: Vincenzo Frascino <vincenzo.frascino@linaro.org>
This commit is contained in:
parent
6597896f0a
commit
68f3b71b5d
4 changed files with 141 additions and 1 deletions
|
@ -13,6 +13,29 @@
|
||||||
#include <logging/sys_log.h>
|
#include <logging/sys_log.h>
|
||||||
#include <misc/__assert.h>
|
#include <misc/__assert.h>
|
||||||
|
|
||||||
|
#define STACK_GUARD_REGION_SIZE 32
|
||||||
|
|
||||||
|
/* NXP MPU Enabled state */
|
||||||
|
static u8_t nxp_mpu_enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This internal function is utilized by the MPU driver to parse the intent
|
||||||
|
* type (i.e. THREAD_STACK_REGION) and return the correct parameter set.
|
||||||
|
*/
|
||||||
|
static inline u32_t _get_region_attr_by_type(u32_t type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case THREAD_STACK_REGION:
|
||||||
|
return 0;
|
||||||
|
case THREAD_STACK_GUARD_REGION:
|
||||||
|
/* The stack guard region has to be not accessible */
|
||||||
|
return REGION_RO_ATTR;
|
||||||
|
default:
|
||||||
|
/* Size 0 region */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline u8_t _get_num_regions(void)
|
static inline u8_t _get_num_regions(void)
|
||||||
{
|
{
|
||||||
u32_t type = (SYSMPU->CESR & SYSMPU_CESR_NRGD_MASK)
|
u32_t type = (SYSMPU->CESR & SYSMPU_CESR_NRGD_MASK)
|
||||||
|
@ -48,6 +71,108 @@ static void _region_init(u32_t index, u32_t region_base,
|
||||||
SYSMPU->WORD[index][3]);
|
SYSMPU->WORD[index][3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ARM Core MPU Driver API Implementation for NXP MPU */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief enable the MPU
|
||||||
|
*/
|
||||||
|
void arm_core_mpu_enable(void)
|
||||||
|
{
|
||||||
|
if (nxp_mpu_enabled == 0) {
|
||||||
|
/* Enable MPU */
|
||||||
|
SYSMPU->CESR |= SYSMPU_CESR_VLD_MASK;
|
||||||
|
|
||||||
|
nxp_mpu_enabled = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief disable the MPU
|
||||||
|
*/
|
||||||
|
void arm_core_mpu_disable(void)
|
||||||
|
{
|
||||||
|
if (nxp_mpu_enabled == 1) {
|
||||||
|
/* Disable MPU */
|
||||||
|
SYSMPU->CESR &= ~SYSMPU_CESR_VLD_MASK;
|
||||||
|
/* Clear Interrupts */
|
||||||
|
SYSMPU->CESR |= SYSMPU_CESR_SPERR_MASK;
|
||||||
|
|
||||||
|
nxp_mpu_enabled = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief configure the base address and size for an MPU region
|
||||||
|
*
|
||||||
|
* @param type MPU region type
|
||||||
|
* @param base base address in RAM
|
||||||
|
* @param size size of the region
|
||||||
|
*/
|
||||||
|
void arm_core_mpu_configure(u8_t type, u32_t base, u32_t size)
|
||||||
|
{
|
||||||
|
SYS_LOG_DBG("Region info: 0x%x 0x%x", base, size);
|
||||||
|
/*
|
||||||
|
* The new MPU regions are are allocated per type after the statically
|
||||||
|
* configured regions.
|
||||||
|
*/
|
||||||
|
u32_t region_index = mpu_config.num_regions + type;
|
||||||
|
u32_t region_attr = _get_region_attr_by_type(type);
|
||||||
|
u32_t last_region = _get_num_regions() - 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The NXP MPU manages the permissions of the overlapping regions
|
||||||
|
* doing the logic OR in between them, hence they can't be used
|
||||||
|
* for stack/stack guard protection. For this reason the last region of
|
||||||
|
* the MPU will be reserved.
|
||||||
|
*
|
||||||
|
* A consequence of this is that the SRAM is splitted in different
|
||||||
|
* regions. In example if THREAD_STACK_GUARD_REGION is selected:
|
||||||
|
* - SRAM before THREAD_STACK_GUARD_REGION: RW
|
||||||
|
* - SRAM THREAD_STACK_GUARD_REGION: RO
|
||||||
|
* - SRAM after THREAD_STACK_GUARD_REGION: RW
|
||||||
|
*/
|
||||||
|
/* NXP MPU supports up to 16 Regions */
|
||||||
|
if (region_index > _get_num_regions() - 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure SRAM_0 region */
|
||||||
|
/*
|
||||||
|
* The mpu_config.sram_region contains the index of the region in
|
||||||
|
* the mpu_config.mpu_regions array but the region 0 on the NXP MPU
|
||||||
|
* is the background region, so on this MPU the regions are mapped
|
||||||
|
* starting from 1, hence the mpu_config.sram_region on the data
|
||||||
|
* structure is mapped on the mpu_config.sram_region + 1 region of
|
||||||
|
* the MPU.
|
||||||
|
*/
|
||||||
|
_region_init(mpu_config.sram_region + 1,
|
||||||
|
mpu_config.mpu_regions[mpu_config.sram_region].base,
|
||||||
|
ENDADDR_ROUND(base),
|
||||||
|
mpu_config.mpu_regions[mpu_config.sram_region].attr);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case THREAD_STACK_REGION:
|
||||||
|
break;
|
||||||
|
case THREAD_STACK_GUARD_REGION:
|
||||||
|
_region_init(region_index, base,
|
||||||
|
ENDADDR_ROUND(base + STACK_GUARD_REGION_SIZE),
|
||||||
|
region_attr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure SRAM_1 region */
|
||||||
|
_region_init(last_region,
|
||||||
|
base + STACK_GUARD_REGION_SIZE,
|
||||||
|
ENDADDR_ROUND(
|
||||||
|
mpu_config.mpu_regions[mpu_config.sram_region].end),
|
||||||
|
mpu_config.mpu_regions[mpu_config.sram_region].attr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NXP MPU Driver Initial Setup */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief MPU default configuration
|
* @brief MPU default configuration
|
||||||
*
|
*
|
||||||
|
@ -75,6 +200,12 @@ static void _nxp_mpu_config(void)
|
||||||
/* Disable Region 0 */
|
/* Disable Region 0 */
|
||||||
SYSMPU->WORD[0][2] = 0;
|
SYSMPU->WORD[0][2] = 0;
|
||||||
|
|
||||||
|
SYS_LOG_DBG("[0] 0x%08x 0x%08x 0x%08x 0x%08x",
|
||||||
|
SYSMPU->WORD[0][0],
|
||||||
|
SYSMPU->WORD[0][1],
|
||||||
|
SYSMPU->WORD[0][2],
|
||||||
|
SYSMPU->WORD[0][3]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configure regions:
|
* Configure regions:
|
||||||
* r_index starts from 0 but is passed to region_init as r_index + 1,
|
* r_index starts from 0 but is passed to region_init as r_index + 1,
|
||||||
|
@ -90,6 +221,8 @@ static void _nxp_mpu_config(void)
|
||||||
/* Enable MPU */
|
/* Enable MPU */
|
||||||
SYSMPU->CESR |= SYSMPU_CESR_VLD_MASK;
|
SYSMPU->CESR |= SYSMPU_CESR_VLD_MASK;
|
||||||
|
|
||||||
|
nxp_mpu_enabled = 1;
|
||||||
|
|
||||||
/* Make sure that all the registers are set before proceeding */
|
/* Make sure that all the registers are set before proceeding */
|
||||||
__DSB();
|
__DSB();
|
||||||
__ISB();
|
__ISB();
|
||||||
|
|
|
@ -46,4 +46,5 @@ static struct nxp_mpu_region mpu_regions[] = {
|
||||||
struct nxp_mpu_config mpu_config = {
|
struct nxp_mpu_config mpu_config = {
|
||||||
.num_regions = ARRAY_SIZE(mpu_regions),
|
.num_regions = ARRAY_SIZE(mpu_regions),
|
||||||
.mpu_regions = mpu_regions,
|
.mpu_regions = mpu_regions,
|
||||||
|
.sram_region = 3,
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,11 +25,15 @@
|
||||||
/* Super User Attributes */
|
/* Super User Attributes */
|
||||||
#define MPU_REGION_SU ((3 << 3) | (3 << 9) | (3 << 15) | (3 << 21))
|
#define MPU_REGION_SU ((3 << 3) | (3 << 9) | (3 << 15) | (3 << 21))
|
||||||
|
|
||||||
|
/* The ENDADDR field has the last 5 bit reserved and set to 1 */
|
||||||
|
#define ENDADDR_ROUND(x) (x - 0x1F)
|
||||||
|
|
||||||
/* Some helper defines for common regions */
|
/* Some helper defines for common regions */
|
||||||
#define REGION_RAM_ATTR (MPU_REGION_READ | MPU_REGION_WRITE | MPU_REGION_SU)
|
#define REGION_RAM_ATTR (MPU_REGION_READ | MPU_REGION_WRITE | MPU_REGION_SU)
|
||||||
#define REGION_FLASH_ATTR (MPU_REGION_READ | MPU_REGION_EXEC | MPU_REGION_SU)
|
#define REGION_FLASH_ATTR (MPU_REGION_READ | MPU_REGION_EXEC | MPU_REGION_SU)
|
||||||
#define REGION_IO_ATTR (MPU_REGION_READ | MPU_REGION_WRITE | \
|
#define REGION_IO_ATTR (MPU_REGION_READ | MPU_REGION_WRITE | \
|
||||||
MPU_REGION_EXEC | MPU_REGION_SU)
|
MPU_REGION_EXEC | MPU_REGION_SU)
|
||||||
|
#define REGION_RO_ATTR (MPU_REGION_READ | MPU_REGION_SU)
|
||||||
|
|
||||||
/* Region definition data structure */
|
/* Region definition data structure */
|
||||||
struct nxp_mpu_region {
|
struct nxp_mpu_region {
|
||||||
|
@ -57,6 +61,8 @@ struct nxp_mpu_config {
|
||||||
u32_t num_regions;
|
u32_t num_regions;
|
||||||
/* Regions */
|
/* Regions */
|
||||||
struct nxp_mpu_region *mpu_regions;
|
struct nxp_mpu_region *mpu_regions;
|
||||||
|
/* SRAM Region */
|
||||||
|
u32_t sram_region;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Reference to the MPU configuration */
|
/* Reference to the MPU configuration */
|
||||||
|
|
|
@ -7,4 +7,4 @@ build_only = true
|
||||||
extra_args = CONF_FILE=prj_stack_guard.conf
|
extra_args = CONF_FILE=prj_stack_guard.conf
|
||||||
tags = apps
|
tags = apps
|
||||||
arch_whitelist = arm
|
arch_whitelist = arm
|
||||||
filter = CONFIG_MPU_STACK_GUARD and CONFIG_ARM_MPU
|
filter = CONFIG_MPU_STACK_GUARD
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue