Line data Source code
1 1 : /* 2 : * Copyright (c) 2014 Wind River Systems, Inc. 3 : * 4 : * SPDX-License-Identifier: Apache-2.0 5 : */ 6 : 7 : /** 8 : * @file 9 : * @brief ARC specific kernel interface header 10 : * 11 : * This header contains the ARC specific kernel interface. It is 12 : * included by the kernel interface architecture-abstraction header 13 : * include/arch/cpu.h) 14 : */ 15 : 16 : #ifndef ZEPHYR_INCLUDE_ARCH_ARC_ARCH_H_ 17 : #define ZEPHYR_INCLUDE_ARCH_ARC_ARCH_H_ 18 : 19 : #include <zephyr/devicetree.h> 20 : #include <zephyr/sw_isr_table.h> 21 : #include <zephyr/arch/common/ffs.h> 22 : #include <zephyr/arch/arc/thread.h> 23 : #include <zephyr/arch/common/sys_bitops.h> 24 : #include "sys-io-common.h" 25 : 26 : #include <zephyr/arch/arc/v2/exception.h> 27 : #include <zephyr/arch/arc/v2/irq.h> 28 : #include <zephyr/arch/arc/v2/misc.h> 29 : #include <zephyr/arch/arc/v2/aux_regs.h> 30 : #include <zephyr/arch/arc/v2/arcv2_irq_unit.h> 31 : #include <zephyr/arch/arc/v2/asm_inline.h> 32 : #include <zephyr/arch/arc/arc_addr_types.h> 33 : #include <zephyr/arch/arc/v2/error.h> 34 : 35 : #ifdef CONFIG_ARC_CONNECT 36 : #include <zephyr/arch/arc/v2/arc_connect.h> 37 : #endif 38 : 39 : #ifdef CONFIG_ISA_ARCV2 40 : #include "v2/sys_io.h" 41 : #ifdef CONFIG_ARC_HAS_SECURE 42 : #include <zephyr/arch/arc/v2/secureshield/arc_secure.h> 43 : #endif 44 : #endif 45 : 46 : #if defined(CONFIG_ARC_FIRQ) && defined(CONFIG_ISA_ARCV3) 47 : #error "Unsupported configuration: ARC_FIRQ and ISA_ARCV3" 48 : #endif 49 : 50 : /* 51 : * We don't allow the configuration with FIRQ enabled and only one interrupt priority level 52 : * (so all interrupts are FIRQ). Such configuration isn't supported in software and it is not 53 : * beneficial from the performance point of view. 54 : */ 55 : #if defined(CONFIG_ARC_FIRQ) && CONFIG_NUM_IRQ_PRIO_LEVELS < 2 56 : #error "Unsupported configuration: ARC_FIRQ and (NUM_IRQ_PRIO_LEVELS < 2)" 57 : #endif 58 : 59 : #if CONFIG_RGF_NUM_BANKS > 1 && !defined(CONFIG_ARC_FIRQ) 60 : #error "Unsupported configuration: (RGF_NUM_BANKS > 1) and !ARC_FIRQ" 61 : #endif 62 : 63 : /* 64 : * It's required to have more than one interrupt priority level to use second register bank 65 : * - otherwise all interrupts will use same register bank. Such configuration isn't supported in 66 : * software and it is not beneficial from the performance point of view. 67 : */ 68 : #if CONFIG_RGF_NUM_BANKS > 1 && CONFIG_NUM_IRQ_PRIO_LEVELS < 2 69 : #error "Unsupported configuration: (RGF_NUM_BANKS > 1) and (NUM_IRQ_PRIO_LEVELS < 2)" 70 : #endif 71 : 72 : #if defined(CONFIG_ARC_FIRQ_STACK) && !defined(CONFIG_ARC_FIRQ) 73 : #error "Unsupported configuration: ARC_FIRQ_STACK and !ARC_FIRQ" 74 : #endif 75 : 76 : #if defined(CONFIG_ARC_FIRQ_STACK) && CONFIG_RGF_NUM_BANKS < 2 77 : #error "Unsupported configuration: ARC_FIRQ_STACK and (RGF_NUM_BANKS < 2)" 78 : #endif 79 : 80 : /* In case of ARC 2+2 secure mode enabled the firq are not supported by HW */ 81 : #if defined(CONFIG_ARC_FIRQ) && defined(CONFIG_ARC_HAS_SECURE) 82 : #error "Unsupported configuration: ARC_FIRQ and ARC_HAS_SECURE" 83 : #endif 84 : 85 : #if defined(CONFIG_SMP) && !defined(CONFIG_MULTITHREADING) 86 : #error "Non-multithreading mode isn't supported on SMP targets" 87 : #endif 88 : 89 : #ifndef _ASMLANGUAGE 90 : 91 : #ifdef __cplusplus 92 : extern "C" { 93 : #endif 94 : 95 : #ifdef CONFIG_64BIT 96 : #define ARCH_STACK_PTR_ALIGN 8 97 : #else 98 0 : #define ARCH_STACK_PTR_ALIGN 4 99 : #endif /* CONFIG_64BIT */ 100 : 101 : BUILD_ASSERT(CONFIG_ISR_STACK_SIZE % ARCH_STACK_PTR_ALIGN == 0, 102 : "CONFIG_ISR_STACK_SIZE must be a multiple of ARCH_STACK_PTR_ALIGN"); 103 : 104 : BUILD_ASSERT(CONFIG_ARC_EXCEPTION_STACK_SIZE % ARCH_STACK_PTR_ALIGN == 0, 105 : "CONFIG_ARC_EXCEPTION_STACK_SIZE must be a multiple of ARCH_STACK_PTR_ALIGN"); 106 : 107 : /* Indicate, for a minimally sized MPU region, how large it must be and what 108 : * its base address must be aligned to. 109 : * 110 : * For regions that are NOT the minimum size, this define has no semantics 111 : * on ARC MPUv2 as its regions must be power of two size and aligned to their 112 : * own size. On ARC MPUv4, region sizes are arbitrary and this just indicates 113 : * the required size granularity. 114 : */ 115 : #ifdef CONFIG_ARC_CORE_MPU 116 : #if CONFIG_ARC_MPU_VER == 2 117 : #define Z_ARC_MPU_ALIGN 2048 118 : #elif (CONFIG_ARC_MPU_VER == 3) || (CONFIG_ARC_MPU_VER == 4) || \ 119 : (CONFIG_ARC_MPU_VER == 6) || (CONFIG_ARC_MPU_VER == 8) 120 : #define Z_ARC_MPU_ALIGN 32 121 : #else 122 : #error "Unsupported MPU version" 123 : #endif 124 : #endif 125 : 126 : #ifdef CONFIG_MPU_STACK_GUARD 127 : #define Z_ARC_STACK_GUARD_SIZE Z_ARC_MPU_ALIGN 128 : #else 129 : #define Z_ARC_STACK_GUARD_SIZE 0 130 : #endif 131 : 132 : /* Kernel-only stacks have the following layout if a stack guard is enabled: 133 : * 134 : * +------------+ <- thread.stack_obj 135 : * | Guard | } Z_ARC_STACK_GUARD_SIZE 136 : * +------------+ <- thread.stack_info.start 137 : * | Kernel | 138 : * | stack | 139 : * | | 140 : * +............| 141 : * | TLS | } thread.stack_info.delta 142 : * +------------+ <- thread.stack_info.start + thread.stack_info.size 143 : */ 144 : #ifdef CONFIG_MPU_STACK_GUARD 145 : #define ARCH_KERNEL_STACK_RESERVED Z_ARC_STACK_GUARD_SIZE 146 : #define ARCH_KERNEL_STACK_OBJ_ALIGN Z_ARC_MPU_ALIGN 147 : #endif 148 : 149 : #ifdef CONFIG_USERSPACE 150 : /* Any thread running In user mode will have full access to the region denoted 151 : * by thread.stack_info. 152 : * 153 : * Thread-local storage is at the very highest memory locations of this area. 154 : * Memory for TLS and any initial random stack pointer offset is captured 155 : * in thread.stack_info.delta. 156 : */ 157 : #ifdef CONFIG_MPU_STACK_GUARD 158 : /* MPU guards are only supported with V3 MPU and later. In this configuration 159 : * the stack object will contain the MPU guard, the privilege stack, and then 160 : * the stack buffer in that order: 161 : * 162 : * +------------+ <- thread.stack_obj 163 : * | Guard | } Z_ARC_STACK_GUARD_SIZE 164 : * +------------+ <- thread.arch.priv_stack_start 165 : * | Priv Stack | } CONFIG_PRIVILEGED_STACK_SIZE 166 : * +------------+ <- thread.stack_info.start 167 : * | Thread | 168 : * | stack | 169 : * | | 170 : * +............| 171 : * | TLS | } thread.stack_info.delta 172 : * +------------+ <- thread.stack_info.start + thread.stack_info.size 173 : */ 174 : #define ARCH_THREAD_STACK_RESERVED (Z_ARC_STACK_GUARD_SIZE + \ 175 : CONFIG_PRIVILEGED_STACK_SIZE) 176 : #define ARCH_THREAD_STACK_OBJ_ALIGN(size) Z_ARC_MPU_ALIGN 177 : /* We need to be able to exactly cover the stack buffer with an MPU region, 178 : * so round its size up to the required granularity of the MPU 179 : */ 180 : #define ARCH_THREAD_STACK_SIZE_ADJUST(size) \ 181 : (ROUND_UP((size), Z_ARC_MPU_ALIGN)) 182 : BUILD_ASSERT(CONFIG_PRIVILEGED_STACK_SIZE % Z_ARC_MPU_ALIGN == 0, 183 : "improper privilege stack size"); 184 : #else /* !CONFIG_MPU_STACK_GUARD */ 185 : /* Userspace enabled, but supervisor stack guards are not in use */ 186 : #ifdef CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT 187 : /* Use defaults for everything. The privilege elevation stack is located 188 : * in another area of memory generated at build time by gen_kobject_list.py 189 : * 190 : * +------------+ <- thread.arch.priv_stack_start 191 : * | Priv Stack | } K_KERNEL_STACK_LEN(CONFIG_PRIVILEGED_STACK_SIZE) 192 : * +------------+ 193 : * 194 : * +------------+ <- thread.stack_obj = thread.stack_info.start 195 : * | Thread | 196 : * | stack | 197 : * | | 198 : * +............| 199 : * | TLS | } thread.stack_info.delta 200 : * +------------+ <- thread.stack_info.start + thread.stack_info.size 201 : */ 202 : #define ARCH_THREAD_STACK_SIZE_ADJUST(size) \ 203 : Z_POW2_CEIL(ROUND_UP((size), Z_ARC_MPU_ALIGN)) 204 : #define ARCH_THREAD_STACK_OBJ_ALIGN(size) \ 205 : ARCH_THREAD_STACK_SIZE_ADJUST(size) 206 : #define ARCH_THREAD_STACK_RESERVED 0 207 : #else /* !CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT */ 208 : /* Reserved area of the thread object just contains the privilege stack: 209 : * 210 : * +------------+ <- thread.stack_obj = thread.arch.priv_stack_start 211 : * | Priv Stack | } CONFIG_PRIVILEGED_STACK_SIZE 212 : * +------------+ <- thread.stack_info.start 213 : * | Thread | 214 : * | stack | 215 : * | | 216 : * +............| 217 : * | TLS | } thread.stack_info.delta 218 : * +------------+ <- thread.stack_info.start + thread.stack_info.size 219 : */ 220 0 : #define ARCH_THREAD_STACK_RESERVED CONFIG_PRIVILEGED_STACK_SIZE 221 0 : #define ARCH_THREAD_STACK_SIZE_ADJUST(size) \ 222 : (ROUND_UP((size), Z_ARC_MPU_ALIGN)) 223 0 : #define ARCH_THREAD_STACK_OBJ_ALIGN(size) Z_ARC_MPU_ALIGN 224 : 225 : BUILD_ASSERT(CONFIG_PRIVILEGED_STACK_SIZE % Z_ARC_MPU_ALIGN == 0, 226 : "improper privilege stack size"); 227 : #endif /* CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT */ 228 : #endif /* CONFIG_MPU_STACK_GUARD */ 229 : 230 : #else /* !CONFIG_USERSPACE */ 231 : 232 : #ifdef CONFIG_MPU_STACK_GUARD 233 : /* Only supported on ARC MPU V3 and higher. Reserve some memory for the stack 234 : * guard. This is just a minimally-sized region at the beginning of the stack 235 : * object, which is programmed to produce an exception if written to. 236 : * 237 : * +------------+ <- thread.stack_obj 238 : * | Guard | } Z_ARC_STACK_GUARD_SIZE 239 : * +------------+ <- thread.stack_info.start 240 : * | Thread | 241 : * | stack | 242 : * | | 243 : * +............| 244 : * | TLS | } thread.stack_info.delta 245 : * +------------+ <- thread.stack_info.start + thread.stack_info.size 246 : */ 247 : #define ARCH_THREAD_STACK_RESERVED Z_ARC_STACK_GUARD_SIZE 248 : #define ARCH_THREAD_STACK_OBJ_ALIGN(size) Z_ARC_MPU_ALIGN 249 : /* Default for ARCH_THREAD_STACK_SIZE_ADJUST */ 250 : #else /* !CONFIG_MPU_STACK_GUARD */ 251 : /* No stack guard, no userspace, Use defaults for everything. */ 252 : #endif /* CONFIG_MPU_STACK_GUARD */ 253 : #endif /* CONFIG_USERSPACE */ 254 : 255 : #ifdef CONFIG_ARC_MPU 256 : 257 : /* Legacy case: retain containing extern "C" with C++ */ 258 : #include <zephyr/arch/arc/v2/mpu/arc_mpu.h> 259 : 260 : #define K_MEM_PARTITION_P_NA_U_NA AUX_MPU_ATTR_N 261 : #define K_MEM_PARTITION_P_RW_U_RW (AUX_MPU_ATTR_UW | AUX_MPU_ATTR_UR | \ 262 : AUX_MPU_ATTR_KW | AUX_MPU_ATTR_KR) 263 : #define K_MEM_PARTITION_P_RW_U_RO (AUX_MPU_ATTR_UR | \ 264 : AUX_MPU_ATTR_KW | AUX_MPU_ATTR_KR) 265 : #define K_MEM_PARTITION_P_RW_U_NA (AUX_MPU_ATTR_KW | AUX_MPU_ATTR_KR) 266 : #define K_MEM_PARTITION_P_RO_U_RO (AUX_MPU_ATTR_UR | AUX_MPU_ATTR_KR) 267 : #define K_MEM_PARTITION_P_RO_U_NA (AUX_MPU_ATTR_KR) 268 : 269 : /* Execution-allowed attributes */ 270 : #define K_MEM_PARTITION_P_RWX_U_RWX (AUX_MPU_ATTR_UW | AUX_MPU_ATTR_UR | \ 271 : AUX_MPU_ATTR_KW | AUX_MPU_ATTR_KR | \ 272 : AUX_MPU_ATTR_KE | AUX_MPU_ATTR_UE) 273 : #define K_MEM_PARTITION_P_RWX_U_RX (AUX_MPU_ATTR_UR | \ 274 : AUX_MPU_ATTR_KW | AUX_MPU_ATTR_KR | \ 275 : AUX_MPU_ATTR_KE | AUX_MPU_ATTR_UE) 276 : #define K_MEM_PARTITION_P_RX_U_RX (AUX_MPU_ATTR_UR | \ 277 : AUX_MPU_ATTR_KR | \ 278 : AUX_MPU_ATTR_KE | AUX_MPU_ATTR_UE) 279 : 280 : #define K_MEM_PARTITION_IS_WRITABLE(attr) \ 281 : ({ \ 282 : int __is_writable__; \ 283 : switch (attr & (AUX_MPU_ATTR_UW | AUX_MPU_ATTR_KW)) { \ 284 : case (AUX_MPU_ATTR_UW | AUX_MPU_ATTR_KW): \ 285 : case AUX_MPU_ATTR_UW: \ 286 : case AUX_MPU_ATTR_KW: \ 287 : __is_writable__ = 1; \ 288 : break; \ 289 : default: \ 290 : __is_writable__ = 0; \ 291 : break; \ 292 : } \ 293 : __is_writable__; \ 294 : }) 295 : #define K_MEM_PARTITION_IS_EXECUTABLE(attr) \ 296 : ((attr) & (AUX_MPU_ATTR_KE | AUX_MPU_ATTR_UE)) 297 : 298 : /* 299 : * BUILD_ASSERT in case of MWDT is a bit more picky in performing compile-time check. 300 : * For example it can't evaluate variable address at build time like GCC toolchain can do. 301 : * That's why we provide custom _ARCH_MEM_PARTITION_ALIGN_CHECK implementation for MWDT toolchain 302 : * with additional check for arguments availability in compile time. 303 : */ 304 : #ifdef __CCAC__ 305 : #define IS_BUILTIN_MWDT(val) __builtin_constant_p((uintptr_t)(val)) 306 : #if CONFIG_ARC_MPU_VER == 2 || CONFIG_ARC_MPU_VER == 3 || CONFIG_ARC_MPU_VER == 6 307 : #define _ARCH_MEM_PARTITION_ALIGN_CHECK(start, size) \ 308 : BUILD_ASSERT(IS_BUILTIN_MWDT(size) ? !((size) & ((size) - 1)) : 1, \ 309 : "partition size must be power of 2"); \ 310 : BUILD_ASSERT(IS_BUILTIN_MWDT(size) ? (size) >= Z_ARC_MPU_ALIGN : 1, \ 311 : "partition size must be >= mpu address alignment."); \ 312 : BUILD_ASSERT(IS_BUILTIN_MWDT(size) ? IS_BUILTIN_MWDT(start) ? \ 313 : !((uintptr_t)(start) & ((size) - 1)) : 1 : 1, \ 314 : "partition start address must align with size.") 315 : #elif CONFIG_ARC_MPU_VER == 4 || CONFIG_ARC_MPU_VER == 8 316 : #define _ARCH_MEM_PARTITION_ALIGN_CHECK(start, size) \ 317 : BUILD_ASSERT(IS_BUILTIN_MWDT(size) ? (size) % Z_ARC_MPU_ALIGN == 0 : 1, \ 318 : "partition size must align with " STRINGIFY(Z_ARC_MPU_ALIGN)); \ 319 : BUILD_ASSERT(IS_BUILTIN_MWDT(size) ? (size) >= Z_ARC_MPU_ALIGN : 1, \ 320 : "partition size must be >= " STRINGIFY(Z_ARC_MPU_ALIGN)); \ 321 : BUILD_ASSERT(IS_BUILTIN_MWDT(start) ? (uintptr_t)(start) % Z_ARC_MPU_ALIGN == 0 : 1, \ 322 : "partition start address must align with " STRINGIFY(Z_ARC_MPU_ALIGN)) 323 : #endif 324 : #else /* __CCAC__ */ 325 : #if CONFIG_ARC_MPU_VER == 2 || CONFIG_ARC_MPU_VER == 3 || CONFIG_ARC_MPU_VER == 6 326 : #define _ARCH_MEM_PARTITION_ALIGN_CHECK(start, size) \ 327 : BUILD_ASSERT(!((size) & ((size) - 1)), \ 328 : "partition size must be power of 2"); \ 329 : BUILD_ASSERT((size) >= Z_ARC_MPU_ALIGN, \ 330 : "partition size must be >= mpu address alignment."); \ 331 : BUILD_ASSERT(!((uintptr_t)(start) & ((size) - 1)), \ 332 : "partition start address must align with size.") 333 : #elif CONFIG_ARC_MPU_VER == 4 || CONFIG_ARC_MPU_VER == 8 334 : #define _ARCH_MEM_PARTITION_ALIGN_CHECK(start, size) \ 335 : BUILD_ASSERT((size) % Z_ARC_MPU_ALIGN == 0, \ 336 : "partition size must align with " STRINGIFY(Z_ARC_MPU_ALIGN)); \ 337 : BUILD_ASSERT((size) >= Z_ARC_MPU_ALIGN, \ 338 : "partition size must be >= " STRINGIFY(Z_ARC_MPU_ALIGN)); \ 339 : BUILD_ASSERT((uintptr_t)(start) % Z_ARC_MPU_ALIGN == 0, \ 340 : "partition start address must align with " STRINGIFY(Z_ARC_MPU_ALIGN)) 341 : #endif 342 : #endif /* __CCAC__ */ 343 : #endif /* CONFIG_ARC_MPU*/ 344 : 345 : /* Typedef for the k_mem_partition attribute*/ 346 0 : typedef uint32_t k_mem_partition_attr_t; 347 : 348 0 : static ALWAYS_INLINE void arch_nop(void) 349 : { 350 : __builtin_arc_nop(); 351 : } 352 : 353 : #ifndef CONFIG_XIP 354 : extern char __arc_rw_sram_size[]; 355 : #endif /* CONFIG_XIP */ 356 : 357 : #endif /* _ASMLANGUAGE */ 358 : 359 : #ifdef __cplusplus 360 : } 361 : #endif 362 : #endif /* ZEPHYR_INCLUDE_ARCH_ARC_ARCH_H_ */