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