mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 11:56:10 +08:00
arm_mpu:Reentrant allocation Region
Changes have been completed: 1.armv7m 2.armv8m 3.armv7r 4.arm64 Signed-off-by: chenrun1 <chenrun1@xiaomi.com>
This commit is contained in:
+227
-13
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
#include "mpu.h"
|
#include "mpu.h"
|
||||||
#include "arm_internal.h"
|
#include "arm_internal.h"
|
||||||
@@ -69,9 +70,9 @@ static const uint8_t g_ls_regionmask[9] =
|
|||||||
0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
|
0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The next available region number */
|
/* The available region bitmap */
|
||||||
|
|
||||||
static uint8_t g_region;
|
static unsigned int g_mpu_region;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
@@ -89,6 +90,13 @@ static uint8_t g_region;
|
|||||||
* l2size has the same properties as the return value from
|
* l2size has the same properties as the return value from
|
||||||
* mpu_log2regionceil()
|
* mpu_log2regionceil()
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* size: The size of the region.
|
||||||
|
* l2size: The L2 size of the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The sub-region bitmask.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline uint32_t mpu_subregion_ms(size_t size, uint8_t l2size)
|
static inline uint32_t mpu_subregion_ms(size_t size, uint8_t l2size)
|
||||||
@@ -140,6 +148,13 @@ static inline uint32_t mpu_subregion_ms(size_t size, uint8_t l2size)
|
|||||||
* l2size has the same properties as the return value from
|
* l2size has the same properties as the return value from
|
||||||
* mpu_log2regionceil()
|
* mpu_log2regionceil()
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* offset: The offset of the region.
|
||||||
|
* l2size: The L2 size of the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The sub-region bitmask.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline uint32_t mpu_subregion_ls(size_t offset, uint8_t l2size)
|
static inline uint32_t mpu_subregion_ls(size_t offset, uint8_t l2size)
|
||||||
@@ -184,6 +199,12 @@ static inline uint32_t mpu_subregion_ls(size_t offset, uint8_t l2size)
|
|||||||
* Description:
|
* Description:
|
||||||
* Resets the MPU to disabled.
|
* Resets the MPU to disabled.
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if defined(CONFIG_ARM_MPU_RESET) || defined(CONFIG_ARM_MPU_EARLY_RESET)
|
#if defined(CONFIG_ARM_MPU_RESET) || defined(CONFIG_ARM_MPU_EARLY_RESET)
|
||||||
@@ -218,17 +239,51 @@ static void mpu_reset_internal()
|
|||||||
* Description:
|
* Description:
|
||||||
* Allocate the next region
|
* Allocate the next region
|
||||||
*
|
*
|
||||||
* Assumptions:
|
* Input Parameters:
|
||||||
* - Regions are never deallocated
|
* None
|
||||||
* - Regions are only allocated early in initialization, so no special
|
*
|
||||||
* protection against re-entrancy is required;
|
* Returned Value:
|
||||||
|
* The index of the allocated region.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
unsigned int mpu_allocregion(void)
|
unsigned int mpu_allocregion(void)
|
||||||
{
|
{
|
||||||
DEBUGASSERT(g_region < CONFIG_ARM_MPU_NREGIONS);
|
unsigned int i = ffs(~g_mpu_region) - 1;
|
||||||
return (unsigned int)g_region++;
|
|
||||||
|
/* There are not enough regions to apply */
|
||||||
|
|
||||||
|
DEBUGASSERT(i < CONFIG_ARM_MPU_NREGIONS);
|
||||||
|
g_mpu_region |= 1 << i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_freeregion
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Free target region.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* region - The index of the region to be freed.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_freeregion(unsigned int region)
|
||||||
|
{
|
||||||
|
DEBUGASSERT(region < CONFIG_ARM_MPU_NREGIONS);
|
||||||
|
|
||||||
|
/* Clear and disable the given MPU Region */
|
||||||
|
|
||||||
|
putreg32(region, MPU_RNR);
|
||||||
|
putreg32(0, MPU_RASR);
|
||||||
|
putreg32(0, MPU_RBAR);
|
||||||
|
g_mpu_region &= ~(1 << region);
|
||||||
|
ARM_DSB();
|
||||||
|
ARM_ISB();
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -240,6 +295,12 @@ unsigned int mpu_allocregion(void)
|
|||||||
*
|
*
|
||||||
* size <= (1 << l2size)
|
* size <= (1 << l2size)
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* size - The size of the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The logarithm base 2 of the ceiling value for the MPU region size.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
uint8_t mpu_log2regionceil(size_t size)
|
uint8_t mpu_log2regionceil(size_t size)
|
||||||
@@ -261,6 +322,12 @@ uint8_t mpu_log2regionceil(size_t size)
|
|||||||
*
|
*
|
||||||
* size >= (1 << l2size)
|
* size >= (1 << l2size)
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* size - The size of the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The logarithm base 2 of the floor value for the MPU region size.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
uint8_t mpu_log2regionfloor(size_t size)
|
uint8_t mpu_log2regionfloor(size_t size)
|
||||||
@@ -287,6 +354,14 @@ uint8_t mpu_log2regionfloor(size_t size)
|
|||||||
* l2size has the same properties as the return value from
|
* l2size has the same properties as the return value from
|
||||||
* mpu_log2regionceil()
|
* mpu_log2regionceil()
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* base - The base address of the region.
|
||||||
|
* size - The size of the region.
|
||||||
|
* l2size - Log2 of the actual region size is <= (1 << l2size).
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The subregion settings as a 32-bit value.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
uint32_t mpu_subregion(uintptr_t base, size_t size, uint8_t l2size)
|
uint32_t mpu_subregion(uintptr_t base, size_t size, uint8_t l2size)
|
||||||
@@ -338,6 +413,16 @@ uint32_t mpu_subregion(uintptr_t base, size_t size, uint8_t l2size)
|
|||||||
* Description:
|
* Description:
|
||||||
* Configure and enable (or disable) the MPU
|
* Configure and enable (or disable) the MPU
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* enable - Flag indicating whether to enable the MPU.
|
||||||
|
* hfnmiena - Flag indicating whether to enable the MPU during hard
|
||||||
|
* fult, NMI, and FAULTMAS.
|
||||||
|
* privdefena - Flag indicating whether to enable privileged access to
|
||||||
|
* the default memory map.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void mpu_control(bool enable, bool hfnmiena, bool privdefena)
|
void mpu_control(bool enable, bool hfnmiena, bool privdefena)
|
||||||
@@ -368,22 +453,34 @@ void mpu_control(bool enable, bool hfnmiena, bool privdefena)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_configure_region
|
* Name: mpu_modify_region
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Configure a region for privileged, strongly ordered memory
|
* Modify a region for privileged, strongly ordered memory
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* region - Region number to modify.
|
||||||
|
* base - Base address of the region.
|
||||||
|
* size - Size of the region.
|
||||||
|
* flags - Flags to configure the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void mpu_configure_region(uintptr_t base, size_t size,
|
void mpu_modify_region(unsigned int region, uintptr_t base, size_t size,
|
||||||
uint32_t flags)
|
uint32_t flags)
|
||||||
{
|
{
|
||||||
unsigned int region = mpu_allocregion();
|
|
||||||
uint32_t regval;
|
uint32_t regval;
|
||||||
uint8_t l2size;
|
uint8_t l2size;
|
||||||
uint8_t subregions;
|
uint8_t subregions;
|
||||||
uintptr_t alignedbase;
|
uintptr_t alignedbase;
|
||||||
|
|
||||||
|
/* Check that the region is valid */
|
||||||
|
|
||||||
|
DEBUGASSERT(g_mpu_region & (1 << region));
|
||||||
|
|
||||||
/* Ensure the base address alignment
|
/* Ensure the base address alignment
|
||||||
*
|
*
|
||||||
* ARMv7-M Architecture Reference Manual
|
* ARMv7-M Architecture Reference Manual
|
||||||
@@ -429,6 +526,111 @@ void mpu_configure_region(uintptr_t base, size_t size,
|
|||||||
ARM_ISB();
|
ARM_ISB();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_configure_region
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Configure a region for privileged, strongly ordered memory
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* base - Base address of the region.
|
||||||
|
* size - Size of the region.
|
||||||
|
* flags - Flags to configure the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The region number allocated for the configured region.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
unsigned int mpu_configure_region(uintptr_t base, size_t size,
|
||||||
|
uint32_t flags)
|
||||||
|
{
|
||||||
|
unsigned int region = mpu_allocregion();
|
||||||
|
mpu_modify_region(region, base, size, flags);
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_initialize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Configure a region for privileged, strongly ordered memory
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* table - MPU initialization table.
|
||||||
|
* hfnmiena - A boolean indicating whether the MPU should enable the
|
||||||
|
* HFNMIENA bit.
|
||||||
|
* privdefena - A boolean indicating whether the MPU should enable the
|
||||||
|
* PRIVDEFENA bit.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* NULL.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_initialize(const struct mpu_region_s *table, bool hfnmiena,
|
||||||
|
bool privdefena)
|
||||||
|
{
|
||||||
|
const struct mpu_region_s *conf;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
mpu_control(false, false, false);
|
||||||
|
for (index = 0; index < nitems(table); index++)
|
||||||
|
{
|
||||||
|
conf = &table[index];
|
||||||
|
mpu_configure_region(conf->base, conf->size, conf->flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpu_control(true, hfnmiena, privdefena);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_dump_region
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Dump the region that has been used.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_dump_region(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int count = 0;
|
||||||
|
uint32_t rasr;
|
||||||
|
uint32_t rbar;
|
||||||
|
uint32_t ctrl;
|
||||||
|
|
||||||
|
/* Get free region */
|
||||||
|
|
||||||
|
ctrl = getreg32(MPU_CTRL);
|
||||||
|
_info("MPU-CTRL Enable:%" PRIu32 ", HFNMIENA:%"PRIu32","
|
||||||
|
"PRIVDEFENA:%" PRIu32 "\n", ctrl & MPU_CTRL_ENABLE,
|
||||||
|
ctrl & MPU_CTRL_HFNMIENA, ctrl & MPU_CTRL_PRIVDEFENA);
|
||||||
|
for (i = 0; i < CONFIG_ARM_MPU_NREGIONS; i++)
|
||||||
|
{
|
||||||
|
putreg32(i, MPU_RNR);
|
||||||
|
rasr = getreg32(MPU_RASR);
|
||||||
|
rbar = getreg32(MPU_RBAR);
|
||||||
|
_info("MPU-%d, alignedbase=0%08X l2size=%"PRIu32" SRD=%X"
|
||||||
|
"AP=%X XN=%u\n", i, rbar & MPU_RBAR_ADDR_MASK,
|
||||||
|
rasr & MPU_RASR_SIZE_MASK, rasr & MPU_RASR_SRD_MASK,
|
||||||
|
rasr & MPU_RASR_AP_MASK, rasr & MPU_RASR_XN);
|
||||||
|
if (rasr & MPU_RASR_ENABLE)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_info("Total Use Region:%d, Remaining Available:%d\n", count,
|
||||||
|
CONFIG_ARM_MPU_NREGIONS - count);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_reset
|
* Name: mpu_reset
|
||||||
*
|
*
|
||||||
@@ -436,6 +638,12 @@ void mpu_configure_region(uintptr_t base, size_t size,
|
|||||||
* Conditional public interface that resets the MPU to disabled during
|
* Conditional public interface that resets the MPU to disabled during
|
||||||
* MPU initialization.
|
* MPU initialization.
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#if defined(CONFIG_ARM_MPU_RESET)
|
#if defined(CONFIG_ARM_MPU_RESET)
|
||||||
void mpu_reset()
|
void mpu_reset()
|
||||||
@@ -451,6 +659,12 @@ void mpu_reset()
|
|||||||
* Conditional public interface that resets the MPU to disabled immediately
|
* Conditional public interface that resets the MPU to disabled immediately
|
||||||
* after reset.
|
* after reset.
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#if defined(CONFIG_ARM_MPU_EARLY_RESET)
|
#if defined(CONFIG_ARM_MPU_EARLY_RESET)
|
||||||
void mpu_early_reset()
|
void mpu_early_reset()
|
||||||
|
|||||||
+231
-121
@@ -130,6 +130,21 @@
|
|||||||
# define MPU_RASR_AP_RORO (6 << MPU_RASR_AP_SHIFT) /* P:RO U:RO */
|
# define MPU_RASR_AP_RORO (6 << MPU_RASR_AP_SHIFT) /* P:RO U:RO */
|
||||||
# define MPU_RASR_XN (1 << 28) /* Bit 28: Instruction access disable */
|
# define MPU_RASR_XN (1 << 28) /* Bit 28: Instruction access disable */
|
||||||
|
|
||||||
|
struct mpu_region_s
|
||||||
|
{
|
||||||
|
/* Region Base Address */
|
||||||
|
|
||||||
|
uintptr_t base;
|
||||||
|
|
||||||
|
/* Region Size */
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
/* Region Attributes */
|
||||||
|
|
||||||
|
uint32_t flags;
|
||||||
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_reset
|
* Name: mpu_reset
|
||||||
*
|
*
|
||||||
@@ -137,6 +152,12 @@
|
|||||||
* Conditional public interface that resets the MPU to disabled during
|
* Conditional public interface that resets the MPU to disabled during
|
||||||
* MPU initialization.
|
* MPU initialization.
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if defined(CONFIG_ARM_MPU_RESET)
|
#if defined(CONFIG_ARM_MPU_RESET)
|
||||||
@@ -152,6 +173,12 @@ void mpu_reset(void);
|
|||||||
* Conditional public interface that resets the MPU to disabled immediately
|
* Conditional public interface that resets the MPU to disabled immediately
|
||||||
* after reset.
|
* after reset.
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if defined(CONFIG_ARM_MPU_EARLY_RESET)
|
#if defined(CONFIG_ARM_MPU_EARLY_RESET)
|
||||||
@@ -180,12 +207,34 @@ extern "C"
|
|||||||
* Name: mpu_allocregion
|
* Name: mpu_allocregion
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Allocate the next region
|
* Allocate the next region
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The index of the allocated region.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
unsigned int mpu_allocregion(void);
|
unsigned int mpu_allocregion(void);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_freeregion
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Free target region.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* region - The index of the region to be freed.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_freeregion(unsigned int region);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_log2regionceil
|
* Name: mpu_log2regionceil
|
||||||
*
|
*
|
||||||
@@ -195,6 +244,12 @@ unsigned int mpu_allocregion(void);
|
|||||||
*
|
*
|
||||||
* size <= (1 << l2size)
|
* size <= (1 << l2size)
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* size - The size of the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The logarithm base 2 of the ceiling value for the MPU region size.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
uint8_t mpu_log2regionceil(size_t size);
|
uint8_t mpu_log2regionceil(size_t size);
|
||||||
@@ -208,6 +263,12 @@ uint8_t mpu_log2regionceil(size_t size);
|
|||||||
*
|
*
|
||||||
* size >= (1 << l2size)
|
* size >= (1 << l2size)
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* size - The size of the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The logarithm base 2 of the floor value for the MPU region size.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
uint8_t mpu_log2regionfloor(size_t size);
|
uint8_t mpu_log2regionfloor(size_t size);
|
||||||
@@ -216,14 +277,22 @@ uint8_t mpu_log2regionfloor(size_t size);
|
|||||||
* Name: mpu_subregion
|
* Name: mpu_subregion
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Given (1) the offset to the beginning of valid data, (2) the size of the
|
* Given the size of the (1) memory to be mapped and (2) the log2 size
|
||||||
* memory to be mapped and (2) the log2 size of the mapping to use,
|
* of the mapping to use, determine the minimal sub-region set to span
|
||||||
* determine the minimal sub-region set to span that memory region.
|
* that memory region.
|
||||||
*
|
*
|
||||||
* Assumption:
|
* Assumption:
|
||||||
* l2size has the same properties as the return value from
|
* l2size has the same properties as the return value from
|
||||||
* mpu_log2regionceil()
|
* mpu_log2regionceil()
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* base - The base address of the region.
|
||||||
|
* size - The size of the region.
|
||||||
|
* l2size - Log2 of the actual region size is <= (1 << l2size).
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The subregion settings as a 32-bit value.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
uint32_t mpu_subregion(uintptr_t base, size_t size, uint8_t l2size);
|
uint32_t mpu_subregion(uintptr_t base, size_t size, uint8_t l2size);
|
||||||
@@ -234,19 +303,95 @@ uint32_t mpu_subregion(uintptr_t base, size_t size, uint8_t l2size);
|
|||||||
* Description:
|
* Description:
|
||||||
* Configure and enable (or disable) the MPU
|
* Configure and enable (or disable) the MPU
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* enable - Flag indicating whether to enable the MPU.
|
||||||
|
* hfnmiena - Flag indicating whether to enable the MPU during hard
|
||||||
|
* fult, NMI, and FAULTMAS.
|
||||||
|
* privdefena - Flag indicating whether to enable privileged access to
|
||||||
|
* the default memory map.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void mpu_control(bool enable, bool hfnmiena, bool privdefena);
|
void mpu_control(bool enable, bool hfnmiena, bool privdefena);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_dump_region
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Dump the region that has been used.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_dump_region(void);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_modify_region
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Modify a region for privileged, strongly ordered memory
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* region - Region number to modify.
|
||||||
|
* base - Base address of the region.
|
||||||
|
* size - Size of the region.
|
||||||
|
* flags - Flags to configure the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_modify_region(unsigned int region, uintptr_t base, size_t size,
|
||||||
|
uint32_t flags);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_configure_region
|
* Name: mpu_configure_region
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Configure a region for privileged, strongly ordered memory
|
* Configure a region for privileged, strongly ordered memory
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* base - Base address of the region.
|
||||||
|
* size - Size of the region.
|
||||||
|
* flags - Flags to configure the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The region number allocated for the configured region.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void mpu_configure_region(uintptr_t base, size_t size, uint32_t flags);
|
unsigned int mpu_configure_region(uintptr_t base, size_t size,
|
||||||
|
uint32_t flags);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_initialize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Configure a region for privileged, strongly ordered memory
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* table - MPU initialization table.
|
||||||
|
* hfnmiena - A boolean indicating whether the MPU should enable the
|
||||||
|
* HFNMIENA bit.
|
||||||
|
* privdefena - A boolean indicating whether the MPU should enable the
|
||||||
|
* PRIVDEFENA bit.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* NULL.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_initialize(const struct mpu_region_s *table, bool hfnmiena,
|
||||||
|
bool privdefena);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Inline Functions
|
* Inline Functions
|
||||||
@@ -284,18 +429,14 @@ void mpu_configure_region(uintptr_t base, size_t size, uint32_t flags);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_priv_stronglyordered(base, size) \
|
#define mpu_priv_stronglyordered(base, size) \
|
||||||
do \
|
/* The configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* The configure the region */ \
|
MPU_RASR_TEX_SO | /* Ordered */ \
|
||||||
mpu_configure_region(base, size, \
|
/* Not Cacheable */ \
|
||||||
MPU_RASR_TEX_SO | /* Ordered */ \
|
/* Not Bufferable */ \
|
||||||
/* Not Cacheable */ \
|
MPU_RASR_S | /* Shareable */ \
|
||||||
/* Not Bufferable */ \
|
MPU_RASR_AP_RWNO /* P:RW U:None */ \
|
||||||
MPU_RASR_S | /* Shareable */ \
|
/* Instruction access */)
|
||||||
MPU_RASR_AP_RWNO /* P:RW U:None */ \
|
|
||||||
/* Instruction access */); \
|
|
||||||
} \
|
|
||||||
while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_user_flash
|
* Name: mpu_user_flash
|
||||||
@@ -306,18 +447,14 @@ void mpu_configure_region(uintptr_t base, size_t size, uint32_t flags);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_user_flash(base, size) \
|
#define mpu_user_flash(base, size) \
|
||||||
do \
|
/* The configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* The configure the region */ \
|
MPU_RASR_TEX_SO | /* Ordered */ \
|
||||||
mpu_configure_region(base, size, \
|
MPU_RASR_C | /* Cacheable */ \
|
||||||
MPU_RASR_TEX_SO | /* Ordered */ \
|
/* Not Bufferable */ \
|
||||||
MPU_RASR_C | /* Cacheable */ \
|
/* Not Shareable */ \
|
||||||
/* Not Bufferable */ \
|
MPU_RASR_AP_RORO /* P:RO U:RO */ \
|
||||||
/* Not Shareable */ \
|
/* Instruction access */)
|
||||||
MPU_RASR_AP_RORO /* P:RO U:RO */ \
|
|
||||||
/* Instruction access */); \
|
|
||||||
} \
|
|
||||||
while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_priv_flash
|
* Name: mpu_priv_flash
|
||||||
@@ -328,18 +465,14 @@ void mpu_configure_region(uintptr_t base, size_t size, uint32_t flags);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_priv_flash(base, size) \
|
#define mpu_priv_flash(base, size) \
|
||||||
do \
|
/* The configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* The configure the region */ \
|
MPU_RASR_TEX_SO | /* Ordered */ \
|
||||||
mpu_configure_region(base, size, \
|
MPU_RASR_C | /* Cacheable */ \
|
||||||
MPU_RASR_TEX_SO | /* Ordered */ \
|
/* Not Bufferable */ \
|
||||||
MPU_RASR_C | /* Cacheable */ \
|
/* Not Shareable */ \
|
||||||
/* Not Bufferable */ \
|
MPU_RASR_AP_RONO /* P:RO U:None */ \
|
||||||
/* Not Shareable */ \
|
/* Instruction access */)
|
||||||
MPU_RASR_AP_RONO /* P:RO U:None */ \
|
|
||||||
/* Instruction access */); \
|
|
||||||
} \
|
|
||||||
while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_user_intsram
|
* Name: mpu_user_intsram
|
||||||
@@ -350,18 +483,14 @@ void mpu_configure_region(uintptr_t base, size_t size, uint32_t flags);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_user_intsram(base, size) \
|
#define mpu_user_intsram(base, size) \
|
||||||
do \
|
/* The configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* The configure the region */ \
|
MPU_RASR_TEX_SO | /* Ordered */ \
|
||||||
mpu_configure_region(base, size, \
|
MPU_RASR_C | /* Cacheable */ \
|
||||||
MPU_RASR_TEX_SO | /* Ordered */ \
|
/* Not Bufferable */ \
|
||||||
MPU_RASR_C | /* Cacheable */ \
|
MPU_RASR_S | /* Shareable */ \
|
||||||
/* Not Bufferable */ \
|
MPU_RASR_AP_RWRW /* P:RW U:RW */ \
|
||||||
MPU_RASR_S | /* Shareable */ \
|
/* Instruction access */)
|
||||||
MPU_RASR_AP_RWRW /* P:RW U:RW */ \
|
|
||||||
/* Instruction access */); \
|
|
||||||
} \
|
|
||||||
while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_priv_intsram
|
* Name: mpu_priv_intsram
|
||||||
@@ -372,18 +501,14 @@ void mpu_configure_region(uintptr_t base, size_t size, uint32_t flags);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_priv_intsram(base, size) \
|
#define mpu_priv_intsram(base, size) \
|
||||||
do \
|
/* The configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* The configure the region */ \
|
MPU_RASR_TEX_SO | /* Ordered */ \
|
||||||
mpu_configure_region(base, size, \
|
MPU_RASR_C | /* Cacheable */ \
|
||||||
MPU_RASR_TEX_SO | /* Ordered */ \
|
/* Not Bufferable */ \
|
||||||
MPU_RASR_C | /* Cacheable */ \
|
MPU_RASR_S | /* Shareable */ \
|
||||||
/* Not Bufferable */ \
|
MPU_RASR_AP_RWNO /* P:RW U:None */ \
|
||||||
MPU_RASR_S | /* Shareable */ \
|
/* Instruction access */)
|
||||||
MPU_RASR_AP_RWNO /* P:RW U:None */ \
|
|
||||||
/* Instruction access */); \
|
|
||||||
} \
|
|
||||||
while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_priv_shmem
|
* Name: mpu_priv_shmem
|
||||||
@@ -393,18 +518,15 @@ void mpu_configure_region(uintptr_t base, size_t size, uint32_t flags);
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_priv_shmem(base, size) \
|
#define mpu_priv_shmem(base, size) \
|
||||||
do \
|
/* The configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* The configure the region */ \
|
MPU_RASR_TEX_SO | /* Ordered */ \
|
||||||
mpu_configure_region(base, size, \
|
/* Not Cacheable */ \
|
||||||
MPU_RASR_TEX_SO | /* Ordered */ \
|
MPU_RASR_B | /* Bufferable */ \
|
||||||
/* Not Cacheable */ \
|
MPU_RASR_S | /* Shareable */ \
|
||||||
MPU_RASR_B | /* Bufferable */ \
|
MPU_RASR_AP_RWNO | /* P:RW U:None */ \
|
||||||
MPU_RASR_S | /* Shareable */ \
|
MPU_RASR_XN /* No Instruction access */)
|
||||||
MPU_RASR_AP_RWNO | /* P:RW U:None */ \
|
|
||||||
MPU_RASR_XN /* No Instruction access */); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_user_extsram
|
* Name: mpu_user_extsram
|
||||||
@@ -415,17 +537,14 @@ void mpu_configure_region(uintptr_t base, size_t size, uint32_t flags);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_user_extsram(base, size) \
|
#define mpu_user_extsram(base, size) \
|
||||||
do \
|
/* The configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* The configure the region */ \
|
MPU_RASR_TEX_SO | /* Ordered */ \
|
||||||
mpu_configure_region(base, size, \
|
MPU_RASR_C | /* Cacheable */ \
|
||||||
MPU_RASR_TEX_SO | /* Ordered */ \
|
MPU_RASR_B | /* Bufferable */ \
|
||||||
MPU_RASR_C | /* Cacheable */ \
|
MPU_RASR_S | /* Shareable */ \
|
||||||
MPU_RASR_B | /* Bufferable */ \
|
MPU_RASR_AP_RWRW /* P:RW U:RW */ \
|
||||||
MPU_RASR_S | /* Shareable */ \
|
/* Instruction access */)
|
||||||
MPU_RASR_AP_RWRW /* P:RW U:RW */ \
|
|
||||||
/* Instruction access */); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_priv_extsram
|
* Name: mpu_priv_extsram
|
||||||
@@ -436,17 +555,14 @@ void mpu_configure_region(uintptr_t base, size_t size, uint32_t flags);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_priv_extsram(base, size) \
|
#define mpu_priv_extsram(base, size) \
|
||||||
do \
|
/* The configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* The configure the region */ \
|
MPU_RASR_TEX_SO | /* Ordered */ \
|
||||||
mpu_configure_region(base, size, \
|
MPU_RASR_C | /* Cacheable */ \
|
||||||
MPU_RASR_TEX_SO | /* Ordered */ \
|
MPU_RASR_B | /* Bufferable */ \
|
||||||
MPU_RASR_C | /* Cacheable */ \
|
MPU_RASR_S | /* Shareable */ \
|
||||||
MPU_RASR_B | /* Bufferable */ \
|
MPU_RASR_AP_RWNO /* P:RW U:None */ \
|
||||||
MPU_RASR_S | /* Shareable */ \
|
/* Instruction access */)
|
||||||
MPU_RASR_AP_RWNO /* P:RW U:None */ \
|
|
||||||
/* Instruction access */); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_peripheral
|
* Name: mpu_peripheral
|
||||||
@@ -457,17 +573,14 @@ void mpu_configure_region(uintptr_t base, size_t size, uint32_t flags);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_peripheral(base, size) \
|
#define mpu_peripheral(base, size) \
|
||||||
do \
|
/* Then configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* Then configure the region */ \
|
MPU_RASR_TEX_DEV | /* Device */ \
|
||||||
mpu_configure_region(base, size, \
|
/* Not Cacheable */ \
|
||||||
MPU_RASR_TEX_DEV | /* Device */ \
|
MPU_RASR_B | /* Bufferable */ \
|
||||||
/* Not Cacheable */ \
|
MPU_RASR_S | /* Shareable */ \
|
||||||
MPU_RASR_B | /* Bufferable */ \
|
MPU_RASR_AP_RWNO | /* P:RW U:None */ \
|
||||||
MPU_RASR_S | /* Shareable */ \
|
MPU_RASR_XN /* No Instruction access */)
|
||||||
MPU_RASR_AP_RWNO | /* P:RW U:None */ \
|
|
||||||
MPU_RASR_XN /* No Instruction access */); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_user_peripheral
|
* Name: mpu_user_peripheral
|
||||||
@@ -478,17 +591,14 @@ void mpu_configure_region(uintptr_t base, size_t size, uint32_t flags);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_user_peripheral(base, size) \
|
#define mpu_user_peripheral(base, size) \
|
||||||
do \
|
/* Then configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* Then configure the region */ \
|
MPU_RASR_TEX_DEV | /* Device */ \
|
||||||
mpu_configure_region(base, size, \
|
/* Not Cacheable */ \
|
||||||
MPU_RASR_TEX_DEV | /* Device */ \
|
MPU_RASR_B | /* Bufferable */ \
|
||||||
/* Not Cacheable */ \
|
MPU_RASR_S | /* Shareable */ \
|
||||||
MPU_RASR_B | /* Bufferable */ \
|
MPU_RASR_AP_RWRW | /* P:RW U:RW */ \
|
||||||
MPU_RASR_S | /* Shareable */ \
|
MPU_RASR_XN /* No Instruction access */)
|
||||||
MPU_RASR_AP_RWRW | /* P:RW U:RW */ \
|
|
||||||
MPU_RASR_XN /* No Instruction access */); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
#include "mpu.h"
|
#include "mpu.h"
|
||||||
#include "arm_internal.h"
|
#include "arm_internal.h"
|
||||||
@@ -68,9 +69,9 @@ static const uint8_t g_ls_regionmask[9] =
|
|||||||
0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
|
0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The next available region number */
|
/* The available region bitmap */
|
||||||
|
|
||||||
static uint8_t g_region;
|
static unsigned int g_mpu_region;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
@@ -88,6 +89,13 @@ static uint8_t g_region;
|
|||||||
* l2size has the same properties as the return value from
|
* l2size has the same properties as the return value from
|
||||||
* mpu_log2regionceil()
|
* mpu_log2regionceil()
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* size: The size of the region.
|
||||||
|
* l2size: The L2 size of the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The sub-region bitmask.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline uint32_t mpu_subregion_ms(size_t size, uint8_t l2size)
|
static inline uint32_t mpu_subregion_ms(size_t size, uint8_t l2size)
|
||||||
@@ -139,6 +147,13 @@ static inline uint32_t mpu_subregion_ms(size_t size, uint8_t l2size)
|
|||||||
* l2size has the same properties as the return value from
|
* l2size has the same properties as the return value from
|
||||||
* mpu_log2regionceil()
|
* mpu_log2regionceil()
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* offset: The offset of the region.
|
||||||
|
* l2size: The L2 size of the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The sub-region bitmask.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline uint32_t mpu_subregion_ls(size_t offset, uint8_t l2size)
|
static inline uint32_t mpu_subregion_ls(size_t offset, uint8_t l2size)
|
||||||
@@ -183,6 +198,12 @@ static inline uint32_t mpu_subregion_ls(size_t offset, uint8_t l2size)
|
|||||||
* Description:
|
* Description:
|
||||||
* Resets the MPU to disabled.
|
* Resets the MPU to disabled.
|
||||||
*
|
*
|
||||||
|
* * Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if defined(CONFIG_ARM_MPU_RESET) || defined(CONFIG_ARM_MPU_EARLY_RESET)
|
#if defined(CONFIG_ARM_MPU_RESET) || defined(CONFIG_ARM_MPU_EARLY_RESET)
|
||||||
@@ -214,17 +235,52 @@ static void mpu_reset_internal()
|
|||||||
* Description:
|
* Description:
|
||||||
* Allocate the next region
|
* Allocate the next region
|
||||||
*
|
*
|
||||||
* Assumptions:
|
* Input Parameters:
|
||||||
* - Regions are never deallocated
|
* None
|
||||||
* - Regions are only allocated early in initialization, so no special
|
*
|
||||||
* protection against re-entrancy is required;
|
* Returned Value:
|
||||||
|
* The index of the allocated region.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
unsigned int mpu_allocregion(void)
|
unsigned int mpu_allocregion(void)
|
||||||
{
|
{
|
||||||
DEBUGASSERT(g_region < CONFIG_ARM_MPU_NREGIONS);
|
unsigned int i = ffs(~g_mpu_region) - 1;
|
||||||
return (unsigned int)g_region++;
|
|
||||||
|
/* There are not enough regions to apply */
|
||||||
|
|
||||||
|
DEBUGASSERT(i < CONFIG_ARM_MPU_NREGIONS);
|
||||||
|
g_mpu_region |= 1 << i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_freeregion
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Free target region.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* region - The index of the region to be freed.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_freeregion(unsigned int region)
|
||||||
|
{
|
||||||
|
DEBUGASSERT(region < CONFIG_ARM_MPU_NREGIONS);
|
||||||
|
|
||||||
|
/* Clear and disable the given MPU Region */
|
||||||
|
|
||||||
|
mpu_set_rgnr(region);
|
||||||
|
mpu_set_drbar(0);
|
||||||
|
mpu_set_dracr(0);
|
||||||
|
mpu_set_drsr(0);
|
||||||
|
g_mpu_region &= ~(1 << region);
|
||||||
|
ARM_DSB();
|
||||||
|
ARM_ISB();
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -236,6 +292,12 @@ unsigned int mpu_allocregion(void)
|
|||||||
*
|
*
|
||||||
* size <= (1 << l2size)
|
* size <= (1 << l2size)
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* size - The size of the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The logarithm base 2 of the ceiling value for the MPU region size.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
uint8_t mpu_log2regionceil(size_t size)
|
uint8_t mpu_log2regionceil(size_t size)
|
||||||
@@ -257,6 +319,12 @@ uint8_t mpu_log2regionceil(size_t size)
|
|||||||
*
|
*
|
||||||
* size >= (1 << l2size)
|
* size >= (1 << l2size)
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* size - The size of the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The logarithm base 2 of the floor value for the MPU region size.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
uint8_t mpu_log2regionfloor(size_t size)
|
uint8_t mpu_log2regionfloor(size_t size)
|
||||||
@@ -283,6 +351,14 @@ uint8_t mpu_log2regionfloor(size_t size)
|
|||||||
* l2size has the same properties as the return value from
|
* l2size has the same properties as the return value from
|
||||||
* mpu_log2regionceil()
|
* mpu_log2regionceil()
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* base - The base address of the region.
|
||||||
|
* size - The size of the region.
|
||||||
|
* l2size - Log2 of the actual region size is <= (1 << l2size).
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The subregion settings as a 32-bit value.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
uint32_t mpu_subregion(uintptr_t base, size_t size, uint8_t l2size)
|
uint32_t mpu_subregion(uintptr_t base, size_t size, uint8_t l2size)
|
||||||
@@ -328,6 +404,156 @@ uint32_t mpu_subregion(uintptr_t base, size_t size, uint8_t l2size)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_modify_region
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Modify a region for privileged, strongly ordered memory
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* region - Region number to modify.
|
||||||
|
* base - Base address of the region.
|
||||||
|
* size - Size of the region.
|
||||||
|
* flags - Flags to configure the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_modify_region(unsigned int region, uintptr_t base, size_t size,
|
||||||
|
uint32_t flags)
|
||||||
|
{
|
||||||
|
uint32_t regval;
|
||||||
|
uint8_t l2size;
|
||||||
|
uint8_t subregions;
|
||||||
|
|
||||||
|
/* Check that the region is valid */
|
||||||
|
|
||||||
|
DEBUGASSERT(g_mpu_region & (1 << region));
|
||||||
|
|
||||||
|
/* Select the region */
|
||||||
|
|
||||||
|
mpu_set_rgnr(region);
|
||||||
|
|
||||||
|
/* Select the region base address */
|
||||||
|
|
||||||
|
mpu_set_drbar(base & MPU_RBAR_ADDR_MASK);
|
||||||
|
|
||||||
|
/* Select the region size and the sub-region map */
|
||||||
|
|
||||||
|
l2size = mpu_log2regionceil(size);
|
||||||
|
subregions = mpu_subregion(base, size, l2size);
|
||||||
|
|
||||||
|
/* Configure the Region */
|
||||||
|
|
||||||
|
mpu_set_dracr(flags);
|
||||||
|
regval = MPU_RASR_ENABLE | /* Enable region */
|
||||||
|
MPU_RASR_RSIZE_LOG2(l2size) | /* Region size */
|
||||||
|
(subregions << MPU_RASR_SRD_SHIFT); /* Sub-regions */
|
||||||
|
mpu_set_drsr(regval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_configure_region
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Configure a region.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* base - Base address of the region.
|
||||||
|
* size - Size of the region.
|
||||||
|
* flags - Flags to configure the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The region number allocated for the configured region.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
unsigned int mpu_configure_region(uintptr_t base, size_t size,
|
||||||
|
uint32_t flags)
|
||||||
|
{
|
||||||
|
unsigned int region = mpu_allocregion();
|
||||||
|
mpu_modify_region(region, base, size, flags);
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_initialize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Configure a region for privileged, strongly ordered memory
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* table - MPU Initiaze table.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* NULL.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_initialize(const struct mpu_region_s *table)
|
||||||
|
{
|
||||||
|
const struct mpu_region_s *conf;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
mpu_control(false);
|
||||||
|
for (index = 0; index < nitems(table); index++)
|
||||||
|
{
|
||||||
|
conf = &table[index];
|
||||||
|
mpu_configure_region(conf->base, conf->size, conf->flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpu_control(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_dump_region
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Dump the region that has been used.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_dump_region(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int count = 0;
|
||||||
|
uint32_t dracr;
|
||||||
|
uint32_t drbar;
|
||||||
|
uint32_t drsr;
|
||||||
|
uint32_t sctrl;
|
||||||
|
|
||||||
|
/* Get free region */
|
||||||
|
|
||||||
|
sctrl = cp15_rdsctlr();
|
||||||
|
_info("MPU-SCTRL Enable:%" PRIu32 "\n", sctrl & SCTLR_M);
|
||||||
|
for (i = 0; i < CONFIG_ARM_MPU_NREGIONS; i++)
|
||||||
|
{
|
||||||
|
mpu_set_rgnr(i);
|
||||||
|
drbar = mpu_get_drbar();
|
||||||
|
dracr = mpu_get_dracr();
|
||||||
|
drsr = mpu_get_drsr();
|
||||||
|
_info("MPU-%d, base=0%08X l2size=%"PRIu32" bufferable=%u"
|
||||||
|
"cacheable=%u shareable=%u\n", i, drbar & MPU_RBAR_ADDR_MASK,
|
||||||
|
drsr & MPU_RASR_RSIZE_MASK, dracr & MPU_RACR_B,
|
||||||
|
dracr & MPU_RACR_C, dracr & MPU_RACR_S);
|
||||||
|
if (drsr & MPU_RASR_ENABLE)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_info("Total Use Region:%d, Remaining Available:%d\n", count,
|
||||||
|
CONFIG_ARM_MPU_NREGIONS - count);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_reset
|
* Name: mpu_reset
|
||||||
*
|
*
|
||||||
@@ -335,6 +561,12 @@ uint32_t mpu_subregion(uintptr_t base, size_t size, uint8_t l2size)
|
|||||||
* Conditional public interface that resets the MPU to disabled during
|
* Conditional public interface that resets the MPU to disabled during
|
||||||
* MPU initialization.
|
* MPU initialization.
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#if defined(CONFIG_ARM_MPU_RESET)
|
#if defined(CONFIG_ARM_MPU_RESET)
|
||||||
void mpu_reset()
|
void mpu_reset()
|
||||||
@@ -350,6 +582,12 @@ void mpu_reset()
|
|||||||
* Conditional public interface that resets the MPU to disabled immediately
|
* Conditional public interface that resets the MPU to disabled immediately
|
||||||
* after reset.
|
* after reset.
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#if defined(CONFIG_ARM_MPU_EARLY_RESET)
|
#if defined(CONFIG_ARM_MPU_EARLY_RESET)
|
||||||
void mpu_early_reset()
|
void mpu_early_reset()
|
||||||
|
|||||||
+250
-336
File diff suppressed because it is too large
Load Diff
+215
-30
@@ -26,6 +26,8 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
#include "mpu.h"
|
#include "mpu.h"
|
||||||
#include "arm_internal.h"
|
#include "arm_internal.h"
|
||||||
@@ -45,39 +47,26 @@
|
|||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* The next available region number */
|
/* The available region bitmap */
|
||||||
|
|
||||||
static uint8_t g_region;
|
static unsigned int g_mpu_region;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: mpu_allocregion
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Allocate the next region
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
* - Regions are never deallocated
|
|
||||||
* - Regions are only allocated early in initialization, so no special
|
|
||||||
* protection against re-entrancy is required;
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
unsigned int mpu_allocregion(void)
|
|
||||||
{
|
|
||||||
DEBUGASSERT(g_region < CONFIG_ARM_MPU_NREGIONS);
|
|
||||||
return (unsigned int)g_region++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_reset_internal
|
* Name: mpu_reset_internal
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Resets the MPU to disabled.
|
* Resets the MPU to disabled.
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if defined(CONFIG_ARM_MPU_RESET) || defined(CONFIG_ARM_MPU_EARLY_RESET)
|
#if defined(CONFIG_ARM_MPU_RESET) || defined(CONFIG_ARM_MPU_EARLY_RESET)
|
||||||
@@ -91,7 +80,7 @@ static void mpu_reset_internal()
|
|||||||
for (region = 0; region < regions; region++)
|
for (region = 0; region < regions; region++)
|
||||||
{
|
{
|
||||||
putreg32(region, MPU_RNR);
|
putreg32(region, MPU_RNR);
|
||||||
putreg32(0, MPU_RASR);
|
putreg32(0, MPU_RLAR);
|
||||||
putreg32(0, MPU_RBAR);
|
putreg32(0, MPU_RBAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,12 +95,75 @@ static void mpu_reset_internal()
|
|||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_allocregion
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Allocate the next region
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The index of the allocated region.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
unsigned int mpu_allocregion(void)
|
||||||
|
{
|
||||||
|
unsigned int i = ffs(~g_mpu_region) - 1;
|
||||||
|
|
||||||
|
/* There are not enough regions to apply */
|
||||||
|
|
||||||
|
DEBUGASSERT(i < CONFIG_ARM_MPU_NREGIONS);
|
||||||
|
g_mpu_region |= 1 << i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_freeregion
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Free target region.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* region - The index of the region to be freed.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_freeregion(unsigned int region)
|
||||||
|
{
|
||||||
|
DEBUGASSERT(region < CONFIG_ARM_MPU_NREGIONS);
|
||||||
|
|
||||||
|
/* Clear and disable the given MPU Region */
|
||||||
|
|
||||||
|
putreg32(region, MPU_RNR);
|
||||||
|
putreg32(0, MPU_RLAR);
|
||||||
|
putreg32(0, MPU_RBAR);
|
||||||
|
g_mpu_region &= ~(1 << region);
|
||||||
|
ARM_DSB();
|
||||||
|
ARM_ISB();
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_control
|
* Name: mpu_control
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Configure and enable (or disable) the MPU
|
* Configure and enable (or disable) the MPU
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* enable - Flag indicating whether to enable the MPU.
|
||||||
|
* hfnmiena - Flag indicating whether to enable the MPU during hard
|
||||||
|
* fult, NMI, and FAULTMAS.
|
||||||
|
* privdefena - Flag indicating whether to enable privileged access to
|
||||||
|
* the default memory map.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void mpu_control(bool enable, bool hfnmiena, bool privdefena)
|
void mpu_control(bool enable, bool hfnmiena, bool privdefena)
|
||||||
@@ -151,18 +203,32 @@ void mpu_control(bool enable, bool hfnmiena, bool privdefena)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_configure_region
|
* Name: mpu_modify_region
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Configure a region for privileged, strongly ordered memory
|
* Modify a region for privileged, strongly ordered memory
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* region - The index of the MPU region to modify.
|
||||||
|
* base - The base address of the region.
|
||||||
|
* size - The size of the region.
|
||||||
|
* flags1 - Additional flags for the region.
|
||||||
|
* flags2 - Additional flags for the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void mpu_configure_region(uintptr_t base, size_t size,
|
void mpu_modify_region(unsigned int region, uintptr_t base, size_t size,
|
||||||
uint32_t flags1, uint32_t flags2)
|
uint32_t flags1, uint32_t flags2)
|
||||||
{
|
{
|
||||||
unsigned int region = mpu_allocregion();
|
uintptr_t limit;
|
||||||
uintptr_t limit;
|
uintptr_t rbase;
|
||||||
|
|
||||||
|
/* Check that the region is valid */
|
||||||
|
|
||||||
|
DEBUGASSERT(g_mpu_region & (1 << region));
|
||||||
|
|
||||||
/* Ensure the base address alignment
|
/* Ensure the base address alignment
|
||||||
*
|
*
|
||||||
@@ -173,7 +239,7 @@ void mpu_configure_region(uintptr_t base, size_t size,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
limit = (base + size - 1) & MPU_RLAR_LIMIT_MASK;
|
limit = (base + size - 1) & MPU_RLAR_LIMIT_MASK;
|
||||||
base &= MPU_RBAR_BASE_MASK;
|
rbase = base & MPU_RBAR_BASE_MASK;
|
||||||
|
|
||||||
/* Select the region */
|
/* Select the region */
|
||||||
|
|
||||||
@@ -181,7 +247,7 @@ void mpu_configure_region(uintptr_t base, size_t size,
|
|||||||
|
|
||||||
/* Set the region base, limit and attribute */
|
/* Set the region base, limit and attribute */
|
||||||
|
|
||||||
putreg32(base | flags1, MPU_RBAR);
|
putreg32(rbase | flags1, MPU_RBAR);
|
||||||
putreg32(limit | flags2 | MPU_RLAR_ENABLE, MPU_RLAR);
|
putreg32(limit | flags2 | MPU_RLAR_ENABLE, MPU_RLAR);
|
||||||
|
|
||||||
/* Ensure MPU setting take effects */
|
/* Ensure MPU setting take effects */
|
||||||
@@ -190,6 +256,113 @@ void mpu_configure_region(uintptr_t base, size_t size,
|
|||||||
ARM_ISB();
|
ARM_ISB();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_configure_region
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Configure a region for privileged, strongly ordered memory
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* base - The base address of the region.
|
||||||
|
* size - The size of the region.
|
||||||
|
* flags1 - Additional flags for the region.
|
||||||
|
* flags2 - Additional flags for the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The region number allocated for the configured region.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
unsigned int mpu_configure_region(uintptr_t base, size_t size,
|
||||||
|
uint32_t flags1, uint32_t flags2)
|
||||||
|
{
|
||||||
|
unsigned int region = mpu_allocregion();
|
||||||
|
mpu_modify_region(region, base, size, flags1, flags2);
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_initialize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Configure a region for privileged, strongly ordered memory
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* table - MPU initialization table.
|
||||||
|
* hfnmiena - A boolean indicating whether the MPU should enable the
|
||||||
|
* HFNMIENA bit.
|
||||||
|
* privdefena - A boolean indicating whether the MPU should enable the
|
||||||
|
* PRIVDEFENA bit.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* NULL.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_initialize(const struct mpu_region_s *table, bool hfnmiena,
|
||||||
|
bool privdefena)
|
||||||
|
{
|
||||||
|
const struct mpu_region_s *conf;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
mpu_control(false, false, false);
|
||||||
|
for (index = 0; index < nitems(table); index++)
|
||||||
|
{
|
||||||
|
conf = &table[index];
|
||||||
|
mpu_configure_region(conf->base, conf->size, conf->flags1,
|
||||||
|
conf->flags2);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpu_control(true, hfnmiena, privdefena);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_dump_region
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Dump the region that has been used.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_dump_region(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int count = 0;
|
||||||
|
uint32_t rlar;
|
||||||
|
uint32_t rbar;
|
||||||
|
uint32_t ctrl;
|
||||||
|
|
||||||
|
/* Get free region */
|
||||||
|
|
||||||
|
ctrl = getreg32(MPU_CTRL);
|
||||||
|
_info("MPU-CTRL Enable:%" PRIu32 ", HFNMIENA:%"PRIu32","
|
||||||
|
"PRIVDEFENA:%" PRIu32 "\n", ctrl & MPU_CTRL_ENABLE,
|
||||||
|
ctrl & MPU_CTRL_HFNMIENA, ctrl & MPU_CTRL_PRIVDEFENA);
|
||||||
|
for (i = 0; i < CONFIG_ARM_MPU_NREGIONS; i++)
|
||||||
|
{
|
||||||
|
putreg32(i, MPU_RNR);
|
||||||
|
rlar = getreg32(MPU_RLAR);
|
||||||
|
rbar = getreg32(MPU_RBAR);
|
||||||
|
_info("MPU-%d, 0x%08X-0x%08X SH=%X AP=%X XN=%u\n",
|
||||||
|
i, rbar & MPU_RBAR_BASE_MASK, rlar & MPU_RLAR_LIMIT_MASK,
|
||||||
|
rbar & MPU_RBAR_SH_MASK, rbar & MPU_RBAR_AP_MASK,
|
||||||
|
rbar & MPU_RBAR_XN);
|
||||||
|
if (rlar & MPU_RLAR_ENABLE)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_info("Total Use Region:%d, Remaining Available:%d\n", count,
|
||||||
|
CONFIG_ARM_MPU_NREGIONS - count);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_reset
|
* Name: mpu_reset
|
||||||
*
|
*
|
||||||
@@ -197,6 +370,12 @@ void mpu_configure_region(uintptr_t base, size_t size,
|
|||||||
* Conditional public interface that resets the MPU to disabled during
|
* Conditional public interface that resets the MPU to disabled during
|
||||||
* MPU initialization.
|
* MPU initialization.
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#if defined(CONFIG_ARM_MPU_RESET)
|
#if defined(CONFIG_ARM_MPU_RESET)
|
||||||
void mpu_reset()
|
void mpu_reset()
|
||||||
@@ -212,6 +391,12 @@ void mpu_reset()
|
|||||||
* Conditional public interface that resets the MPU to disabled immediately
|
* Conditional public interface that resets the MPU to disabled immediately
|
||||||
* after reset.
|
* after reset.
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#if defined(CONFIG_ARM_MPU_EARLY_RESET)
|
#if defined(CONFIG_ARM_MPU_EARLY_RESET)
|
||||||
void mpu_early_reset()
|
void mpu_early_reset()
|
||||||
|
|||||||
+181
-87
@@ -168,6 +168,21 @@
|
|||||||
MPU_MAIR_OUTER_RA | MPU_MAIR_OUTER_WA | \
|
MPU_MAIR_OUTER_RA | MPU_MAIR_OUTER_WA | \
|
||||||
MPU_MAIR_INNER_NT | MPU_MAIR_INNER_WB | \
|
MPU_MAIR_INNER_NT | MPU_MAIR_INNER_WB | \
|
||||||
MPU_MAIR_INNER_RA | MPU_MAIR_INNER_WA)
|
MPU_MAIR_INNER_RA | MPU_MAIR_INNER_WA)
|
||||||
|
struct mpu_region_s
|
||||||
|
{
|
||||||
|
/* Region Base Address */
|
||||||
|
|
||||||
|
uintptr_t base;
|
||||||
|
|
||||||
|
/* Region Size */
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
/* Region Attributes */
|
||||||
|
|
||||||
|
uint32_t flags1;
|
||||||
|
uint32_t flags2;
|
||||||
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_reset
|
* Name: mpu_reset
|
||||||
@@ -215,26 +230,135 @@ extern "C"
|
|||||||
#define EXTERN extern
|
#define EXTERN extern
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_allocregion
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Allocate the next region
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The index of the allocated region.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
unsigned int mpu_allocregion(void);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_freeregion
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Free target region.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* region - The index of the region to be freed.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_freeregion(unsigned int region);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_control
|
* Name: mpu_control
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Configure and enable (or disable) the MPU
|
* Configure and enable (or disable) the MPU
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* enable - Flag indicating whether to enable the MPU.
|
||||||
|
* hfnmiena - Flag indicating whether to enable the MPU during hard
|
||||||
|
* fult, NMI, and FAULTMAS.
|
||||||
|
* privdefena - Flag indicating whether to enable privileged access to
|
||||||
|
* the default memory map.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void mpu_control(bool enable, bool hfnmiena, bool privdefena);
|
void mpu_control(bool enable, bool hfnmiena, bool privdefena);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_dump_region
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Dump the region that has been used.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_dump_region(void);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_modify_region
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Modify a region for privileged, strongly ordered memory
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* region - The index of the MPU region to modify.
|
||||||
|
* base - The base address of the region.
|
||||||
|
* size - The size of the region.
|
||||||
|
* flags1 - Additional flags for the region.
|
||||||
|
* flags2 - Additional flags for the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_modify_region(unsigned int region, uintptr_t base, size_t size,
|
||||||
|
uint32_t flags1, uint32_t flags2);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_configure_region
|
* Name: mpu_configure_region
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Configure a region for privileged, strongly ordered memory
|
* Configure a region for privileged, strongly ordered memory
|
||||||
*
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* base - The base address of the region.
|
||||||
|
* size - The size of the region.
|
||||||
|
* flags1 - Additional flags for the region.
|
||||||
|
* flags2 - Additional flags for the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The region number allocated for the configured region.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void mpu_configure_region(uintptr_t base, size_t size,
|
unsigned int mpu_configure_region(uintptr_t base, size_t size,
|
||||||
uint32_t flags1, uint32_t flags2);
|
uint32_t flags1, uint32_t flags2);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_initialize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Configure a region for privileged, strongly ordered memory
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* table - MPU initialization table.
|
||||||
|
* hfnmiena - A boolean indicating whether the MPU should enable the
|
||||||
|
* HFNMIENA bit.
|
||||||
|
* privdefena - A boolean indicating whether the MPU should enable the
|
||||||
|
* PRIVDEFENA bit.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* NULL.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_initialize(const struct mpu_region_s *table, bool hfnmiena,
|
||||||
|
bool privdefena);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Inline Functions
|
* Inline Functions
|
||||||
@@ -271,14 +395,11 @@ void mpu_configure_region(uintptr_t base, size_t size,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_priv_stronglyordered(base, size) \
|
#define mpu_priv_stronglyordered(base, size) \
|
||||||
do \
|
/* The configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* The configure the region */ \
|
MPU_RBAR_AP_RWNO, \
|
||||||
mpu_configure_region(base, size, \
|
MPU_RLAR_STRONGLY_ORDER | \
|
||||||
MPU_RBAR_AP_RWNO, \
|
MPU_RLAR_PXN)
|
||||||
MPU_RLAR_STRONGLY_ORDER | \
|
|
||||||
MPU_RLAR_PXN); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_user_flash
|
* Name: mpu_user_flash
|
||||||
@@ -289,13 +410,10 @@ void mpu_configure_region(uintptr_t base, size_t size,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_user_flash(base, size) \
|
#define mpu_user_flash(base, size) \
|
||||||
do \
|
/* The configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* The configure the region */ \
|
MPU_RBAR_AP_RORO, \
|
||||||
mpu_configure_region(base, size, \
|
MPU_RLAR_WRITE_BACK)
|
||||||
MPU_RBAR_AP_RORO, \
|
|
||||||
MPU_RLAR_WRITE_BACK); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_priv_flash
|
* Name: mpu_priv_flash
|
||||||
@@ -306,13 +424,10 @@ void mpu_configure_region(uintptr_t base, size_t size,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_priv_flash(base, size) \
|
#define mpu_priv_flash(base, size) \
|
||||||
do \
|
/* The configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* The configure the region */ \
|
MPU_RBAR_AP_RONO, \
|
||||||
mpu_configure_region(base, size, \
|
MPU_RLAR_WRITE_BACK)
|
||||||
MPU_RBAR_AP_RONO, \
|
|
||||||
MPU_RLAR_WRITE_BACK); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_user_intsram
|
* Name: mpu_user_intsram
|
||||||
@@ -323,15 +438,12 @@ void mpu_configure_region(uintptr_t base, size_t size,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_user_intsram(base, size) \
|
#define mpu_user_intsram(base, size) \
|
||||||
do \
|
/* The configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* The configure the region */ \
|
MPU_RBAR_XN | \
|
||||||
mpu_configure_region(base, size, \
|
MPU_RBAR_AP_RWRW, \
|
||||||
MPU_RBAR_XN | \
|
MPU_RLAR_NONCACHEABLE | \
|
||||||
MPU_RBAR_AP_RWRW, \
|
MPU_RLAR_PXN)
|
||||||
MPU_RLAR_NONCACHEABLE | \
|
|
||||||
MPU_RLAR_PXN); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_priv_intsram
|
* Name: mpu_priv_intsram
|
||||||
@@ -342,14 +454,11 @@ void mpu_configure_region(uintptr_t base, size_t size,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_priv_intsram(base, size) \
|
#define mpu_priv_intsram(base, size) \
|
||||||
do \
|
/* The configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* The configure the region */ \
|
MPU_RBAR_AP_RWNO, \
|
||||||
mpu_configure_region(base, size, \
|
MPU_RLAR_NONCACHEABLE | \
|
||||||
MPU_RBAR_AP_RWNO, \
|
MPU_RLAR_PXN)
|
||||||
MPU_RLAR_NONCACHEABLE | \
|
|
||||||
MPU_RLAR_PXN); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_priv_shmem
|
* Name: mpu_priv_shmem
|
||||||
@@ -359,16 +468,13 @@ void mpu_configure_region(uintptr_t base, size_t size,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_priv_shmem(base, size) \
|
#define mpu_priv_shmem(base, size) \
|
||||||
do \
|
/* The configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* The configure the region */ \
|
MPU_RBAR_AP_RWNO, \
|
||||||
mpu_configure_region(base, size, \
|
MPU_RLAR_NONCACHEABLE | \
|
||||||
MPU_RBAR_AP_RWNO, \
|
MPU_RBAR_SH_INNER | \
|
||||||
MPU_RLAR_NONCACHEABLE | \
|
MPU_RLAR_PXN)
|
||||||
MPU_RBAR_SH_INNER | \
|
|
||||||
MPU_RLAR_PXN); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_user_extsram
|
* Name: mpu_user_extsram
|
||||||
@@ -379,16 +485,13 @@ void mpu_configure_region(uintptr_t base, size_t size,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_user_extsram(base, size) \
|
#define mpu_user_extsram(base, size) \
|
||||||
do \
|
/* The configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* The configure the region */ \
|
MPU_RBAR_XN | \
|
||||||
mpu_configure_region(base, size, \
|
MPU_RBAR_AP_RWRW | \
|
||||||
MPU_RBAR_XN | \
|
MPU_RBAR_SH_OUTER, \
|
||||||
MPU_RBAR_AP_RWRW | \
|
MPU_RLAR_WRITE_BACK | \
|
||||||
MPU_RBAR_SH_OUTER, \
|
MPU_RLAR_PXN)
|
||||||
MPU_RLAR_WRITE_BACK | \
|
|
||||||
MPU_RLAR_PXN); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_priv_extsram
|
* Name: mpu_priv_extsram
|
||||||
@@ -399,15 +502,12 @@ void mpu_configure_region(uintptr_t base, size_t size,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_priv_extsram(base, size) \
|
#define mpu_priv_extsram(base, size) \
|
||||||
do \
|
/* The configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* The configure the region */ \
|
MPU_RBAR_AP_RWNO | \
|
||||||
mpu_configure_region(base, size, \
|
MPU_RBAR_SH_OUTER, \
|
||||||
MPU_RBAR_AP_RWNO | \
|
MPU_RLAR_WRITE_BACK | \
|
||||||
MPU_RBAR_SH_OUTER, \
|
MPU_RLAR_PXN)
|
||||||
MPU_RLAR_WRITE_BACK | \
|
|
||||||
MPU_RLAR_PXN); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_peripheral
|
* Name: mpu_peripheral
|
||||||
@@ -418,14 +518,11 @@ void mpu_configure_region(uintptr_t base, size_t size,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_peripheral(base, size) \
|
#define mpu_peripheral(base, size) \
|
||||||
do \
|
/* Then configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* Then configure the region */ \
|
MPU_RBAR_AP_RWNO, \
|
||||||
mpu_configure_region(base, size, \
|
MPU_RLAR_DEVICE | \
|
||||||
MPU_RBAR_AP_RWNO, \
|
MPU_RLAR_PXN)
|
||||||
MPU_RLAR_DEVICE | \
|
|
||||||
MPU_RLAR_PXN); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_user_peripheral
|
* Name: mpu_user_peripheral
|
||||||
@@ -436,15 +533,12 @@ void mpu_configure_region(uintptr_t base, size_t size,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define mpu_user_peripheral(base, size) \
|
#define mpu_user_peripheral(base, size) \
|
||||||
do \
|
/* Then configure the region */ \
|
||||||
{ \
|
mpu_configure_region(base, size, \
|
||||||
/* Then configure the region */ \
|
MPU_RBAR_XN | \
|
||||||
mpu_configure_region(base, size, \
|
MPU_RBAR_AP_RWRW, \
|
||||||
MPU_RBAR_XN | \
|
MPU_RLAR_DEVICE | \
|
||||||
MPU_RBAR_AP_RWRW, \
|
MPU_RLAR_PXN)
|
||||||
MPU_RLAR_DEVICE | \
|
|
||||||
MPU_RLAR_PXN); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/***************************************************************************
|
/****************************************************************************
|
||||||
* arch/arm64/src/common/arm64_mpu.c
|
* arch/arm64/src/common/arm64_mpu.c
|
||||||
*
|
*
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
@@ -16,11 +16,11 @@
|
|||||||
* License for the specific language governing permissions and limitations
|
* License for the specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/***************************************************************************
|
/****************************************************************************
|
||||||
* Included Files
|
* Included Files
|
||||||
***************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -36,9 +36,9 @@
|
|||||||
#include "arm64_fatal.h"
|
#include "arm64_fatal.h"
|
||||||
#include "arm64_mpu.h"
|
#include "arm64_mpu.h"
|
||||||
|
|
||||||
/***************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
***************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define __MPU_ASSERT(__cond, fmt, ...) \
|
#define __MPU_ASSERT(__cond, fmt, ...) \
|
||||||
do \
|
do \
|
||||||
@@ -70,65 +70,50 @@
|
|||||||
* regions.
|
* regions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static uint8_t static_regions_num;
|
static unsigned int g_mpu_region;
|
||||||
|
|
||||||
/***************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
***************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Get the number of supported MPU regions. */
|
/****************************************************************************
|
||||||
|
* Name: get_num_regions
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Get the number of supported MPU regions.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Numbers of the region.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
static inline uint8_t get_num_regions(void)
|
static inline unsigned int get_num_regions(void)
|
||||||
{
|
{
|
||||||
uint64_t type;
|
uint64_t type;
|
||||||
|
|
||||||
type = read_sysreg(mpuir_el1);
|
type = read_sysreg(mpuir_el1);
|
||||||
type = type & MPU_IR_REGION_MSK;
|
type = type & MPU_IR_REGION_MSK;
|
||||||
|
|
||||||
return (uint8_t)type;
|
return (unsigned int)type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ARM Core MPU Driver API Implementation for ARM MPU */
|
/****************************************************************************
|
||||||
|
* Name: mpu_init
|
||||||
/* Enable the MPU */
|
|
||||||
|
|
||||||
void arm64_core_mpu_enable(void)
|
|
||||||
{
|
|
||||||
uint64_t val;
|
|
||||||
|
|
||||||
val = read_sysreg(sctlr_el1);
|
|
||||||
val |= (SCTLR_M_BIT
|
|
||||||
#ifndef CONFIG_ARM64_DCACHE_DISABLE
|
|
||||||
| SCTLR_C_BIT
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
write_sysreg(val, sctlr_el1);
|
|
||||||
ARM64_DSB();
|
|
||||||
ARM64_ISB();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Disable the MPU */
|
|
||||||
|
|
||||||
void arm64_core_mpu_disable(void)
|
|
||||||
{
|
|
||||||
uint64_t val;
|
|
||||||
|
|
||||||
/* Force any outstanding transfers to complete before disabling MPU */
|
|
||||||
|
|
||||||
ARM64_DMB();
|
|
||||||
|
|
||||||
val = read_sysreg(sctlr_el1);
|
|
||||||
val &= ~(SCTLR_M_BIT | SCTLR_C_BIT);
|
|
||||||
write_sysreg(val, sctlr_el1);
|
|
||||||
ARM64_DSB();
|
|
||||||
ARM64_ISB();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ARM MPU Driver Initial Setup
|
|
||||||
*
|
*
|
||||||
* Configure the cache-ability attributes for all the
|
* Description:
|
||||||
* different types of memory regions.
|
* Configure the cache-ability attributes for all the different types
|
||||||
*/
|
* of memory regions.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
static void mpu_init(void)
|
static void mpu_init(void)
|
||||||
{
|
{
|
||||||
@@ -145,44 +130,257 @@ static void mpu_init(void)
|
|||||||
ARM64_ISB();
|
ARM64_ISB();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mpu_set_region(uint32_t rnr, uint64_t rbar,
|
/****************************************************************************
|
||||||
uint64_t rlar)
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_allocregion
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Allocate the next region
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The index of the allocated region.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
unsigned int mpu_allocregion(void)
|
||||||
{
|
{
|
||||||
write_sysreg(rnr, prselr_el1);
|
unsigned int num_regions = get_num_regions();
|
||||||
|
unsigned int i = ffs(~g_mpu_region) - 1;
|
||||||
|
|
||||||
|
/* There are not enough regions to apply */
|
||||||
|
|
||||||
|
DEBUGASSERT(i < num_regions);
|
||||||
|
g_mpu_region |= 1 << i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_freeregion
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Free target region.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* region - The index of the region to be freed.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_freeregion(unsigned int region)
|
||||||
|
{
|
||||||
|
unsigned int num_regions = get_num_regions();
|
||||||
|
|
||||||
|
/* Check region vaild */
|
||||||
|
|
||||||
|
DEBUGASSERT(region < num_regions);
|
||||||
|
|
||||||
|
write_sysreg(region, prselr_el1);
|
||||||
ARM64_DSB();
|
ARM64_DSB();
|
||||||
|
|
||||||
|
/* Set the region base, limit and attribute */
|
||||||
|
|
||||||
|
write_sysreg(0, prbar_el1);
|
||||||
|
write_sysreg(0, prlar_el1);
|
||||||
|
g_mpu_region &= ~(1 << region);
|
||||||
|
ARM64_DSB();
|
||||||
|
ARM64_ISB();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arm64_mpu_enable
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Enable the MPU
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void arm64_mpu_enable(void)
|
||||||
|
{
|
||||||
|
uint64_t val;
|
||||||
|
|
||||||
|
val = read_sysreg(sctlr_el1);
|
||||||
|
val |= (SCTLR_M_BIT
|
||||||
|
#ifndef CONFIG_ARM64_DCACHE_DISABLE
|
||||||
|
| SCTLR_C_BIT
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
write_sysreg(val, sctlr_el1);
|
||||||
|
ARM64_DSB();
|
||||||
|
ARM64_ISB();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arm64_mpu_disable
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Disable the MPU
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void arm64_mpu_disable(void)
|
||||||
|
{
|
||||||
|
uint64_t val;
|
||||||
|
|
||||||
|
/* Force any outstanding transfers to complete before disabling MPU */
|
||||||
|
|
||||||
|
ARM64_DMB();
|
||||||
|
|
||||||
|
val = read_sysreg(sctlr_el1);
|
||||||
|
val &= ~(SCTLR_M_BIT | SCTLR_C_BIT);
|
||||||
|
write_sysreg(val, sctlr_el1);
|
||||||
|
ARM64_DSB();
|
||||||
|
ARM64_ISB();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_modify_region
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Modify a region for privileged, strongly ordered memory
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* region - The index of the MPU region to modify.
|
||||||
|
* table - Pointer to a struct containing the configuration
|
||||||
|
* parameters for the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_modify_region(unsigned int region,
|
||||||
|
const struct arm64_mpu_region *table)
|
||||||
|
{
|
||||||
|
uint64_t rbar = table->base & MPU_RBAR_BASE_MSK;
|
||||||
|
uint64_t rlar = (table->limit - 1) & MPU_RLAR_LIMIT_MSK;
|
||||||
|
|
||||||
|
/* Check that the region is valid */
|
||||||
|
|
||||||
|
DEBUGASSERT(g_mpu_region & (1 << region));
|
||||||
|
|
||||||
|
rbar |= table->attr.rbar &
|
||||||
|
(MPU_RBAR_XN_MSK | MPU_RBAR_AP_MSK | MPU_RBAR_SH_MSK);
|
||||||
|
rlar |=
|
||||||
|
(table->attr.mair_idx <<
|
||||||
|
MPU_RLAR_ATTRINDX_POS) & MPU_RLAR_ATTRINDX_MSK;
|
||||||
|
rlar |= MPU_RLAR_EN_MSK;
|
||||||
|
|
||||||
|
/* Select the region */
|
||||||
|
|
||||||
|
write_sysreg(region, prselr_el1);
|
||||||
|
ARM64_DSB();
|
||||||
|
|
||||||
|
/* Set the region base, limit and attribute */
|
||||||
|
|
||||||
write_sysreg(rbar, prbar_el1);
|
write_sysreg(rbar, prbar_el1);
|
||||||
write_sysreg(rlar, prlar_el1);
|
write_sysreg(rlar, prlar_el1);
|
||||||
ARM64_DSB();
|
ARM64_DSB();
|
||||||
ARM64_ISB();
|
ARM64_ISB();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This internal functions performs MPU region initialization. */
|
/****************************************************************************
|
||||||
|
* Name: mpu_configure_region
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Configure a region for privileged, strongly ordered memory
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* table - Pointer to a struct containing the configuration
|
||||||
|
* parameters for the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The region number allocated for the configured region.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
static void region_init(const uint32_t index,
|
unsigned int mpu_configure_region(const struct arm64_mpu_region *
|
||||||
const struct arm64_mpu_region *region_conf)
|
table)
|
||||||
{
|
{
|
||||||
uint64_t rbar = region_conf->base & MPU_RBAR_BASE_MSK;
|
unsigned int region = mpu_allocregion();
|
||||||
uint64_t rlar = (region_conf->limit - 1) & MPU_RLAR_LIMIT_MSK;
|
mpu_modify_region(region, table);
|
||||||
|
return region;
|
||||||
rbar |= region_conf->attr.rbar &
|
|
||||||
(MPU_RBAR_XN_MSK | MPU_RBAR_AP_MSK | MPU_RBAR_SH_MSK);
|
|
||||||
rlar |=
|
|
||||||
(region_conf->attr.mair_idx <<
|
|
||||||
MPU_RLAR_ATTRINDX_POS) & MPU_RLAR_ATTRINDX_MSK;
|
|
||||||
rlar |= MPU_RLAR_EN_MSK;
|
|
||||||
|
|
||||||
mpu_set_region(index, rbar, rlar);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Name: mpu_dump_region
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/* @brief MPU default configuration
|
|
||||||
*
|
*
|
||||||
* This function here provides the default configuration mechanism
|
* Description:
|
||||||
* for the Memory Protection Unit (MPU).
|
* Dump the region that has been used.
|
||||||
*/
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_dump_region(void)
|
||||||
|
{
|
||||||
|
uint64_t sctlr_el1;
|
||||||
|
uint64_t prlar;
|
||||||
|
uint64_t prbar;
|
||||||
|
unsigned int num_regions;
|
||||||
|
int i;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
num_regions = get_num_regions();
|
||||||
|
sctlr_el1 = read_sysreg(sctlr_el1);
|
||||||
|
_info("MPU-SCTLR_EL1 Enable:%" PRIu64 ", Cacheable: %" PRIu64 "\n",
|
||||||
|
sctlr_el1 & SCTLR_M_BIT, sctlr_el1 & SCTLR_C_BIT);
|
||||||
|
for (i = 0; i < num_regions; i++)
|
||||||
|
{
|
||||||
|
write_sysreg(i, prselr_el1);
|
||||||
|
prlar = read_sysreg(prlar_el1);
|
||||||
|
prbar = read_sysreg(prbar_el1);
|
||||||
|
_info("MPU-%d, 0x%08X-0x%08X SH=%X AP=%X XN=%X\n", i,
|
||||||
|
prbar & MPU_RBAR_BASE_MSK, prlar & MPU_RLAR_LIMIT_MSK,
|
||||||
|
prbar & MPU_RBAR_SH_MSK, prbar & MPU_RBAR_AP_MSK,
|
||||||
|
prbar & MPU_RBAR_XN_MSK);
|
||||||
|
if (prlar & MPU_RLAR_EN_MSK)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_info("Total Use Region:%d, Remaining Available:%d\n", count,
|
||||||
|
num_regions - count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arm64_mpu_init
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function here provides the default configuration mechanism
|
||||||
|
* for the Memory Protection Unit (MPU).
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* is_primary_core: A boolean indicating whether the current core is the
|
||||||
|
* primary core.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
void arm64_mpu_init(bool is_primary_core)
|
void arm64_mpu_init(bool is_primary_core)
|
||||||
{
|
{
|
||||||
@@ -206,21 +404,7 @@ void arm64_mpu_init(bool is_primary_core)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_mpu_config.num_regions > get_num_regions())
|
arm64_mpu_disable();
|
||||||
{
|
|
||||||
/* Attempt to configure more MPU regions than
|
|
||||||
* what is supported by hardware. As this operation
|
|
||||||
* is executed during system (pre-kernel) initialization,
|
|
||||||
* we want to ensure we can detect an attempt to
|
|
||||||
* perform invalid configuration.
|
|
||||||
*/
|
|
||||||
|
|
||||||
__MPU_ASSERT(0, "Request to configure: %u regions (supported: %u)\n",
|
|
||||||
g_mpu_config.num_regions, get_num_regions());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
arm64_core_mpu_disable();
|
|
||||||
|
|
||||||
/* Architecture-specific configuration */
|
/* Architecture-specific configuration */
|
||||||
|
|
||||||
@@ -230,12 +414,8 @@ void arm64_mpu_init(bool is_primary_core)
|
|||||||
|
|
||||||
for (r_index = 0U; r_index < g_mpu_config.num_regions; r_index++)
|
for (r_index = 0U; r_index < g_mpu_config.num_regions; r_index++)
|
||||||
{
|
{
|
||||||
region_init(r_index, &g_mpu_config.mpu_regions[r_index]);
|
mpu_configure_region(&g_mpu_config.mpu_regions[r_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update the number of programmed MPU regions. */
|
arm64_mpu_enable();
|
||||||
|
|
||||||
static_regions_num = g_mpu_config.num_regions;
|
|
||||||
|
|
||||||
arm64_core_mpu_enable();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -304,6 +304,131 @@ extern const struct arm64_mpu_config g_mpu_config;
|
|||||||
* Public Function Prototypes
|
* Public Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_allocregion
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Allocate the next region
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The index of the allocated region.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
unsigned int mpu_allocregion(void);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_freeregion
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Free target region.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* region - The index of the region to be freed.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_freeregion(unsigned int region);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arm64_mpu_enable
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Enable the MPU
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void arm64_mpu_enable(void);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arm64_mpu_disable
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Disable the MPU
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void arm64_mpu_disable(void);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_dump_region
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Dump the region that has been used.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_dump_region(void);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_modify_region
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Modify a region for privileged, strongly ordered memory
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* region - The index of the MPU region to modify.
|
||||||
|
* table - Pointer to a struct containing the configuration
|
||||||
|
* parameters for the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void mpu_modify_region(unsigned int region,
|
||||||
|
const struct arm64_mpu_region *table);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_configure_region
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Configure a region for privileged, strongly ordered memory
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* table - Pointer to a struct containing the configuration
|
||||||
|
* parameters for the region.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The region number allocated for the configured region.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
unsigned int mpu_configure_region(const struct arm64_mpu_region *
|
||||||
|
table);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arm64_mpu_init
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function here provides the default configuration mechanism
|
||||||
|
* for the Memory Protection Unit (MPU).
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
void arm64_mpu_init(bool is_primary_core);
|
void arm64_mpu_init(bool is_primary_core);
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
|
|||||||
Reference in New Issue
Block a user