arch: arm: aarch32: add ARMv8-R MPU support

ARMv8-R aarch32 processor has support for
ARM PMSAv8-32. To add support for ARMv8-R we reuse the
ARMv8-M effort and change access to the different registers
such as rbar, rlar, mair, prselr.

Signed-off-by: Julien Massot <julien.massot@iot.bzh>
Signed-off-by: Manuel Arguelles <manuel.arguelles@nxp.com>
This commit is contained in:
Julien Massot 2022-03-14 11:11:52 +01:00 committed by Carles Cufí
parent ff54de3e16
commit ddcc5fb28d
8 changed files with 383 additions and 69 deletions

View file

@ -12,7 +12,8 @@ config ARM_MPU
select THREAD_STACK_INFO
select ARCH_HAS_EXECUTABLE_PAGE_BIT
select MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT if !(CPU_HAS_NXP_MPU || ARMV8_M_BASELINE || ARMV8_M_MAINLINE)
select MPU_REQUIRES_NON_OVERLAPPING_REGIONS if CPU_HAS_ARM_MPU && (ARMV8_M_BASELINE || ARMV8_M_MAINLINE)
select MPU_REQUIRES_NON_OVERLAPPING_REGIONS if CPU_HAS_ARM_MPU && (ARMV8_M_BASELINE || ARMV8_M_MAINLINE || AARCH32_ARMV8_R)
select MPU_GAP_FILLING if AARCH32_ARMV8_R
help
MCU implements Memory Protection Unit.
@ -46,6 +47,7 @@ config ARM_MPU
config ARM_MPU_REGION_MIN_ALIGN_AND_SIZE
int
default 256 if ARM_MPU && ARMV6_M_ARMV8_M_BASELINE && !ARMV8_M_BASELINE
default 64 if ARM_MPU && AARCH32_ARMV8_R
default 32 if ARM_MPU
default 4
help

View file

@ -155,6 +155,8 @@ void z_arm_configure_static_mpu_regions(void)
#endif /* CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS */
}
extern void arm_core_mpu_enable(void);
extern void arm_core_mpu_disable(void);
/**
* @brief Use the HW-specific MPU driver to program
* the dynamic MPU regions.
@ -303,8 +305,14 @@ void z_arm_configure_dynamic_mpu_regions(struct k_thread *thread)
#endif /* CONFIG_MPU_STACK_GUARD */
/* Configure the dynamic MPU regions */
#ifdef CONFIG_AARCH32_ARMV8_R
arm_core_mpu_disable();
#endif
arm_core_mpu_configure_dynamic_mpu_regions(dynamic_regions,
region_num);
#ifdef CONFIG_AARCH32_ARMV8_R
arm_core_mpu_enable();
#endif
}
#if defined(CONFIG_USERSPACE)

View file

