blob: 67a5a365993ff6530569539cb03f81ec9b060ab8 [file] [log] [blame]
/*
* Copyright (c) 2018 Linaro Limited.
* Copyright (c) 2018 Nordic Semiconductor ASA.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _ASMLANGUAGE
/* 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 */
/*#define NO_ACCESS_Msk ((NO_ACCESS << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) */
/* Privileged No Access, Unprivileged No Access */
/*#define P_NA_U_NA 0x0 */
/*#define P_NA_U_NA_Msk ((P_NA_U_NA << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) */
/* Privileged Read Write, Unprivileged No Access */
#define P_RW_U_NA 0x0
#define P_RW_U_NA_Msk ((P_RW_U_NA << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
/* Privileged Read Write, Unprivileged Read Only */
/*#define P_RW_U_RO 0x2 */
/*#define P_RW_U_RO_Msk ((P_RW_U_RO << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk)*/
/* Privileged Read Write, Unprivileged Read Write */
#define P_RW_U_RW 0x1
#define P_RW_U_RW_Msk ((P_RW_U_RW << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
/* Privileged Read Write, Unprivileged Read Write */
#define FULL_ACCESS 0x1
#define FULL_ACCESS_Msk ((FULL_ACCESS << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
/* Privileged Read Only, Unprivileged No Access */
#define P_RO_U_NA 0x2
#define P_RO_U_NA_Msk ((P_RO_U_NA << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
/* Privileged Read Only, Unprivileged Read Only */
#define P_RO_U_RO 0x3
#define P_RO_U_RO_Msk ((P_RO_U_RO << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
/* Privileged Read Only, Unprivileged Read Only */
#define RO 0x3
#define RO_Msk ((RO << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
/* Attribute flag for not-allowing execution (eXecute Never) */
#define NOT_EXEC MPU_RBAR_XN_Msk
/* Attribute flags for share-ability */
#define NON_SHAREABLE 0x0
#define NON_SHAREABLE_Msk \
((NON_SHAREABLE << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk)
#define OUTER_SHAREABLE 0x2
#define OUTER_SHAREABLE_Msk \
((OUTER_SHAREABLE << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk)
#define INNER_SHAREABLE 0x3
#define INNER_SHAREABLE_Msk \
((INNER_SHAREABLE << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk)
/* Helper define to calculate the region limit address. */
#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 */
#define R_NON_W_ALLOC 0x1 /* Do not allocate Read, Allocate Write */
#define R_ALLOC_W_NON 0x2 /* Allocate Read, Do not allocate Write */
#define R_ALLOC_W_ALLOC 0x3 /* Allocate Read/Write */
/* Memory Attributes for Normal Memory */
#define NORMAL_O_WT_NT 0x80 /* Normal, Outer Write-through non-transient */
#define NORMAL_O_WB_NT 0xC0 /* Normal, Outer Write-back non-transient */
#define NORMAL_O_NON_C 0x40 /* Normal, Outer Non-Cacheable */
#define NORMAL_I_WT_NT 0x08 /* Normal, Inner Write-through non-transient */
#define NORMAL_I_WB_NT 0x0C /* Normal, Inner Write-back non-transient */
#define NORMAL_I_NON_C 0x04 /* Normal, Inner Non-Cacheable */
#define NORMAL_OUTER_INNER_WRITE_THROUGH_READ_ALLOCATE_NON_TRANS \
((NORMAL_O_WT_NT | (R_ALLOC_W_NON << 4)) \
| \
(NORMAL_I_WT_NT | R_ALLOC_W_NON)) \
#define NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_TRANS \
((NORMAL_O_WB_NT | (R_ALLOC_W_ALLOC << 4)) \
| \
(NORMAL_I_WB_NT | R_ALLOC_W_ALLOC))
#define NORMAL_OUTER_INNER_NON_CACHEABLE \
((NORMAL_O_NON_C | (R_NON_W_NON << 4)) \
| \
(NORMAL_I_NON_C | R_NON_W_NON))
/* Common cache-ability configuration for Flash, SRAM regions */
#define MPU_CACHE_ATTRIBUTES_FLASH \
NORMAL_OUTER_INNER_WRITE_THROUGH_READ_ALLOCATE_NON_TRANS
#define MPU_CACHE_ATTRIBUTES_SRAM \
NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_TRANS
#define MPU_CACHE_ATTRIBUTES_SRAM_NOCACHE \
NORMAL_OUTER_INNER_NON_CACHEABLE
/* Global MAIR configurations */
#define MPU_MAIR_ATTR_FLASH MPU_CACHE_ATTRIBUTES_FLASH
#define MPU_MAIR_INDEX_FLASH 0
#define MPU_MAIR_ATTR_SRAM MPU_CACHE_ATTRIBUTES_SRAM
#define MPU_MAIR_INDEX_SRAM 1
#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/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 | \
P_RW_U_NA_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
/* Cache-ability */ \
.mair_idx = MPU_MAIR_INDEX_SRAM, \
.r_limit = REGION_LIMIT_ADDR(base, size), /* Region Limit */ \
}
#define REGION_RAM_NOCACHE_ATTR(base, size) \
{\
.rbar = NOT_EXEC | \
P_RW_U_NA_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
/* Cache-ability */ \
.mair_idx = MPU_MAIR_INDEX_SRAM_NOCACHE, \
.r_limit = REGION_LIMIT_ADDR(base, size), /* 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(base, size) \
{\
.rbar = P_RW_U_RW_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
/* Cache-ability */ \
.mair_idx = MPU_MAIR_INDEX_FLASH, \
.r_limit = REGION_LIMIT_ADDR(base, size), /* Region Limit */ \
}
#else /* CONFIG_MPU_ALLOW_FLASH_WRITE */
#define REGION_FLASH_ATTR(base, size) \
{\
.rbar = RO_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
/* Cache-ability */ \
.mair_idx = MPU_MAIR_INDEX_FLASH, \
.r_limit = REGION_LIMIT_ADDR(base, size), /* Region Limit */ \
}
#endif /* CONFIG_MPU_ALLOW_FLASH_WRITE */
#endif
struct arm_mpu_region_attr {
/* Attributes belonging to RBAR */
uint8_t rbar: 5;
/* MAIR index for attribute indirection */
uint8_t mair_idx: 3;
/* Region Limit Address value to be written to the RLAR register. */
uint32_t r_limit;
};
typedef struct arm_mpu_region_attr arm_mpu_region_attr_t;
/* Typedef for the k_mem_partition attribute */
typedef struct {
uint16_t rbar;
uint16_t mair_idx;
} k_mem_partition_attr_t;
/* Kernel macros for memory attribution
* (access permissions and cache-ability).
*
* The macros are to be stored in k_mem_partition_attr_t
* objects. The format of a k_mem_partition_attr_t object
* is as follows: field <rbar> contains a direct mapping
* of the <XN> and <AP> bit-fields of the RBAR register;
* field <mair_idx> contains a direct mapping of AttrIdx
* bit-field, stored in RLAR register.
*/
/* Read-Write access permission attributes */
#define K_MEM_PARTITION_P_RW_U_RW ((k_mem_partition_attr_t) \
{(P_RW_U_RW_Msk | NOT_EXEC), MPU_MAIR_INDEX_SRAM})
#define K_MEM_PARTITION_P_RW_U_NA ((k_mem_partition_attr_t) \
{(P_RW_U_NA_Msk | NOT_EXEC), MPU_MAIR_INDEX_SRAM})
#define K_MEM_PARTITION_P_RO_U_RO ((k_mem_partition_attr_t) \
{(P_RO_U_RO_Msk | NOT_EXEC), MPU_MAIR_INDEX_SRAM})
#define K_MEM_PARTITION_P_RO_U_NA ((k_mem_partition_attr_t) \
{(P_RO_U_NA_Msk | NOT_EXEC), MPU_MAIR_INDEX_SRAM})
/* Execution-allowed attributes */
#define K_MEM_PARTITION_P_RWX_U_RWX ((k_mem_partition_attr_t) \
{(P_RW_U_RW_Msk), MPU_MAIR_INDEX_SRAM})
#define K_MEM_PARTITION_P_RX_U_RX ((k_mem_partition_attr_t) \
{(P_RO_U_RO_Msk), MPU_MAIR_INDEX_SRAM})
/*
* @brief Evaluate Write-ability
*
* Evaluate whether the access permissions include write-ability.
*
* @param attr The k_mem_partition_attr_t object holding the
* MPU attributes to be checked against write-ability.
*/
#define K_MEM_PARTITION_IS_WRITABLE(attr) \
({ \
int __is_writable__; \
switch (attr.rbar & MPU_RBAR_AP_Msk) { \
case P_RW_U_RW_Msk: \
case P_RW_U_NA_Msk: \
__is_writable__ = 1; \
break; \
default: \
__is_writable__ = 0; \
} \
__is_writable__; \
})
/*
* @brief Evaluate Execution allowance
*
* Evaluate whether the access permissions include execution.
*
* @param attr The k_mem_partition_attr_t object holding the
* MPU attributes to be checked against execution
* allowance.
*/
#define K_MEM_PARTITION_IS_EXECUTABLE(attr) \
(!((attr.rbar) & (NOT_EXEC)))
/* Attributes for no-cache enabling (share-ability is selected by default) */
/* Read-Write access permission attributes */
#define K_MEM_PARTITION_P_RW_U_RW_NOCACHE ((k_mem_partition_attr_t) \
{(P_RW_U_RW_Msk | NOT_EXEC | OUTER_SHAREABLE_Msk), \
MPU_MAIR_INDEX_SRAM_NOCACHE})
#define K_MEM_PARTITION_P_RW_U_NA_NOCACHE ((k_mem_partition_attr_t) \
{(P_RW_U_NA_Msk | NOT_EXEC | OUTER_SHAREABLE_Msk), \
MPU_MAIR_INDEX_SRAM_NOCACHE})
#define K_MEM_PARTITION_P_RO_U_RO_NOCACHE ((k_mem_partition_attr_t) \
{(P_RO_U_RO_Msk | NOT_EXEC | OUTER_SHAREABLE_Msk), \
MPU_MAIR_INDEX_SRAM_NOCACHE})
#define K_MEM_PARTITION_P_RO_U_NA_NOCACHE ((k_mem_partition_attr_t) \
{(P_RO_U_NA_Msk | NOT_EXEC | OUTER_SHAREABLE_Msk), \
MPU_MAIR_INDEX_SRAM_NOCACHE})
/* Execution-allowed attributes */
#define K_MEM_PARTITION_P_RWX_U_RWX_NOCACHE ((k_mem_partition_attr_t) \
{(P_RW_U_RW_Msk | OUTER_SHAREABLE_Msk), MPU_MAIR_INDEX_SRAM_NOCACHE})
#define K_MEM_PARTITION_P_RX_U_RX_NOCACHE ((k_mem_partition_attr_t) \
{(P_RO_U_RO_Msk | OUTER_SHAREABLE_Msk), MPU_MAIR_INDEX_SRAM_NOCACHE})
#endif /* _ASMLANGUAGE */
#define _ARCH_MEM_PARTITION_ALIGN_CHECK(start, size) \
BUILD_ASSERT((size > 0) && ((uint32_t)start % \
CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE == 0U) && \
((size) % CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE == 0), \
" the start and size of the partition must align " \
"with the minimum MPU region size.")