LCOV - code coverage report
Current view: top level - zephyr/arch/x86 - arch.h Hit Total Coverage
Test: new.info Lines: 0 32 0.0 %
Date: 2025-01-02 12:14:04

          Line data    Source code
       1           0 : /*
       2             :  * Copyright (c) 2019 Intel Corp.
       3             :  * SPDX-License-Identifier: Apache-2.0
       4             :  */
       5             : 
       6             : #ifndef ZEPHYR_INCLUDE_ARCH_X86_ARCH_H_
       7             : #define ZEPHYR_INCLUDE_ARCH_X86_ARCH_H_
       8             : 
       9             : #include <zephyr/devicetree.h>
      10             : 
      11             : /* Changing this value will require manual changes to exception and IDT setup
      12             :  * in locore.S for intel64
      13             :  */
      14             : #define Z_X86_OOPS_VECTOR       32
      15             : 
      16             : #if !defined(_ASMLANGUAGE)
      17             : 
      18             : #include <zephyr/sys/sys_io.h>
      19             : #include <zephyr/types.h>
      20             : #include <stddef.h>
      21             : #include <stdbool.h>
      22             : #include <zephyr/irq.h>
      23             : #include <zephyr/arch/x86/mmustructs.h>
      24             : #include <zephyr/arch/x86/thread_stack.h>
      25             : #include <zephyr/linker/sections.h>
      26             : 
      27             : #ifdef __cplusplus
      28             : extern "C" {
      29             : #endif
      30             : 
      31             : #ifdef CONFIG_PCIE_MSI
      32             : 
      33             : struct x86_msi_vector {
      34             :         unsigned int irq;
      35             :         uint8_t vector;
      36             : #ifdef CONFIG_INTEL_VTD_ICTL
      37             :         bool remap;
      38             :         uint8_t irte;
      39             : #endif
      40             : };
      41             : 
      42             : typedef struct x86_msi_vector arch_msi_vector_t;
      43             : 
      44             : #endif /* CONFIG_PCIE_MSI */
      45             : 
      46           0 : static ALWAYS_INLINE void arch_irq_unlock(unsigned int key)
      47             : {
      48             :         if ((key & 0x00000200U) != 0U) { /* 'IF' bit */
      49             :                 __asm__ volatile ("sti" ::: "memory");
      50             :         }
      51             : }
      52             : 
      53           0 : static ALWAYS_INLINE void sys_out8(uint8_t data, io_port_t port)
      54             : {
      55             :         __asm__ volatile("outb %b0, %w1" :: "a"(data), "Nd"(port));
      56             : }
      57             : 
      58           0 : static ALWAYS_INLINE uint8_t sys_in8(io_port_t port)
      59             : {
      60             :         uint8_t ret;
      61             : 
      62             :         __asm__ volatile("inb %w1, %b0" : "=a"(ret) : "Nd"(port));
      63             : 
      64             :         return ret;
      65             : }
      66             : 
      67           0 : static ALWAYS_INLINE void sys_out16(uint16_t data, io_port_t port)
      68             : {
      69             :         __asm__ volatile("outw %w0, %w1" :: "a"(data), "Nd"(port));
      70             : }
      71             : 
      72           0 : static ALWAYS_INLINE uint16_t sys_in16(io_port_t port)
      73             : {
      74             :         uint16_t ret;
      75             : 
      76             :         __asm__ volatile("inw %w1, %w0" : "=a"(ret) : "Nd"(port));
      77             : 
      78             :         return ret;
      79             : }
      80             : 
      81           0 : static ALWAYS_INLINE void sys_out32(uint32_t data, io_port_t port)
      82             : {
      83             :         __asm__ volatile("outl %0, %w1" :: "a"(data), "Nd"(port));
      84             : }
      85             : 
      86           0 : static ALWAYS_INLINE uint32_t sys_in32(io_port_t port)
      87             : {
      88             :         uint32_t ret;
      89             : 
      90             :         __asm__ volatile("inl %w1, %0" : "=a"(ret) : "Nd"(port));
      91             : 
      92             :         return ret;
      93             : }
      94             : 
      95           0 : static ALWAYS_INLINE void sys_write8(uint8_t data, mm_reg_t addr)
      96             : {
      97             :         __asm__ volatile("movb %0, %1"
      98             :                          :
      99             :                          : "q"(data), "m" (*(volatile uint8_t *)(uintptr_t) addr)
     100             :                          : "memory");
     101             : }
     102             : 
     103           0 : static ALWAYS_INLINE uint8_t sys_read8(mm_reg_t addr)
     104             : {
     105             :         uint8_t ret;
     106             : 
     107             :         __asm__ volatile("movb %1, %0"
     108             :                          : "=q"(ret)
     109             :                          : "m" (*(volatile uint8_t *)(uintptr_t) addr)
     110             :                          : "memory");
     111             : 
     112             :         return ret;
     113             : }
     114             : 
     115           0 : static ALWAYS_INLINE void sys_write16(uint16_t data, mm_reg_t addr)
     116             : {
     117             :         __asm__ volatile("movw %0, %1"
     118             :                          :
     119             :                          : "r"(data), "m" (*(volatile uint16_t *)(uintptr_t) addr)
     120             :                          : "memory");
     121             : }
     122             : 
     123           0 : static ALWAYS_INLINE uint16_t sys_read16(mm_reg_t addr)
     124             : {
     125             :         uint16_t ret;
     126             : 
     127             :         __asm__ volatile("movw %1, %0"
     128             :                          : "=r"(ret)
     129             :                          : "m" (*(volatile uint16_t *)(uintptr_t) addr)
     130             :                          : "memory");
     131             : 
     132             :         return ret;
     133             : }
     134             : 
     135           0 : static ALWAYS_INLINE void sys_write32(uint32_t data, mm_reg_t addr)
     136             : {
     137             :         __asm__ volatile("movl %0, %1"
     138             :                          :
     139             :                          : "r"(data), "m" (*(volatile uint32_t *)(uintptr_t) addr)
     140             :                          : "memory");
     141             : }
     142             : 
     143           0 : static ALWAYS_INLINE uint32_t sys_read32(mm_reg_t addr)
     144             : {
     145             :         uint32_t ret;
     146             : 
     147             :         __asm__ volatile("movl %1, %0"
     148             :                          : "=r"(ret)
     149             :                          : "m" (*(volatile uint32_t *)(uintptr_t) addr)
     150             :                          : "memory");
     151             : 
     152             :         return ret;
     153             : }
     154             : 
     155           0 : static ALWAYS_INLINE void sys_set_bit(mem_addr_t addr, unsigned int bit)
     156             : {
     157             :         __asm__ volatile("btsl %1, %0"
     158             :                          : "+m" (*(volatile uint8_t *) (addr))
     159             :                          : "Ir" (bit)
     160             :                          : "memory");
     161             : }
     162             : 
     163           0 : static ALWAYS_INLINE void sys_clear_bit(mem_addr_t addr, unsigned int bit)
     164             : {
     165             :         __asm__ volatile("btrl %1, %0"
     166             :                          : "+m" (*(volatile uint8_t *) (addr))
     167             :                          : "Ir" (bit));
     168             : }
     169             : 
     170           0 : static ALWAYS_INLINE int sys_test_bit(mem_addr_t addr, unsigned int bit)
     171             : {
     172             :         int ret;
     173             : 
     174             :         __asm__ volatile("btl %2, %1;"
     175             :                          "sbb %0, %0"
     176             :                          : "=r" (ret), "+m" (*(volatile uint8_t *) (addr))
     177             :                          : "Ir" (bit));
     178             : 
     179             :         return ret;
     180             : }
     181             : 
     182           0 : static ALWAYS_INLINE int sys_test_and_set_bit(mem_addr_t addr,
     183             :                                               unsigned int bit)
     184             : {
     185             :         int ret;
     186             : 
     187             :         __asm__ volatile("btsl %2, %1;"
     188             :                          "sbb %0, %0"
     189             :                          : "=r" (ret), "+m" (*(volatile uint8_t *) (addr))
     190             :                          : "Ir" (bit));
     191             : 
     192             :         return ret;
     193             : }
     194             : 
     195           0 : static ALWAYS_INLINE int sys_test_and_clear_bit(mem_addr_t addr,
     196             :                                                 unsigned int bit)
     197             : {
     198             :         int ret;
     199             : 
     200             :         __asm__ volatile("btrl %2, %1;"
     201             :                          "sbb %0, %0"
     202             :                          : "=r" (ret), "+m" (*(volatile uint8_t *) (addr))
     203             :                          : "Ir" (bit));
     204             : 
     205             :         return ret;
     206             : }
     207             : 
     208           0 : #define sys_bitfield_set_bit sys_set_bit
     209           0 : #define sys_bitfield_clear_bit sys_clear_bit
     210           0 : #define sys_bitfield_test_bit sys_test_bit
     211           0 : #define sys_bitfield_test_and_set_bit sys_test_and_set_bit
     212           0 : #define sys_bitfield_test_and_clear_bit sys_test_and_clear_bit
     213             : 
     214             : /*
     215             :  * Map of IRQ numbers to their assigned vectors. On IA32, this is generated
     216             :  * at build time and defined via the linker script. On Intel64, it's an array.
     217             :  */
     218             : 
     219             : extern unsigned char _irq_to_interrupt_vector[CONFIG_MAX_IRQ_LINES];
     220             : 
     221             : #define Z_IRQ_TO_INTERRUPT_VECTOR(irq) \
     222             :         ((unsigned int) _irq_to_interrupt_vector[(irq)])
     223             : 
     224             : 
     225             : #endif /* _ASMLANGUAGE */
     226             : 
     227             : #ifdef __cplusplus
     228             : }
     229             : #endif
     230             : 
     231             : #include <zephyr/drivers/interrupt_controller/sysapic.h>
     232             : 
     233             : #ifdef CONFIG_X86_64
     234             : #include <zephyr/arch/x86/intel64/arch.h>
     235             : #else
     236             : #include <zephyr/arch/x86/ia32/arch.h>
     237             : #endif
     238             : 
     239             : #include <zephyr/arch/common/ffs.h>
     240             : 
     241             : #ifdef __cplusplus
     242             : extern "C" {
     243             : #endif
     244             : 
     245             : #ifndef _ASMLANGUAGE
     246             : 
     247           0 : void arch_irq_enable(unsigned int irq);
     248           0 : void arch_irq_disable(unsigned int irq);
     249             : 
     250           0 : uint32_t sys_clock_cycle_get_32(void);
     251             : 
     252             : __pinned_func
     253           0 : static inline uint32_t arch_k_cycle_get_32(void)
     254             : {
     255             :         return sys_clock_cycle_get_32();
     256             : }
     257             : 
     258           0 : uint64_t sys_clock_cycle_get_64(void);
     259             : 
     260             : __pinned_func
     261           0 : static inline uint64_t arch_k_cycle_get_64(void)
     262             : {
     263             :         return sys_clock_cycle_get_64();
     264             : }
     265             : 
     266           0 : static ALWAYS_INLINE bool arch_irq_unlocked(unsigned int key)
     267             : {
     268             :         return (key & 0x200) != 0;
     269             : }
     270             : 
     271             : /**
     272             :  * @brief read timestamp register, 32-bits only, unserialized
     273             :  */
     274             : 
     275             : static ALWAYS_INLINE uint32_t z_do_read_cpu_timestamp32(void)
     276             : {
     277             :         uint32_t rv;
     278             : 
     279             :         __asm__ volatile("rdtsc" : "=a" (rv) : : "%edx");
     280             : 
     281             :         return rv;
     282             : }
     283             : 
     284             : /**
     285             :  *  @brief read timestamp register ensuring serialization
     286             :  */
     287             : 
     288             : __pinned_func
     289             : static inline uint64_t z_tsc_read(void)
     290             : {
     291             :         union {
     292             :                 struct  {
     293             :                         uint32_t lo;
     294             :                         uint32_t hi;
     295             :                 };
     296             :                 uint64_t  value;
     297             :         }  rv;
     298             : 
     299             : #ifdef CONFIG_X86_64
     300             :         /*
     301             :          * According to Intel 64 and IA-32 Architectures Software
     302             :          * Developer’s Manual, volume 3, chapter 8.2.5, LFENCE provides
     303             :          * a more efficient method of controlling memory ordering than
     304             :          * the CPUID instruction. So use LFENCE here, as all 64-bit
     305             :          * CPUs have LFENCE.
     306             :          */
     307             :         __asm__ volatile ("lfence");
     308             : #else
     309             :         /* rdtsc & cpuid clobbers eax, ebx, ecx and edx registers */
     310             :         __asm__ volatile (/* serialize */
     311             :                 "xorl %%eax,%%eax;"
     312             :                 "cpuid"
     313             :                 :
     314             :                 :
     315             :                 : "%eax", "%ebx", "%ecx", "%edx"
     316             :                 );
     317             : #endif
     318             : 
     319             : #ifdef CONFIG_X86_64
     320             :         /*
     321             :          * We cannot use "=A", since this would use %rax on x86_64 and
     322             :          * return only the lower 32bits of the TSC
     323             :          */
     324             :         __asm__ volatile ("rdtsc" : "=a" (rv.lo), "=d" (rv.hi));
     325             : #else
     326             :         /* "=A" means that value is in eax:edx pair. */
     327             :         __asm__ volatile ("rdtsc" : "=A" (rv.value));
     328             : #endif
     329             : 
     330             :         return rv.value;
     331             : }
     332             : 
     333           0 : static ALWAYS_INLINE void arch_nop(void)
     334             : {
     335             :         __asm__ volatile("nop");
     336             : }
     337             : 
     338             : #endif /* _ASMLANGUAGE */
     339             : 
     340             : #ifdef __cplusplus
     341             : }
     342             : #endif
     343             : 
     344             : #endif /* ZEPHYR_INCLUDE_ARCH_X86_ARCH_H_ */

Generated by: LCOV version 1.14