LCOV - code coverage report
Current view: top level - zephyr/arch/xtensa - arch.h Hit Total Coverage
Test: new.info Lines: 10 13 76.9 %
Date: 2024-12-22 00:14:23

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

Generated by: LCOV version 1.14