LCOV - code coverage report
Current view: top level - zephyr/arch/xtensa - arch.h Coverage Total Hit
Test: new.info Lines: 71.4 % 14 10
Test Date: 2025-09-05 16:43:28

            Line data    Source code
       1            1 : /*
       2              :  * Copyright (c) 2016 Cadence Design Systems, Inc.
       3              :  * SPDX-License-Identifier: Apache-2.0
       4              :  */
       5              : 
       6              : /**
       7              :  * @file
       8              :  * @brief Xtensa specific kernel interface header
       9              :  *
      10              :  * This header contains the Xtensa specific kernel interface.  It is
      11              :  * included by the kernel interface architecture-abstraction header
      12              :  * (include/zephyr/arch/cpu.h).
      13              :  */
      14              : 
      15              : #ifndef ZEPHYR_INCLUDE_ARCH_XTENSA_ARCH_H_
      16              : #define ZEPHYR_INCLUDE_ARCH_XTENSA_ARCH_H_
      17              : 
      18              : #include <zephyr/irq.h>
      19              : 
      20              : #include <zephyr/devicetree.h>
      21              : #if !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__)
      22              : #include <zephyr/types.h>
      23              : #include <zephyr/toolchain.h>
      24              : #include <zephyr/arch/common/sys_bitops.h>
      25              : #include <zephyr/arch/common/sys_io.h>
      26              : #include <zephyr/arch/common/ffs.h>
      27              : #include <zephyr/sw_isr_table.h>
      28              : #include <zephyr/arch/xtensa/syscall.h>
      29              : #include <zephyr/arch/xtensa/thread.h>
      30              : #include <zephyr/arch/xtensa/irq.h>
      31              : #include <xtensa/config/core.h>
      32              : #include <zephyr/arch/common/addr_types.h>
      33              : #include <zephyr/arch/xtensa/gdbstub.h>
      34              : #include <zephyr/debug/sparse.h>
      35              : #include <zephyr/arch/xtensa/thread_stack.h>
      36              : #include <zephyr/sys/slist.h>
      37              : 
      38              : #include <zephyr/drivers/timer/system_timer.h>
      39              : 
      40              : #ifdef CONFIG_XTENSA_MMU
      41              : #include <zephyr/arch/xtensa/xtensa_mmu.h>
      42              : #endif
      43              : 
      44              : #ifdef CONFIG_XTENSA_MPU
      45              : #include <zephyr/arch/xtensa/mpu.h>
      46              : #endif
      47              : 
      48              : /**
      49              :  * @defgroup xtensa_apis Xtensa APIs
      50              :  * @ingroup arch-interface
      51              :  * @{
      52              :  * @}
      53              :  *
      54              :  * @defgroup xtensa_internal_apis Xtensa Internal APIs
      55              :  * @ingroup xtensa_apis
      56              :  * @{
      57              :  * @}
      58              :  */
      59              : 
      60              : #include <zephyr/arch/exception.h>
      61              : 
      62              : #ifdef __cplusplus
      63              : extern "C" {
      64              : #endif
      65              : 
      66              : struct arch_mem_domain {
      67              : #ifdef CONFIG_XTENSA_MMU
      68              :         uint32_t *ptables;
      69              :         uint8_t asid;
      70              :         bool dirty;
      71              : 
      72              :         /* Following are used to program registers when changing page tables. */
      73              :         uint32_t reg_asid;
      74              :         uint32_t reg_ptevaddr;
      75              :         uint32_t reg_ptepin_as;
      76              :         uint32_t reg_ptepin_at;
      77              :         uint32_t reg_vecpin_as;
      78              :         uint32_t reg_vecpin_at;
      79              : #endif
      80              : #ifdef CONFIG_XTENSA_MPU
      81              :         struct xtensa_mpu_map mpu_map;
      82              : #endif
      83              :         sys_snode_t node;
      84              : };
      85              : 
      86            0 : typedef struct arch_mem_domain arch_mem_domain_t;
      87              : 
      88              : /**
      89              :  * @brief Generate hardware exception.
      90              :  *
      91              :  * This generates hardware exception which is used by ARCH_EXCEPT().
      92              :  *
      93              :  * @param reason_p Reason for exception.
      94              :  */
      95            1 : void xtensa_arch_except(int reason_p);
      96              : 
      97              : /**
      98              :  * @brief Generate kernel oops.
      99              :  *
     100              :  * This generates kernel oops which is used by arch_syscall_oops().
     101              :  *
     102              :  * @param reason_p Reason for exception.
     103              :  * @param ssf Stack pointer.
     104              :  */
     105            1 : void xtensa_arch_kernel_oops(int reason_p, void *ssf);
     106              : 
     107              : #ifdef CONFIG_USERSPACE
     108              : 
     109            0 : #define ARCH_EXCEPT(reason_p) do { \
     110              :         if (k_is_user_context()) { \
     111              :                 arch_syscall_invoke1(reason_p, \
     112              :                         K_SYSCALL_XTENSA_USER_FAULT); \
     113              :         } else { \
     114              :                 xtensa_arch_except(reason_p); \
     115              :         } \
     116              :         CODE_UNREACHABLE; \
     117              : } while (false)
     118              : 
     119              : #else
     120              : 
     121              : #define ARCH_EXCEPT(reason_p) do { \
     122              :                 xtensa_arch_except(reason_p); \
     123              :                 CODE_UNREACHABLE; \
     124              :         } while (false)
     125              : 
     126              : #endif
     127              : 
     128            0 : __syscall void xtensa_user_fault(unsigned int reason);
     129              : 
     130              : #include <zephyr/syscalls/arch.h>
     131              : 
     132              : /* internal routine documented in C file, needed by IRQ_CONNECT() macro */
     133              : void z_irq_priority_set(uint32_t irq, uint32_t prio, uint32_t flags);
     134              : 
     135            0 : #define ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \
     136              :         { \
     137              :                 Z_ISR_DECLARE(irq_p, flags_p, isr_p, isr_param_p); \
     138              :         }
     139              : 
     140              : /** Implementation of @ref arch_k_cycle_get_32. */
     141            1 : static inline uint32_t arch_k_cycle_get_32(void)
     142              : {
     143              :         return sys_clock_cycle_get_32();
     144              : }
     145              : 
     146              : /** Implementation of @ref arch_k_cycle_get_64. */
     147            1 : static inline uint64_t arch_k_cycle_get_64(void)
     148              : {
     149              :         return sys_clock_cycle_get_64();
     150              : }
     151              : 
     152              : /** Implementation of @ref arch_nop. */
     153            1 : static ALWAYS_INLINE void arch_nop(void)
     154              : {
     155              :         __asm__ volatile("nop");
     156              : }
     157              : 
     158              : /**
     159              :  * @brief Lock VECBASE if supported by hardware.
     160              :  *
     161              :  * The bit 0 of VECBASE acts as a lock bit on hardware supporting
     162              :  * this feature. When this bit is set, VECBASE cannot be changed
     163              :  * until it is cleared by hardware reset. When the hardware does not
     164              :  * support this bit, it is hardwired to 0.
     165              :  */
     166            1 : static ALWAYS_INLINE void xtensa_vecbase_lock(void)
     167              : {
     168              :         int vecbase;
     169              : 
     170              :         __asm__ volatile("rsr.vecbase %0" : "=r" (vecbase));
     171              :         __asm__ volatile("wsr.vecbase %0; rsync" : : "r" (vecbase | 1));
     172              : }
     173              : 
     174              : #if defined(CONFIG_XTENSA_RPO_CACHE) || defined(__DOXYGEN__)
     175              : #if defined(CONFIG_ARCH_HAS_COHERENCE) || defined(__DOXYGEN__)
     176              : /** Implementation of @ref arch_mem_coherent. */
     177            1 : static inline bool arch_mem_coherent(void *ptr)
     178              : {
     179              :         size_t addr = (size_t) ptr;
     180              : 
     181              :         return (addr >> 29) == CONFIG_XTENSA_UNCACHED_REGION;
     182              : }
     183              : #endif
     184              : 
     185              : 
     186              : /* Utility to generate an unrolled and optimal[1] code sequence to set
     187              :  * the RPO TLB registers (contra the HAL cacheattr macros, which
     188              :  * generate larger code and can't be called from C), based on the
     189              :  * KERNEL_COHERENCE configuration in use.  Selects RPO attribute "2"
     190              :  * for regions (including MMIO registers in region zero) which want to
     191              :  * bypass L1, "4" for the cached region which wants writeback, and
     192              :  * "15" (invalid) elsewhere.
     193              :  *
     194              :  * Note that on cores that have the "translation" option set, we need
     195              :  * to put an identity mapping in the high bits.  Also per spec
     196              :  * changing the current code region (by definition cached) requires
     197              :  * that WITLB be followed by an ISYNC and that both instructions live
     198              :  * in the same cache line (two 3-byte instructions fit in an 8-byte
     199              :  * aligned region, so that's guaranteed not to cross a cache line
     200              :  * boundary).
     201              :  *
     202              :  * [1] With the sole exception of gcc's infuriating insistence on
     203              :  * emitting a precomputed literal for addr + addrincr instead of
     204              :  * computing it with a single ADD instruction from values it already
     205              :  * has in registers.  Explicitly assigning the variables to registers
     206              :  * via an attribute works, but then emits needless MOV instructions
     207              :  * instead.  I tell myself it's just 32 bytes of .text, but... Sigh.
     208              :  */
     209              : #define _REGION_ATTR(r)                                         \
     210              :         ((r) == 0 ? 2 :                                         \
     211              :          ((r) == CONFIG_XTENSA_CACHED_REGION ? 4 :              \
     212              :           ((r) == CONFIG_XTENSA_UNCACHED_REGION ? 2 : 15)))
     213              : 
     214              : #define _SET_ONE_TLB(region) do {                               \
     215              :         uint32_t attr = _REGION_ATTR(region);                   \
     216              :         if (XCHAL_HAVE_XLT_CACHEATTR) {                         \
     217              :                 attr |= addr; /* RPO with translation */        \
     218              :         }                                                       \
     219              :         if (region != CONFIG_XTENSA_CACHED_REGION) {            \
     220              :                 __asm__ volatile("wdtlb %0, %1; witlb %0, %1" \
     221              :                                  :: "r"(attr), "r"(addr));  \
     222              :         } else {                                                \
     223              :                 __asm__ volatile("wdtlb %0, %1"                       \
     224              :                                  :: "r"(attr), "r"(addr));  \
     225              :                 __asm__ volatile("j 1f; .align 8; 1:");               \
     226              :                 __asm__ volatile("witlb %0, %1; isync"                \
     227              :                                  :: "r"(attr), "r"(addr));  \
     228              :         }                                                       \
     229              :         addr += addrincr;                                       \
     230              : } while (0)
     231              : 
     232              : /**
     233              :  * @brief Setup RPO TLB registers.
     234              :  */
     235            1 : #define ARCH_XTENSA_SET_RPO_TLB()                                       \
     236              :         do {                                                            \
     237              :                 register uint32_t addr = 0, addrincr = 0x20000000;      \
     238              :                 FOR_EACH(_SET_ONE_TLB, (;), 0, 1, 2, 3, 4, 5, 6, 7);    \
     239              :         } while (0)
     240              : #endif /* CONFIG_XTENSA_RPO_CACHE */
     241              : 
     242              : #if defined(CONFIG_XTENSA_MMU) || defined(__DOXYGEN__)
     243              : /**
     244              :  * @brief Perform additional steps after MMU initialization.
     245              :  *
     246              :  * This performs additional steps related to memory management
     247              :  * after the main MMU initialization code. This needs to defined
     248              :  * in the SoC layer. Default is do no nothing.
     249              :  *
     250              :  * @param is_core0 True if this is called while executing on
     251              :  *                 CPU core #0.
     252              :  */
     253            1 : void arch_xtensa_mmu_post_init(bool is_core0);
     254              : #endif
     255              : 
     256              : #ifdef __cplusplus
     257              : }
     258              : #endif
     259              : 
     260              : #endif /* !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__)  */
     261              : 
     262              : #endif /* ZEPHYR_INCLUDE_ARCH_XTENSA_ARCH_H_ */
        

Generated by: LCOV version 2.0-1