1 /* 2 * Copyright (c) 2018 Linaro Limited. 3 * Copyright (c) 2018 Nordic Semiconductor ASA. 4 * 5 * SPDX-License-Identifier: Apache-2.0 6 */ 7 8 #ifndef _ASMLANGUAGE 9 10 #include <cmsis_core.h> 11 12 /* Convenience macros to represent the ARMv7-M-specific 13 * configuration for memory access permission and 14 * cache-ability attribution. 15 */ 16 17 /* Privileged No Access, Unprivileged No Access */ 18 #define NO_ACCESS 0x0 19 #define NO_ACCESS_Msk ((NO_ACCESS << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) 20 /* Privileged No Access, Unprivileged No Access */ 21 #define P_NA_U_NA 0x0 22 #define P_NA_U_NA_Msk ((P_NA_U_NA << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) 23 /* Privileged Read Write, Unprivileged No Access */ 24 #define P_RW_U_NA 0x1 25 #define P_RW_U_NA_Msk ((P_RW_U_NA << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) 26 /* Privileged Read Write, Unprivileged Read Only */ 27 #define P_RW_U_RO 0x2 28 #define P_RW_U_RO_Msk ((P_RW_U_RO << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) 29 /* Privileged Read Write, Unprivileged Read Write */ 30 #define P_RW_U_RW 0x3U 31 #define P_RW_U_RW_Msk ((P_RW_U_RW << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) 32 /* Privileged Read Write, Unprivileged Read Write */ 33 #define FULL_ACCESS 0x3 34 #define FULL_ACCESS_Msk ((FULL_ACCESS << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) 35 /* Privileged Read Only, Unprivileged No Access */ 36 #define P_RO_U_NA 0x5 37 #define P_RO_U_NA_Msk ((P_RO_U_NA << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) 38 /* Privileged Read Only, Unprivileged Read Only */ 39 #define P_RO_U_RO 0x6 40 #define P_RO_U_RO_Msk ((P_RO_U_RO << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) 41 /* Privileged Read Only, Unprivileged Read Only */ 42 #define RO 0x7 43 #define RO_Msk ((RO << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) 44 45 /* Attribute flag for not-allowing execution (eXecute Never) */ 46 #define NOT_EXEC MPU_RASR_XN_Msk 47 48 /* The following definitions are for internal use in arm_mpu.h. */ 49 #define STRONGLY_ORDERED_SHAREABLE MPU_RASR_S_Msk 50 #define DEVICE_SHAREABLE (MPU_RASR_B_Msk | MPU_RASR_S_Msk) 51 #define NORMAL_OUTER_INNER_WRITE_THROUGH_SHAREABLE (MPU_RASR_C_Msk | MPU_RASR_S_Msk) 52 #define NORMAL_OUTER_INNER_WRITE_THROUGH_NON_SHAREABLE MPU_RASR_C_Msk 53 /* clang-format off */ 54 #define NORMAL_OUTER_INNER_WRITE_BACK_SHAREABLE \ 55 (MPU_RASR_C_Msk | MPU_RASR_B_Msk | MPU_RASR_S_Msk) 56 /* clang-format on */ 57 #define NORMAL_OUTER_INNER_WRITE_BACK_NON_SHAREABLE (MPU_RASR_C_Msk | MPU_RASR_B_Msk) 58 #define NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE ((1 << MPU_RASR_TEX_Pos) | MPU_RASR_S_Msk) 59 #define NORMAL_OUTER_INNER_NON_CACHEABLE_NON_SHAREABLE (1 << MPU_RASR_TEX_Pos) 60 #define NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_SHAREABLE \ 61 ((1 << MPU_RASR_TEX_Pos) | MPU_RASR_C_Msk | MPU_RASR_B_Msk | MPU_RASR_S_Msk) 62 #define NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE \ 63 ((1 << MPU_RASR_TEX_Pos) | MPU_RASR_C_Msk | MPU_RASR_B_Msk) 64 #define DEVICE_NON_SHAREABLE (2 << MPU_RASR_TEX_Pos) 65 66 /* Bit-masks to disable sub-regions. */ 67 #define SUB_REGION_0_DISABLED ((0x01 << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) 68 #define SUB_REGION_1_DISABLED ((0x02 << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) 69 #define SUB_REGION_2_DISABLED ((0x04 << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) 70 #define SUB_REGION_3_DISABLED ((0x08 << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) 71 #define SUB_REGION_4_DISABLED ((0x10 << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) 72 #define SUB_REGION_5_DISABLED ((0x20 << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) 73 #define SUB_REGION_6_DISABLED ((0x40 << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) 74 #define SUB_REGION_7_DISABLED ((0x80 << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) 75 76 #define REGION_SIZE(size) ((ARM_MPU_REGION_SIZE_##size << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) 77 78 #define REGION_32B REGION_SIZE(32B) 79 #define REGION_64B REGION_SIZE(64B) 80 #define REGION_128B REGION_SIZE(128B) 81 #define REGION_256B REGION_SIZE(256B) 82 #define REGION_512B REGION_SIZE(512B) 83 #define REGION_1K REGION_SIZE(1KB) 84 #define REGION_2K REGION_SIZE(2KB) 85 #define REGION_4K REGION_SIZE(4KB) 86 #define REGION_8K REGION_SIZE(8KB) 87 #define REGION_16K REGION_SIZE(16KB) 88 #define REGION_32K REGION_SIZE(32KB) 89 #define REGION_64K REGION_SIZE(64KB) 90 #define REGION_128K REGION_SIZE(128KB) 91 #define REGION_256K REGION_SIZE(256KB) 92 #define REGION_512K REGION_SIZE(512KB) 93 #define REGION_1M REGION_SIZE(1MB) 94 #define REGION_2M REGION_SIZE(2MB) 95 #define REGION_4M REGION_SIZE(4MB) 96 #define REGION_8M REGION_SIZE(8MB) 97 #define REGION_16M REGION_SIZE(16MB) 98 #define REGION_32M REGION_SIZE(32MB) 99 #define REGION_64M REGION_SIZE(64MB) 100 #define REGION_128M REGION_SIZE(128MB) 101 #define REGION_256M REGION_SIZE(256MB) 102 #define REGION_512M REGION_SIZE(512MB) 103 #define REGION_1G REGION_SIZE(1GB) 104 #define REGION_2G REGION_SIZE(2GB) 105 #define REGION_4G REGION_SIZE(4GB) 106 107 #define ARM_MPU_REGION_INIT(p_name, p_base, p_size, p_attr) \ 108 { \ 109 .name = p_name, \ 110 .base = p_base, \ 111 .attr = p_attr(size_to_mpu_rasr_size(p_size)), \ 112 } 113 114 /* Some helper defines for common regions */ 115 116 /* On Cortex-M, we can only set the XN bit when CONFIG_XIP=y. When 117 * CONFIG_XIP=n, the entire image will be linked to SRAM, so we need to keep 118 * the SRAM region XN bit clear or the application code will not be executable. 119 */ 120 #define REGION_RAM_ATTR(size) \ 121 {(NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE | \ 122 IF_ENABLED(CONFIG_XIP, (MPU_RASR_XN_Msk |)) size | P_RW_U_NA_Msk)} 123 #define REGION_RAM_NOCACHE_ATTR(size) \ 124 {(NORMAL_OUTER_INNER_NON_CACHEABLE_NON_SHAREABLE | MPU_RASR_XN_Msk | size | P_RW_U_NA_Msk)} 125 #if defined(CONFIG_MPU_ALLOW_FLASH_WRITE) 126 #define REGION_FLASH_ATTR(size) \ 127 {(NORMAL_OUTER_INNER_WRITE_THROUGH_NON_SHAREABLE | size | P_RW_U_RO_Msk)} 128 #else 129 #define REGION_FLASH_ATTR(size) {(NORMAL_OUTER_INNER_WRITE_THROUGH_NON_SHAREABLE | size | RO_Msk)} 130 #endif 131 #define REGION_PPB_ATTR(size) {(STRONGLY_ORDERED_SHAREABLE | size | P_RW_U_NA_Msk)} 132 #define REGION_IO_ATTR(size) {(DEVICE_NON_SHAREABLE | size | P_RW_U_NA_Msk)} 133 #define REGION_EXTMEM_ATTR(size) {(STRONGLY_ORDERED_SHAREABLE | size | NO_ACCESS_Msk)} 134 135 struct arm_mpu_region_attr { 136 /* Attributes belonging to RASR (including the encoded region size) */ 137 uint32_t rasr; 138 }; 139 140 typedef struct arm_mpu_region_attr arm_mpu_region_attr_t; 141 142 /* Typedef for the k_mem_partition attribute */ 143 typedef struct { 144 uint32_t rasr_attr; 145 } k_mem_partition_attr_t; 146 147 /* Read-Write access permission attributes */ 148 #define _K_MEM_PARTITION_P_NA_U_NA (NO_ACCESS_Msk | NOT_EXEC) 149 #define _K_MEM_PARTITION_P_RW_U_RW (P_RW_U_RW_Msk | NOT_EXEC) 150 #define _K_MEM_PARTITION_P_RW_U_RO (P_RW_U_RO_Msk | NOT_EXEC) 151 #define _K_MEM_PARTITION_P_RW_U_NA (P_RW_U_NA_Msk | NOT_EXEC) 152 #define _K_MEM_PARTITION_P_RO_U_RO (P_RO_U_RO_Msk | NOT_EXEC) 153 #define _K_MEM_PARTITION_P_RO_U_NA (P_RO_U_NA_Msk | NOT_EXEC) 154 155 /* Execution-allowed attributes */ 156 #define _K_MEM_PARTITION_P_RWX_U_RWX (P_RW_U_RW_Msk) 157 #define _K_MEM_PARTITION_P_RWX_U_RX (P_RW_U_RO_Msk) 158 #define _K_MEM_PARTITION_P_RX_U_RX (P_RO_U_RO_Msk) 159 160 /* Kernel macros for memory attribution 161 * (access permissions and cache-ability). 162 * 163 * The macros are to be stored in k_mem_partition_attr_t 164 * objects. The format of k_mem_partition_attr_t is an 165 * "1-1" mapping of the ARMv7-M MPU RASR attribute register 166 * fields (excluding the <size> and <enable> bit-fields). 167 */ 168 169 /* Read-Write access permission attributes (default cache-ability) */ 170 #define K_MEM_PARTITION_P_NA_U_NA \ 171 ((k_mem_partition_attr_t){ \ 172 _K_MEM_PARTITION_P_NA_U_NA | \ 173 NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE}) 174 #define K_MEM_PARTITION_P_RW_U_RW \ 175 ((k_mem_partition_attr_t){ \ 176 _K_MEM_PARTITION_P_RW_U_RW | \ 177 NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE}) 178 #define K_MEM_PARTITION_P_RW_U_RO \ 179 ((k_mem_partition_attr_t){ \ 180 _K_MEM_PARTITION_P_RW_U_RO | \ 181 NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE}) 182 #define K_MEM_PARTITION_P_RW_U_NA \ 183 ((k_mem_partition_attr_t){ \ 184 _K_MEM_PARTITION_P_RW_U_NA | \ 185 NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE}) 186 #define K_MEM_PARTITION_P_RO_U_RO \ 187 ((k_mem_partition_attr_t){ \ 188 _K_MEM_PARTITION_P_RO_U_RO | \ 189 NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE}) 190 #define K_MEM_PARTITION_P_RO_U_NA \ 191 ((k_mem_partition_attr_t){ \ 192 _K_MEM_PARTITION_P_RO_U_NA | \ 193 NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE}) 194 195 /* Execution-allowed attributes (default-cacheability) */ 196 #define K_MEM_PARTITION_P_RWX_U_RWX \ 197 ((k_mem_partition_attr_t){ \ 198 _K_MEM_PARTITION_P_RWX_U_RWX | \ 199 NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE}) 200 #define K_MEM_PARTITION_P_RWX_U_RX \ 201 ((k_mem_partition_attr_t){ \ 202 _K_MEM_PARTITION_P_RWX_U_RX | \ 203 NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE}) 204 #define K_MEM_PARTITION_P_RX_U_RX \ 205 ((k_mem_partition_attr_t){ \ 206 _K_MEM_PARTITION_P_RX_U_RX | \ 207 NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE}) 208 209 /* 210 * @brief Evaluate Write-ability 211 * 212 * Evaluate whether the access permissions include write-ability. 213 * 214 * @param attr The k_mem_partition_attr_t object holding the 215 * MPU attributes to be checked against write-ability. 216 */ 217 #define K_MEM_PARTITION_IS_WRITABLE(attr) \ 218 ({ \ 219 int __is_writable__; \ 220 switch (attr.rasr_attr & MPU_RASR_AP_Msk) { \ 221 case P_RW_U_RW_Msk: \ 222 case P_RW_U_RO_Msk: \ 223 case P_RW_U_NA_Msk: \ 224 __is_writable__ = 1; \ 225 break; \ 226 default: \ 227 __is_writable__ = 0; \ 228 } \ 229 __is_writable__; \ 230 }) 231 232 /* 233 * @brief Evaluate Execution allowance 234 * 235 * Evaluate whether the access permissions include execution. 236 * 237 * @param attr The k_mem_partition_attr_t object holding the 238 * MPU attributes to be checked against execution 239 * allowance. 240 */ 241 #define K_MEM_PARTITION_IS_EXECUTABLE(attr) (!((attr.rasr_attr) & (NOT_EXEC))) 242 243 /* Attributes for no-cache enabling (share-ability is selected by default) */ 244 245 #define K_MEM_PARTITION_P_NA_U_NA_NOCACHE \ 246 ((k_mem_partition_attr_t){ \ 247 (_K_MEM_PARTITION_P_NA_U_NA | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)}) 248 #define K_MEM_PARTITION_P_RW_U_RW_NOCACHE \ 249 ((k_mem_partition_attr_t){ \ 250 (_K_MEM_PARTITION_P_RW_U_RW | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)}) 251 #define K_MEM_PARTITION_P_RW_U_RO_NOCACHE \ 252 ((k_mem_partition_attr_t){ \ 253 (_K_MEM_PARTITION_P_RW_U_RO | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)}) 254 #define K_MEM_PARTITION_P_RW_U_NA_NOCACHE \ 255 ((k_mem_partition_attr_t){ \ 256 (_K_MEM_PARTITION_P_RW_U_NA | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)}) 257 #define K_MEM_PARTITION_P_RO_U_RO_NOCACHE \ 258 ((k_mem_partition_attr_t){ \ 259 (_K_MEM_PARTITION_P_RO_U_RO | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)}) 260 #define K_MEM_PARTITION_P_RO_U_NA_NOCACHE \ 261 ((k_mem_partition_attr_t){ \ 262 (_K_MEM_PARTITION_P_RO_U_NA | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)}) 263 264 #define K_MEM_PARTITION_P_RWX_U_RWX_NOCACHE \ 265 ((k_mem_partition_attr_t){ \ 266 (_K_MEM_PARTITION_P_RWX_U_RWX | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)}) 267 #define K_MEM_PARTITION_P_RWX_U_RX_NOCACHE \ 268 ((k_mem_partition_attr_t){ \ 269 (_K_MEM_PARTITION_P_RWX_U_RX | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)}) 270 #define K_MEM_PARTITION_P_RX_U_RX_NOCACHE \ 271 ((k_mem_partition_attr_t){ \ 272 (_K_MEM_PARTITION_P_RX_U_RX | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)}) 273 274 #endif /* _ASMLANGUAGE */ 275 276 #define _ARCH_MEM_PARTITION_ALIGN_CHECK_SIZE(size) \ 277 BUILD_ASSERT(!(((size) & ((size) - 1))) && \ 278 (size) >= CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE, \ 279 "The size of the partition must be power of 2 and greater than or equal to " \ 280 "the minimum MPU region size.\n") 281 282 /* Some compilers do not handle BUILD_ASSERT on the values of pointers.*/ 283 #if defined(__IAR_SYSTEMS_ICC__) 284 #define _ARCH_MEM_PARTITION_ALIGN_CHECK_START(start, size) 285 #else 286 #define _ARCH_MEM_PARTITION_ALIGN_CHECK_START(start, size) \ 287 BUILD_ASSERT(!((uint32_t)(start) & ((size) - 1)), \ 288 "The start address of the partition must align with size.") 289 #endif 290 291 #define _ARCH_MEM_PARTITION_ALIGN_CHECK(start, size) \ 292 _ARCH_MEM_PARTITION_ALIGN_CHECK_SIZE(size); \ 293 _ARCH_MEM_PARTITION_ALIGN_CHECK_START(start, size) 294