LCOV - code coverage report
Current view: top level - zephyr/arch/arc - arch.h Hit Total Coverage
Test: new.info Lines: 1 7 14.3 %
Date: 2024-12-22 00:14:23

          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_ */

Generated by: LCOV version 1.14