@ -43,11 +43,12 @@ static uint8_t static_regions_num;
defined(CONFIG_CPU_CORTEX_M3) || \
defined(CONFIG_CPU_CORTEX_M4) || \
defined(CONFIG_CPU_CORTEX_M7) || \
defined(CONFIG_CPU_AARCH32_CORTEX_R)
defined(CONFIG_ARMV7_R)
#include "arm_mpu_v7_internal.h"
#elif defined(CONFIG_CPU_CORTEX_M23) || \
defined(CONFIG_CPU_CORTEX_M33) || \
defined(CONFIG_CPU_CORTEX_M55)
defined(CONFIG_CPU_CORTEX_M55) || \
defined(CONFIG_AARCH32_ARMV8_R)
#include "arm_mpu_v8_internal.h"
#else
#error "Unsupported ARM CPU"
@ -84,7 +85,7 @@ static int mpu_configure_region(const uint8_t index,
/* Populate internal ARM MPU region configuration structure. */
region_conf.base = new_region->start;
#if defined(CONFIG_CPU_AARCH32_CORTEX_R)
#if defined(CONFIG_ARMV7_R)
region_conf.size = size_to_mpu_rasr_size(new_region->size);
#endif
get_region_attr_from_mpu_partition_info(&region_conf.attr,

View file

@ -28,7 +28,109 @@ struct dynamic_region_info {
* regions may be configured.
*/
static struct dynamic_region_info dyn_reg_info[MPU_DYNAMIC_REGION_AREAS_NUM];
#if defined(CONFIG_CPU_CORTEX_M23) || defined(CONFIG_CPU_CORTEX_M33) || \
defined(CONFIG_CPU_CORTEX_M55)
static inline void mpu_set_mair0(uint32_t mair0)
{
MPU->MAIR0 = mair0;
}
static inline void mpu_set_rnr(uint32_t rnr)
{
MPU->RNR = rnr;
}
static inline void mpu_set_rbar(uint32_t rbar)
{
MPU->RBAR = rbar;
}
static inline uint32_t mpu_get_rbar(void)
{
return MPU->RBAR;
}
static inline void mpu_set_rlar(uint32_t rlar)
{
MPU->RLAR = rlar;
}
static inline uint32_t mpu_get_rlar(void)
{
return MPU->RLAR;
}
static inline uint8_t mpu_get_num_regions(void)
{
uint32_t type = MPU->TYPE;
type = (type & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
return (uint8_t)type;
}
static inline void mpu_clear_region(uint32_t rnr)
{
ARM_MPU_ClrRegion(rnr);
}
#elif defined(CONFIG_AARCH32_ARMV8_R)
static inline void mpu_set_mair0(uint32_t mair0)
{
write_mair0(mair0);
__DSB();
__ISB();
}
static inline void mpu_set_rnr(uint32_t rnr)
{
write_prselr(rnr);
__DSB();
}
static inline void mpu_set_rbar(uint32_t rbar)
{
write_prbar(rbar);
__DSB();
__ISB();
}
static inline uint32_t mpu_get_rbar(void)
{
return read_prbar();
}
static inline void mpu_set_rlar(uint32_t rlar)
{
write_prlar(rlar);
__DSB();
__ISB();
}
static inline uint32_t mpu_get_rlar(void)
{
return read_prlar();
}
static inline uint8_t mpu_get_num_regions(void)
{
uint32_t type = read_mpuir();
type = (type >> MPU_IR_REGION_Pos) & MPU_IR_REGION_Msk;
return (uint8_t)type;
}
static inline void mpu_clear_region(uint32_t rnr)
{
mpu_set_rnr(rnr);
mpu_set_rbar(0);
mpu_set_rlar(0);
}
#else
#error "Unsupported ARM CPU"
#endif
/* Global MPU configuration at system initialization. */
static void mpu_init(void)
@ -36,20 +138,14 @@ static void mpu_init(void)
/* Configure the cache-ability attributes for all the
* different types of memory regions.
*/
mpu_set_mair0(MPU_MAIR_ATTRS);
}
/* Flash region(s): Attribute-0
* SRAM region(s): Attribute-1
* SRAM no cache-able regions(s): Attribute-2
*/
MPU->MAIR0 =
((MPU_MAIR_ATTR_FLASH << MPU_MAIR0_Attr0_Pos) &
MPU_MAIR0_Attr0_Msk)
|
((MPU_MAIR_ATTR_SRAM << MPU_MAIR0_Attr1_Pos) &
MPU_MAIR0_Attr1_Msk)
|
((MPU_MAIR_ATTR_SRAM_NOCACHE << MPU_MAIR0_Attr2_Pos) &
MPU_MAIR0_Attr2_Msk);
static void mpu_set_region(uint32_t rnr, uint32_t rbar, uint32_t rlar)
{
mpu_set_rnr(rnr);
mpu_set_rbar(rbar);
mpu_set_rlar(rlar);
}
/* This internal function performs MPU region initialization.
@ -60,7 +156,7 @@ static void mpu_init(void)
static void region_init(const uint32_t index,
const struct arm_mpu_region *region_conf)
{
ARM_MPU_SetRegion(
mpu_set_region(
/* RNR */
index,
/* RBAR */
@ -116,6 +212,21 @@ static int mpu_partition_is_valid(const struct z_arm_mpu_partition *part)
* needs to be enabled.
*
*/
#if defined(CONFIG_AARCH32_ARMV8_R)
static inline int get_region_index(uint32_t start, uint32_t size)
{
uint32_t limit = (start + size - 1) & MPU_RLAR_LIMIT_Msk;
for (uint8_t idx = 0; idx < mpu_get_num_regions(); idx++) {
mpu_set_rnr(idx);
if (start >= (mpu_get_rbar() & MPU_RBAR_BASE_Msk) &&
limit <= (mpu_get_rlar() & MPU_RLAR_LIMIT_Msk)) {
return idx;
}
}
return -EINVAL;
}
#else
static inline int get_region_index(uint32_t start, uint32_t size)
{
uint32_t region_start_addr = arm_cmse_mpu_region_get(start);
@ -129,48 +240,49 @@ static inline int get_region_index(uint32_t start, uint32_t size)
}
return -EINVAL;
}
#endif
static inline uint32_t mpu_region_get_base(const uint32_t index)
{
MPU->RNR = index;
return MPU->RBAR & MPU_RBAR_BASE_Msk;
mpu_set_rnr(index);
return mpu_get_rbar() & MPU_RBAR_BASE_Msk;
}
static inline void mpu_region_set_base(const uint32_t index, const uint32_t base)
{
MPU->RNR = index;
MPU->RBAR = (MPU->RBAR & (~MPU_RBAR_BASE_Msk))
| (base & MPU_RBAR_BASE_Msk);
mpu_set_rnr(index);
mpu_set_rbar((mpu_get_rbar() & (~MPU_RBAR_BASE_Msk))
| (base & MPU_RBAR_BASE_Msk));
}
static inline uint32_t mpu_region_get_last_addr(const uint32_t index)
{
MPU->RNR = index;
return (MPU->RLAR & MPU_RLAR_LIMIT_Msk) | (~MPU_RLAR_LIMIT_Msk);
mpu_set_rnr(index);
return (mpu_get_rlar() & MPU_RLAR_LIMIT_Msk) | (~MPU_RLAR_LIMIT_Msk);
}
static inline void mpu_region_set_limit(const uint32_t index, const uint32_t limit)
{
MPU->RNR = index;
MPU->RLAR = (MPU->RLAR & (~MPU_RLAR_LIMIT_Msk))
| (limit & MPU_RLAR_LIMIT_Msk);
mpu_set_rnr(index);
mpu_set_rlar((mpu_get_rlar() & (~MPU_RLAR_LIMIT_Msk))
| (limit & MPU_RLAR_LIMIT_Msk));
}
static inline void mpu_region_get_access_attr(const uint32_t index,
arm_mpu_region_attr_t *attr)
{
MPU->RNR = index;
mpu_set_rnr(index);
attr->rbar = MPU->RBAR &
attr->rbar = mpu_get_rbar() &
(MPU_RBAR_XN_Msk | MPU_RBAR_AP_Msk | MPU_RBAR_SH_Msk);
attr->mair_idx = (MPU->RLAR & MPU_RLAR_AttrIndx_Msk) >>
attr->mair_idx = (mpu_get_rlar() & MPU_RLAR_AttrIndx_Msk) >>
MPU_RLAR_AttrIndx_Pos;
}
static inline void mpu_region_get_conf(const uint32_t index,
struct arm_mpu_region *region_conf)
{
MPU->RNR = index;
mpu_set_rnr(index);
/* Region attribution:
* - Cache-ability
@ -180,10 +292,10 @@ static inline void mpu_region_get_conf(const uint32_t index,
mpu_region_get_access_attr(index, &region_conf->attr);
/* Region base address */
region_conf->base = (MPU->RBAR & MPU_RBAR_BASE_Msk);
region_conf->base = mpu_get_rbar() & MPU_RBAR_BASE_Msk;
/* Region limit address */
region_conf->attr.r_limit = MPU->RLAR & MPU_RLAR_LIMIT_Msk;
region_conf->attr.r_limit = mpu_get_rlar() & MPU_RLAR_LIMIT_Msk;
}
/**
@ -242,11 +354,76 @@ static inline uint32_t mpu_region_get_size(uint32_t index)
*/
static inline int is_enabled_region(uint32_t index)
{
MPU->RNR = index;
mpu_set_rnr(index);
return (MPU->RLAR & MPU_RLAR_EN_Msk) ? 1 : 0;
return (mpu_get_rlar() & MPU_RLAR_EN_Msk) ? 1 : 0;
}
#if defined(CONFIG_AARCH32_ARMV8_R)
/**
* This internal function checks if the given buffer is in the region.
*
* Note:
* The caller must provide a valid region number.
*/
static inline int is_in_region(uint32_t rnr, uint32_t start, uint32_t size)
{
uint32_t rbar;
uint32_t rlar;
rbar = mpu_region_get_base(rnr);
rlar = mpu_region_get_last_addr(rnr);
if ((start >= rbar) && ((start + size) <= rlar)) {
return 1;
}
return 0;
}
static inline int is_user_accessible_region(uint32_t rnr, int write)
{
uint32_t r_ap;
mpu_set_rnr(rnr);
r_ap = (mpu_get_rbar() & MPU_RBAR_AP_Msk) >> MPU_RBAR_AP_Pos;
if (write != 0) {
return r_ap == P_RW_U_RW;
}
return ((r_ap == P_RW_U_RW) || (r_ap == P_RO_U_RO));
}
/**
* This internal function validates whether a given memory buffer
* is user accessible or not.
*/
static inline int mpu_buffer_validate(void *addr, size_t size, int write)
{
int32_t rnr;
int rc = -EPERM;
int key = arch_irq_lock();
/* Iterate all mpu regions in reversed order */
for (rnr = 0; rnr < mpu_get_num_regions(); rnr++) {
if (!is_enabled_region(rnr) ||
!is_in_region(rnr, (uint32_t)addr, size)) {
continue;
}
if (is_user_accessible_region(rnr, write)) {
rc = 0;
}
}
arch_irq_unlock(key);
return rc;
}
#else
/**
* This internal function validates whether a given memory buffer
* is user accessible or not.
@ -308,7 +485,7 @@ static inline int mpu_buffer_validate(void *addr, size_t size, int write)
#endif /* CONFIG_CPU_HAS_TEE */
return -EPERM;
}
#endif /* CONFIG_AARCH32_ARMV8_R */
#endif /* CONFIG_USERSPACE */
@ -539,11 +716,7 @@ static inline uint8_t get_num_regions(void)
/* Retrieve the number of regions from DTS configuration. */
return NUM_MPU_REGIONS;
#else
uint32_t type = MPU->TYPE;
type = (type & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
return (uint8_t)type;
return mpu_get_num_regions();
#endif /* NUM_MPU_REGIONS */
}
@ -562,7 +735,7 @@ static int mpu_configure_dynamic_mpu_regions(const struct z_arm_mpu_partition
/* Disable all MPU regions except for the static ones. */
for (int i = mpu_reg_index; i < get_num_regions(); i++) {
ARM_MPU_ClrRegion(i);
mpu_clear_region(i);
}
#if defined(CONFIG_MPU_GAP_FILLING)
@ -587,7 +760,7 @@ static int mpu_configure_dynamic_mpu_regions(const struct z_arm_mpu_partition
* may be programmed.
*/
for (int i = 0; i < MPU_DYNAMIC_REGION_AREAS_NUM; i++) {
ARM_MPU_ClrRegion(dyn_reg_info[i].index);
mpu_clear_region(dyn_reg_info[i].index);
}
/* The dynamic regions are now programmed on top of

View file

@ -14,7 +14,7 @@
#include <zephyr/arch/arm/aarch32/exc.h>
#if defined(CONFIG_ARMV7_R)
#if defined(CONFIG_CPU_AARCH32_CORTEX_R)
#include <zephyr/arch/cpu.h>
#endif
@ -63,7 +63,7 @@ SECTION_FUNC(TEXT,z_arm_userspace_enter)
ldr r0, [r0, #_thread_offset_to_priv_stack_start] /* priv stack ptr */
ldr ip, =CONFIG_PRIVILEGED_STACK_SIZE
add r0, r0, ip
#elif defined(CONFIG_ARMV7_R)
#elif defined(CONFIG_CPU_AARCH32_CORTEX_R)
ldr r0, [r0, #_thread_offset_to_priv_stack_start] /* priv stack ptr */
ldr ip, =CONFIG_PRIVILEGED_STACK_SIZE
add r0, r0, ip
@ -79,7 +79,7 @@ SECTION_FUNC(TEXT,z_arm_userspace_enter)
*/
mov ip, sp
#if defined(CONFIG_ARMV7_R)
#if defined(CONFIG_CPU_AARCH32_CORTEX_R)
mov sp, r0
#else
/* set stack to privileged stack
@ -113,7 +113,7 @@ SECTION_FUNC(TEXT,z_arm_userspace_enter)
mov r1, ip
push {r0,r1}
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) \
|| defined(CONFIG_ARMV7_R)
|| defined(CONFIG_CPU_AARCH32_CORTEX_R)
push {r0,ip}
#endif
@ -145,7 +145,7 @@ SECTION_FUNC(TEXT,z_arm_userspace_enter)
push {r0,r3}
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) \
|| defined(CONFIG_ARMV7_R)
|| defined(CONFIG_CPU_AARCH32_CORTEX_R)
pop {r0,ip}
/* load up stack info from user stack */
@ -169,7 +169,7 @@ SECTION_FUNC(TEXT,z_arm_userspace_enter)
pop {r0, r1}
mov ip, r1
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) \
|| defined(CONFIG_ARMV7_R)
|| defined(CONFIG_CPU_AARCH32_CORTEX_R)
pop {r0,ip}
#endif
@ -184,11 +184,11 @@ SECTION_FUNC(TEXT,z_arm_userspace_enter)
mov lr, r4
mov r4, ip
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) \
|| defined(CONFIG_ARMV7_R)
|| defined(CONFIG_CPU_AARCH32_CORTEX_R)
pop {r1,r2,r3,lr}
#endif
#if defined(CONFIG_ARMV7_R)
#if defined(CONFIG_CPU_AARCH32_CORTEX_R)
/*
* set stack to user stack. We are in SYSTEM state, so r13 and r14 are
* shared with USER state
@ -244,7 +244,7 @@ SECTION_FUNC(TEXT,z_arm_userspace_enter)
/* restore r0 */
mov r0, lr
#if defined(CONFIG_ARMV7_R)
#if defined(CONFIG_CPU_AARCH32_CORTEX_R)
/* change processor mode to unprivileged, with all interrupts enabled. */
msr CPSR_c, #MODE_USR
#else
@ -296,7 +296,7 @@ SECTION_FUNC(TEXT,z_arm_userspace_enter)
mov ip, r0
pop {r0, r1}
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) \
|| defined(CONFIG_ARMV7_R)
|| defined(CONFIG_CPU_AARCH32_CORTEX_R)
ldr ip, =z_thread_entry
#endif
bx ip
@ -362,7 +362,7 @@ SECTION_FUNC(TEXT, z_arm_do_syscall)
subs ip, #8
str sp, [ip, #0]
str lr, [ip, #4]
#elif defined(CONFIG_ARMV7_R)
#elif defined(CONFIG_CPU_AARCH32_CORTEX_R)
/*
* The SVC handler has already switched to the privileged stack.
* Store the user SP and LR at the beginning of the priv stack.
@ -373,7 +373,7 @@ SECTION_FUNC(TEXT, z_arm_do_syscall)
push {ip, lr}
#endif
#if !defined(CONFIG_ARMV7_R)
#if !defined(CONFIG_CPU_AARCH32_CORTEX_R)
/* switch to privileged stack */
msr PSP, ip
#endif
@ -449,7 +449,7 @@ dispatch_syscall:
mov r0, ip
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) \
|| defined(CONFIG_ARMV7_R)
|| defined(CONFIG_CPU_AARCH32_CORTEX_R)
ldr ip, =K_SYSCALL_BAD
cmp r6, ip
bne valid_syscall
@ -551,7 +551,7 @@ dispatch_syscall:
msr CONTROL, r2
pop {r2, r3}
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) \
|| defined(CONFIG_ARMV7_R)
|| defined(CONFIG_CPU_AARCH32_CORTEX_R)
ldr r0, =_kernel
ldr r0, [r0, #_kernel_offset_to_current]
ldr r1, [r0, #_thread_offset_to_mode]
@ -615,7 +615,7 @@ dispatch_syscall:
*/
mov ip, r8
orrs ip, ip, #1
#elif defined(CONFIG_ARMV7_R)
#elif defined(CONFIG_CPU_AARCH32_CORTEX_R)
/* Restore user stack pointer */
ldr ip, [sp,#12]
mov sp, ip
@ -646,7 +646,7 @@ SECTION_FUNC(TEXT, arch_user_string_nlen)
/* sp+4 is error value, init to -1 */
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) \
|| defined(CONFIG_ARMV7_R)
|| defined(CONFIG_CPU_AARCH32_CORTEX_R)
ldr r3, =-1
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
mov.w r3, #-1
@ -662,7 +662,7 @@ z_arm_user_string_nlen_fault_start:
ldrb r5, [r0, r3]
z_arm_user_string_nlen_fault_end:
#if defined(CONFIG_ARMV7_R)
#if defined(CONFIG_CPU_AARCH32_CORTEX_R)
cmp r5, #0
beq strlen_done

View file

@ -68,6 +68,7 @@ MAKE_REG_HELPER(sctlr, 0, 1, 0, 0);
MAKE_REG_HELPER(prselr, 0, 6, 2, 1);
MAKE_REG_HELPER(prbar, 0, 6, 3, 0);
MAKE_REG_HELPER(prlar, 0, 6, 3, 1);
MAKE_REG_HELPER(mair0, 0, 10, 2, 0);
MAKE_REG_HELPER(vbar, 0, 12, 0, 0);
MAKE_REG_HELPER(cntv_ctl, 0, 14, 3, 1);
MAKE_REG64_HELPER(ICC_SGI1R, 0, 12);

View file

@ -10,12 +10,13 @@
defined(CONFIG_CPU_CORTEX_M3) || \
defined(CONFIG_CPU_CORTEX_M4) || \
defined(CONFIG_CPU_CORTEX_M7) || \
defined(CONFIG_CPU_AARCH32_CORTEX_R)
defined(CONFIG_ARMV7_R)
#include <zephyr/arch/arm/aarch32/mpu/arm_mpu_v7m.h>
#elif defined(CONFIG_CPU_CORTEX_M23) || \
defined(CONFIG_CPU_CORTEX_M33) || \
defined(CONFIG_CPU_CORTEX_M55)
#include <zephyr/arch/arm/aarch32/mpu/arm_mpu_v8m.h>
defined(CONFIG_CPU_CORTEX_M55) || \
defined(CONFIG_AARCH32_ARMV8_R)
#include <zephyr/arch/arm/aarch32/mpu/arm_mpu_v8.h>
#else
#error "Unsupported ARM CPU"
#endif
@ -44,7 +45,7 @@ struct arm_mpu_config {
const struct arm_mpu_region *mpu_regions;
};
#if defined(CONFIG_CPU_AARCH32_CORTEX_R)
#if defined(CONFIG_ARMV7_R)
#define MPU_REGION_ENTRY(_name, _base, _size, _attr) \
{\
.name = _name, \

View file

@ -7,12 +7,33 @@
#ifndef _ASMLANGUAGE
#include <zephyr/arch/arm/aarch32/cortex_m/cmsis.h>
/* Convenience macros to represent the ARMv8-M-specific
* configuration for memory access permission and
* cache-ability attribution.
*/
#if defined(CONFIG_AARCH32_ARMV8_R)
#define MPU_IR_REGION_Msk (0xFFU)
#define MPU_IR_REGION_Pos 8U
/* MPU RBAR Register attribute msk Definitions */
#define MPU_RBAR_BASE_Pos 6U
#define MPU_RBAR_BASE_Msk (0x3FFFFFFFFFFFFFFUL << MPU_RBAR_BASE_Pos)
#define MPU_RBAR_SH_Pos 3U
#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos)
#define MPU_RBAR_AP_Pos 1U
#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos)
/* RBAR XN */
#define MPU_RBAR_XN_Pos 0U
#define MPU_RBAR_XN_Msk (0x1UL << MPU_RBAR_XN_Pos)
/* MPU PLBAR Register Definitions */
#define MPU_RLAR_LIMIT_Pos 6U
#define MPU_RLAR_LIMIT_Msk (0x3FFFFFFFFFFFFFFUL << MPU_RLAR_LIMIT_Pos)
#define MPU_RLAR_AttrIndx_Pos 1U
#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos)
#define MPU_RLAR_EN_Msk (0x1UL)
#else
#include <zephyr/arch/arm/aarch32/cortex_m/cmsis.h>
#endif
/* Privileged No Access, Unprivileged No Access */
/*#define NO_ACCESS 0x0 */
@ -60,8 +81,31 @@
#define REGION_LIMIT_ADDR(base, size) \
(((base & MPU_RBAR_BASE_Msk) + size - 1) & MPU_RLAR_LIMIT_Msk)
/* Attribute flags for cache-ability */
#if defined(CONFIG_AARCH32_ARMV8_R)
/* Memory Attributes for Device Memory
* 1.Gathering (G/nG)
* Determines whether multiple accesses can be merged into a single
* bus transaction.
* nG: Number/size of accesses on the bus = number/size of accesses
* in code.
*
* 2.Reordering (R/nR)
* Determines whether accesses to the same device can be reordered.
* nR: Accesses to the same IMPLEMENTATION DEFINED block size will
* appear on the bus in program order.
*
* 3 Early Write Acknowledgment (E/nE)
* Indicates to the memory system whether a buffer can send
* acknowledgements.
* nE: The response should come from the end slave, not buffering in
* the interconnect.
*/
#define DEVICE_nGnRnE 0x0U
#define DEVICE_nGnRE 0x4U
#define DEVICE_nGRE 0x8U
#define DEVICE_GRE 0xCU
#endif
/* Read/Write Allocation Configurations for Cacheable Memory */
#define R_NON_W_NON 0x0 /* Do not allocate Read/Write */
@ -109,15 +153,98 @@
#define MPU_MAIR_ATTR_SRAM_NOCACHE MPU_CACHE_ATTRIBUTES_SRAM_NOCACHE
#define MPU_MAIR_INDEX_SRAM_NOCACHE 2
#if defined(CONFIG_AARCH32_ARMV8_R)
#define MPU_MAIR_ATTR_DEVICE DEVICE_nGnRnE
#define MPU_MAIR_INDEX_DEVICE 3
/* Flash region(s): Attribute-0
* SRAM region(s): Attribute-1
* SRAM no cache-able regions(s): Attribute-2
* DEVICE no cache-able regions(s): Attribute-3
*/
#define MPU_MAIR_ATTRS \
((MPU_MAIR_ATTR_FLASH << (MPU_MAIR_INDEX_FLASH * 8)) | \
(MPU_MAIR_ATTR_SRAM << (MPU_MAIR_INDEX_SRAM * 8)) | \
(MPU_MAIR_ATTR_SRAM_NOCACHE << (MPU_MAIR_INDEX_SRAM_NOCACHE * 8)) | \
(MPU_MAIR_ATTR_DEVICE << (MPU_MAIR_INDEX_DEVICE * 8)))
#else
/* Flash region(s): Attribute-0
* SRAM region(s): Attribute-1
* SRAM no cache-able regions(s): Attribute-2
*/
#define MPU_MAIR_ATTRS \
(((MPU_MAIR_ATTR_FLASH << MPU_MAIR0_Attr0_Pos) & MPU_MAIR0_Attr0_Msk) | \
((MPU_MAIR_ATTR_SRAM << MPU_MAIR0_Attr1_Pos) & MPU_MAIR0_Attr1_Msk) | \
((MPU_MAIR_ATTR_SRAM_NOCACHE << MPU_MAIR0_Attr2_Pos) & \
MPU_MAIR0_Attr2_Msk))
#endif
/* Some helper defines for common regions.
*
* Note that the ARMv8-M MPU architecture requires that the
* Note that the ARMv8-M/R MPU architecture requires that the
* enabled MPU regions are non-overlapping. Therefore, it is
* recommended to use these helper defines only for configuring
* fixed MPU regions at build-time (i.e. regions that are not
* expected to be re-programmed or re-adjusted at run-time so
* that they do not overlap with other MPU regions).
*/
#if defined(CONFIG_AARCH32_ARMV8_R)
#define REGION_RAM_ATTR(limit) \
{ \
.rbar = NOT_EXEC | \
P_RW_U_NA_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
/* Cache-ability */ \
.mair_idx = MPU_MAIR_INDEX_SRAM, \
.r_limit = limit - 1, /* Region Limit */ \
}
#define REGION_RAM_TEXT_ATTR(limit) \
{ \
.rbar = P_RO_U_RO_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
/* Cache-ability */ \
.mair_idx = MPU_MAIR_INDEX_SRAM, \
.r_limit = limit - 1, /* Region Limit */ \
}
#define REGION_RAM_RO_ATTR(limit) \
{ \
.rbar = NOT_EXEC | \
P_RO_U_RO_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
/* Cache-ability */ \
.mair_idx = MPU_MAIR_INDEX_SRAM, \
.r_limit = limit - 1, /* Region Limit */ \
}
#if defined(CONFIG_MPU_ALLOW_FLASH_WRITE)
/* Note that the access permissions allow for un-privileged writes, contrary
* to ARMv7-M where un-privileged code has Read-Only permissions.
*/
#define REGION_FLASH_ATTR(limit) \
{ \
.rbar = P_RW_U_RW_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
/* Cache-ability */ \
.mair_idx = MPU_MAIR_INDEX_FLASH, \
.r_limit = limit - 1, /* Region Limit */ \
}
#else /* CONFIG_MPU_ALLOW_FLASH_WRITE */
#define REGION_FLASH_ATTR(limit) \
{ \
.rbar = RO_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
/* Cache-ability */ \
.mair_idx = MPU_MAIR_INDEX_FLASH, \
.r_limit = limit - 1, /* Region Limit */ \
}
#endif /* CONFIG_MPU_ALLOW_FLASH_WRITE */
#define REGION_DEVICE_ATTR(limit) \
{ \
/* AP, XN, SH */ \
.rbar = NOT_EXEC | P_RW_U_NA_Msk | NON_SHAREABLE_Msk, \
/* Cache-ability */ \
.mair_idx = MPU_MAIR_INDEX_DEVICE, \
/* Region Limit */ \
.r_limit = limit - 1, \
}
#else
#define REGION_RAM_ATTR(base, size) \
{\
.rbar = NOT_EXEC | \
@ -157,6 +284,7 @@
}
#endif /* CONFIG_MPU_ALLOW_FLASH_WRITE */
#endif
struct arm_mpu_region_attr {
/* Attributes belonging to RBAR */