LCOV - code coverage report
Current view: top level - zephyr/arch/arc - arch.h Coverage Total Hit
Test: new.info Lines: 14.3 % 7 1
Test Date: 2025-09-05 16:43:28

            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/zephyr/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/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 2.0-1