arm: soc: nxp k6x: Add Initial support for NXP MPU
This patch adds initial MPU support to NXP K6x family. The boot configuration prevents the following security issues: * Prevent to read at an address that is reserved in the memory map. * Prevent to write into the boot Flash/ROM. * Prevent from running code located in SRAM. This driver has been tested on FRDM-K64F. Change-Id: I907168fff0c6028f1c665f1d3c224cbeec31be32 Signed-off-by: Vincenzo Frascino <vincenzo.frascino@linaro.org>
This commit is contained in:
parent
d30d90257c
commit
adf0bf90b6
10 changed files with 267 additions and 0 deletions
|
@ -13,3 +13,11 @@ config ARM_MPU
|
||||||
default n
|
default n
|
||||||
help
|
help
|
||||||
MCU has ARM MPU
|
MCU has ARM MPU
|
||||||
|
|
||||||
|
config NXP_MPU
|
||||||
|
bool "NXP MPU Support"
|
||||||
|
depends on CPU_HAS_MPU
|
||||||
|
depends on SOC_FAMILY_KINETIS
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
MCU has NXP MPU
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
obj-$(CONFIG_ARM_MPU) += arm_mpu.o
|
obj-$(CONFIG_ARM_MPU) += arm_mpu.o
|
||||||
|
obj-$(CONFIG_NXP_MPU) += nxp_mpu.o
|
||||||
|
|
128
arch/arm/core/cortex_m/mpu/nxp_mpu.c
Normal file
128
arch/arm/core/cortex_m/mpu/nxp_mpu.c
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Linaro Limited.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <device.h>
|
||||||
|
#include <init.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <soc.h>
|
||||||
|
#include <arch/arm/cortex_m/cmsis.h>
|
||||||
|
#include <arch/arm/cortex_m/mpu/nxp_mpu.h>
|
||||||
|
#include <logging/sys_log.h>
|
||||||
|
#include <misc/__assert.h>
|
||||||
|
|
||||||
|
static inline u8_t _get_num_regions(void)
|
||||||
|
{
|
||||||
|
u32_t type = (SYSMPU->CESR & SYSMPU_CESR_NRGD_MASK)
|
||||||
|
>> SYSMPU_CESR_NRGD_SHIFT;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 0:
|
||||||
|
return 8;
|
||||||
|
case 1:
|
||||||
|
return 12;
|
||||||
|
case 2:
|
||||||
|
return 16;
|
||||||
|
default:
|
||||||
|
__ASSERT(0, "Unsupported MPU configuration.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NXP_MPU_REGION_NUMBER;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _region_init(u32_t index, u32_t region_base,
|
||||||
|
u32_t region_end, u32_t region_attr)
|
||||||
|
{
|
||||||
|
SYSMPU->WORD[index][0] = region_base;
|
||||||
|
SYSMPU->WORD[index][1] = region_end;
|
||||||
|
SYSMPU->WORD[index][2] = region_attr;
|
||||||
|
SYSMPU->WORD[index][3] = SYSMPU_WORD_VLD_MASK;
|
||||||
|
|
||||||
|
SYS_LOG_DBG("[%d] 0x%08x 0x%08x 0x%08x 0x%08x", index,
|
||||||
|
SYSMPU->WORD[index][0],
|
||||||
|
SYSMPU->WORD[index][1],
|
||||||
|
SYSMPU->WORD[index][2],
|
||||||
|
SYSMPU->WORD[index][3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief MPU default configuration
|
||||||
|
*
|
||||||
|
* This function provides the default configuration mechanism for the Memory
|
||||||
|
* Protection Unit (MPU).
|
||||||
|
*/
|
||||||
|
static void _nxp_mpu_config(void)
|
||||||
|
{
|
||||||
|
u32_t r_index;
|
||||||
|
|
||||||
|
SYS_LOG_DBG("region number: %d", _get_num_regions());
|
||||||
|
|
||||||
|
/* NXP MPU supports up to 16 Regions */
|
||||||
|
if (mpu_config.num_regions > _get_num_regions()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable MPU */
|
||||||
|
SYSMPU->CESR &= ~SYSMPU_CESR_VLD_MASK;
|
||||||
|
/* Clear Interrupts */
|
||||||
|
SYSMPU->CESR |= SYSMPU_CESR_SPERR_MASK;
|
||||||
|
|
||||||
|
/* MPU Configuration */
|
||||||
|
|
||||||
|
/* Disable Region 0 */
|
||||||
|
SYSMPU->WORD[0][2] = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configure regions:
|
||||||
|
* r_index starts from 0 but is passed to region_init as r_index + 1,
|
||||||
|
* region 0 is not configurable
|
||||||
|
*/
|
||||||
|
for (r_index = 0; r_index < mpu_config.num_regions; r_index++) {
|
||||||
|
_region_init(r_index + 1,
|
||||||
|
mpu_config.mpu_regions[r_index].base,
|
||||||
|
mpu_config.mpu_regions[r_index].end,
|
||||||
|
mpu_config.mpu_regions[r_index].attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable MPU */
|
||||||
|
SYSMPU->CESR |= SYSMPU_CESR_VLD_MASK;
|
||||||
|
|
||||||
|
/* Make sure that all the registers are set before proceeding */
|
||||||
|
__DSB();
|
||||||
|
__ISB();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief MPU clock configuration
|
||||||
|
*
|
||||||
|
* This function provides the clock configuration for the Memory Protection
|
||||||
|
* Unit (MPU).
|
||||||
|
*/
|
||||||
|
static void _nxp_mpu_clock_cfg(void)
|
||||||
|
{
|
||||||
|
/* Enable Clock */
|
||||||
|
CLOCK_EnableClock(kCLOCK_Sysmpu0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nxp_mpu_init(struct device *arg)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(arg);
|
||||||
|
|
||||||
|
_nxp_mpu_clock_cfg();
|
||||||
|
|
||||||
|
_nxp_mpu_config();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_SYS_LOG)
|
||||||
|
/* To have logging the driver needs to be initialized later */
|
||||||
|
SYS_INIT(nxp_mpu_init, POST_KERNEL,
|
||||||
|
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||||
|
#else
|
||||||
|
SYS_INIT(nxp_mpu_init, PRE_KERNEL_1,
|
||||||
|
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||||
|
#endif
|
|
@ -64,6 +64,14 @@ config HAS_LPSCI
|
||||||
help
|
help
|
||||||
Set if the low power uart (LPSCI) module is present in the SoC.
|
Set if the low power uart (LPSCI) module is present in the SoC.
|
||||||
|
|
||||||
|
config HAS_SYSMPU
|
||||||
|
bool "Enable MPU"
|
||||||
|
depends on CPU_HAS_MPU
|
||||||
|
select NXP_MPU
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable MPU
|
||||||
|
|
||||||
if HAS_OSC
|
if HAS_OSC
|
||||||
|
|
||||||
choice
|
choice
|
||||||
|
|
|
@ -12,5 +12,6 @@ config SOC_SERIES_KINETIS_K6X
|
||||||
select SOC_FAMILY_KINETIS
|
select SOC_FAMILY_KINETIS
|
||||||
select SYS_POWER_LOW_POWER_STATE_SUPPORTED
|
select SYS_POWER_LOW_POWER_STATE_SUPPORTED
|
||||||
select CPU_HAS_SYSTICK
|
select CPU_HAS_SYSTICK
|
||||||
|
select CPU_HAS_MPU
|
||||||
help
|
help
|
||||||
Enable support for Kinetis K6x MCU series
|
Enable support for Kinetis K6x MCU series
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
obj-y += soc.o
|
obj-y += soc.o
|
||||||
obj-y += wdog.o
|
obj-y += wdog.o
|
||||||
|
obj-$(CONFIG_HAS_SYSMPU) += nxp_mpu_regions.o
|
||||||
|
|
49
arch/arm/soc/nxp_kinetis/k6x/nxp_mpu_regions.c
Normal file
49
arch/arm/soc/nxp_kinetis/k6x/nxp_mpu_regions.c
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Linaro Limited.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include <soc.h>
|
||||||
|
#include <arch/arm/cortex_m/mpu/nxp_mpu.h>
|
||||||
|
|
||||||
|
#define FLEXBUS_BASE_ADDRESS 0x08000000
|
||||||
|
#define SRAM_L_BASE_ADDRESS 0x1FFF0000
|
||||||
|
#define DEVICE_S_BASE_ADDRESS 0x20030000
|
||||||
|
|
||||||
|
static struct nxp_mpu_region mpu_regions[] = {
|
||||||
|
/* Region 0 */
|
||||||
|
MPU_REGION_ENTRY("FLASH_0",
|
||||||
|
CONFIG_FLASH_BASE_ADDRESS,
|
||||||
|
0x07FFFFFF,
|
||||||
|
REGION_FLASH_ATTR),
|
||||||
|
/* Region 1 */
|
||||||
|
/*
|
||||||
|
* This region (Flexbus + FlexNVM) is bigger than the FLEXBUS one in
|
||||||
|
* order to save 1 region allocation in the MPU.
|
||||||
|
*/
|
||||||
|
MPU_REGION_ENTRY("FLEXBUS_0",
|
||||||
|
FLEXBUS_BASE_ADDRESS,
|
||||||
|
0x1BFFFFFF,
|
||||||
|
REGION_IO_ATTR),
|
||||||
|
/* Region 2 */
|
||||||
|
MPU_REGION_ENTRY("RAM_L_0",
|
||||||
|
SRAM_L_BASE_ADDRESS,
|
||||||
|
0x1FFFFFFF,
|
||||||
|
REGION_RAM_ATTR),
|
||||||
|
/* Region 3 */
|
||||||
|
MPU_REGION_ENTRY("RAM_U_0",
|
||||||
|
CONFIG_SRAM_BASE_ADDRESS,
|
||||||
|
(CONFIG_SRAM_BASE_ADDRESS +
|
||||||
|
(CONFIG_SRAM_SIZE * 1024) - 1),
|
||||||
|
REGION_RAM_ATTR),
|
||||||
|
/* Region 4 */
|
||||||
|
MPU_REGION_ENTRY("DEVICE_0",
|
||||||
|
DEVICE_S_BASE_ADDRESS,
|
||||||
|
0xFFFFFFFF,
|
||||||
|
REGION_IO_ATTR),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nxp_mpu_config mpu_config = {
|
||||||
|
.num_regions = ARRAY_SIZE(mpu_regions),
|
||||||
|
.mpu_regions = mpu_regions,
|
||||||
|
};
|
|
@ -153,7 +153,9 @@ static int fsl_frdm_k64f_init(struct device *arg)
|
||||||
ARG_UNUSED(arg);
|
ARG_UNUSED(arg);
|
||||||
|
|
||||||
int oldLevel; /* old interrupt lock level */
|
int oldLevel; /* old interrupt lock level */
|
||||||
|
#if !defined(CONFIG_HAS_SYSMPU)
|
||||||
u32_t temp_reg;
|
u32_t temp_reg;
|
||||||
|
#endif /* !CONFIG_HAS_SYSMPU */
|
||||||
|
|
||||||
/* disable interrupts */
|
/* disable interrupts */
|
||||||
oldLevel = irq_lock();
|
oldLevel = irq_lock();
|
||||||
|
@ -161,6 +163,7 @@ static int fsl_frdm_k64f_init(struct device *arg)
|
||||||
/* release I/O power hold to allow normal run state */
|
/* release I/O power hold to allow normal run state */
|
||||||
PMC->REGSC |= PMC_REGSC_ACKISO_MASK;
|
PMC->REGSC |= PMC_REGSC_ACKISO_MASK;
|
||||||
|
|
||||||
|
#if !defined(CONFIG_HAS_SYSMPU)
|
||||||
/*
|
/*
|
||||||
* Disable memory protection and clear slave port errors.
|
* Disable memory protection and clear slave port errors.
|
||||||
* Note that the K64F does not implement the optional ARMv7-M memory
|
* Note that the K64F does not implement the optional ARMv7-M memory
|
||||||
|
@ -171,6 +174,7 @@ static int fsl_frdm_k64f_init(struct device *arg)
|
||||||
temp_reg &= ~SYSMPU_CESR_VLD_MASK;
|
temp_reg &= ~SYSMPU_CESR_VLD_MASK;
|
||||||
temp_reg |= SYSMPU_CESR_SPERR_MASK;
|
temp_reg |= SYSMPU_CESR_SPERR_MASK;
|
||||||
SYSMPU->CESR = temp_reg;
|
SYSMPU->CESR = temp_reg;
|
||||||
|
#endif /* !CONFIG_HAS_SYSMPU */
|
||||||
|
|
||||||
_ClearFaults();
|
_ClearFaults();
|
||||||
|
|
||||||
|
|
|
@ -9,3 +9,6 @@ CONFIG_CORTEX_M_SYSTICK=y
|
||||||
CONFIG_GPIO=y
|
CONFIG_GPIO=y
|
||||||
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=120000000
|
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=120000000
|
||||||
CONFIG_OSC_EXTERNAL=y
|
CONFIG_OSC_EXTERNAL=y
|
||||||
|
|
||||||
|
# Enable MPU
|
||||||
|
CONFIG_HAS_SYSMPU=y
|
||||||
|
|
64
include/arch/arm/cortex_m/mpu/nxp_mpu.h
Normal file
64
include/arch/arm/cortex_m/mpu/nxp_mpu.h
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Linaro Limited.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef _NXP_MPU_H_
|
||||||
|
#define _NXP_MPU_H_
|
||||||
|
|
||||||
|
#include <fsl_common.h>
|
||||||
|
|
||||||
|
#define NXP_MPU_BASE SYSMPU_BASE
|
||||||
|
|
||||||
|
#define NXP_MPU_REGION_NUMBER 12
|
||||||
|
|
||||||
|
/* Read Attribute */
|
||||||
|
#define MPU_REGION_READ ((1 << 2) | (1 << 8) | (1 << 14))
|
||||||
|
|
||||||
|
/* Write Attribute */
|
||||||
|
#define MPU_REGION_WRITE ((1 << 1) | (1 << 7) | (1 << 13))
|
||||||
|
|
||||||
|
/* Execute Attribute */
|
||||||
|
#define MPU_REGION_EXEC ((1 << 0) | (1 << 6) | (1 << 12))
|
||||||
|
|
||||||
|
/* Super User Attributes */
|
||||||
|
#define MPU_REGION_SU ((3 << 3) | (3 << 9) | (3 << 15) | (3 << 21))
|
||||||
|
|
||||||
|
/* Some helper defines for common regions */
|
||||||
|
#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_IO_ATTR (MPU_REGION_READ | MPU_REGION_WRITE | \
|
||||||
|
MPU_REGION_EXEC | MPU_REGION_SU)
|
||||||
|
|
||||||
|
/* Region definition data structure */
|
||||||
|
struct nxp_mpu_region {
|
||||||
|
/* Region Base Address */
|
||||||
|
u32_t base;
|
||||||
|
/* Region End Address */
|
||||||
|
u32_t end;
|
||||||
|
/* Region Name */
|
||||||
|
const char *name;
|
||||||
|
/* Region Attributes */
|
||||||
|
u32_t attr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MPU_REGION_ENTRY(_name, _base, _end, _attr) \
|
||||||
|
{\
|
||||||
|
.name = _name, \
|
||||||
|
.base = _base, \
|
||||||
|
.end = _end, \
|
||||||
|
.attr = _attr, \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MPU configuration data structure */
|
||||||
|
struct nxp_mpu_config {
|
||||||
|
/* Number of regions */
|
||||||
|
u32_t num_regions;
|
||||||
|
/* Regions */
|
||||||
|
struct nxp_mpu_region *mpu_regions;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Reference to the MPU configuration */
|
||||||
|
extern struct nxp_mpu_config mpu_config;
|
||||||
|
|
||||||
|
#endif /* _NXP_MPU_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue