Line data Source code
1 0 : /* loapic.h - public LOAPIC APIs */
2 :
3 : /*
4 : * Copyright (c) 2015 Wind River Systems, Inc.
5 : *
6 : * SPDX-License-Identifier: Apache-2.0
7 : */
8 :
9 : #ifndef ZEPHYR_INCLUDE_DRIVERS_LOAPIC_H_
10 : #define ZEPHYR_INCLUDE_DRIVERS_LOAPIC_H_
11 :
12 : #include <zephyr/arch/cpu.h>
13 : #include <zephyr/arch/x86/msr.h>
14 : #include <zephyr/sys/device_mmio.h>
15 :
16 : /* Local APIC Register Offset */
17 :
18 0 : #define LOAPIC_ID 0x020 /* Local APIC ID Reg */
19 0 : #define LOAPIC_VER 0x030 /* Local APIC Version Reg */
20 0 : #define LOAPIC_TPR 0x080 /* Task Priority Reg */
21 0 : #define LOAPIC_APR 0x090 /* Arbitration Priority Reg */
22 0 : #define LOAPIC_PPR 0x0a0 /* Processor Priority Reg */
23 0 : #define LOAPIC_EOI 0x0b0 /* EOI Reg */
24 0 : #define LOAPIC_LDR 0x0d0 /* Logical Destination Reg */
25 0 : #define LOAPIC_DFR 0x0e0 /* Destination Format Reg */
26 0 : #define LOAPIC_SVR 0x0f0 /* Spurious Interrupt Reg */
27 0 : #define LOAPIC_ISR 0x100 /* In-service Reg */
28 0 : #define LOAPIC_TMR 0x180 /* Trigger Mode Reg */
29 0 : #define LOAPIC_IRR 0x200 /* Interrupt Request Reg */
30 0 : #define LOAPIC_ESR 0x280 /* Error Status Reg */
31 0 : #define LOAPIC_ICRLO 0x300 /* Interrupt Command Reg */
32 0 : #define LOAPIC_ICRHI 0x310 /* Interrupt Command Reg */
33 0 : #define LOAPIC_TIMER 0x320 /* LVT (Timer) */
34 0 : #define LOAPIC_THERMAL 0x330 /* LVT (Thermal) */
35 0 : #define LOAPIC_PMC 0x340 /* LVT (PMC) */
36 0 : #define LOAPIC_LINT0 0x350 /* LVT (LINT0) */
37 0 : #define LOAPIC_LINT1 0x360 /* LVT (LINT1) */
38 0 : #define LOAPIC_ERROR 0x370 /* LVT (ERROR) */
39 0 : #define LOAPIC_TIMER_ICR 0x380 /* Timer Initial Count Reg */
40 0 : #define LOAPIC_TIMER_CCR 0x390 /* Timer Current Count Reg */
41 0 : #define LOAPIC_TIMER_CONFIG 0x3e0 /* Timer Divide Config Reg */
42 0 : #define LOAPIC_SELF_IPI 0x3f0 /* Self IPI Reg, only support in X2APIC mode */
43 :
44 0 : #define LOAPIC_ICR_BUSY 0x00001000 /* delivery status: 1 = busy */
45 :
46 0 : #define LOAPIC_ICR_IPI_SPECIFIC 0x00004000U /* target IPI to specific CPU */
47 0 : #define LOAPIC_ICR_IPI_OTHERS 0x000C4000U /* normal IPI to other CPUs */
48 0 : #define LOAPIC_ICR_IPI_INIT 0x00004500U
49 0 : #define LOAPIC_ICR_IPI_STARTUP 0x00004600U
50 :
51 0 : #define LOAPIC_LVT_MASKED 0x00010000 /* mask */
52 :
53 : /* Defined in intc_loapic.c */
54 0 : #define LOAPIC_REGS_STR loapic_regs /* mmio device name */
55 :
56 : #ifndef _ASMLANGUAGE
57 :
58 : #ifdef __cplusplus
59 : extern "C" {
60 : #endif
61 :
62 0 : DEVICE_MMIO_TOPLEVEL_DECLARE(LOAPIC_REGS_STR);
63 :
64 : uint32_t z_loapic_irq_base(void);
65 : void z_loapic_enable(unsigned char cpu_number);
66 : void z_loapic_int_vec_set(unsigned int irq, unsigned int vector);
67 : void z_loapic_irq_enable(unsigned int irq);
68 : void z_loapic_irq_disable(unsigned int irq);
69 :
70 : /**
71 : * @brief Read 64-bit value from the local APIC in x2APIC mode.
72 : *
73 : * @param reg the LOAPIC register number to read (LOAPIC_*)
74 : */
75 1 : static inline uint64_t x86_read_x2apic(unsigned int reg)
76 : {
77 : reg >>= 4;
78 : return z_x86_msr_read(X86_X2APIC_BASE_MSR + reg);
79 : }
80 :
81 : /**
82 : * @brief Read 32-bit value from the local APIC in xAPIC (MMIO) mode.
83 : *
84 : * @param reg the LOAPIC register number to read (LOAPIC_*)
85 : */
86 1 : static inline uint32_t x86_read_xapic(unsigned int reg)
87 : {
88 : mm_reg_t base;
89 : base = DEVICE_MMIO_TOPLEVEL_GET(LOAPIC_REGS_STR);
90 : return sys_read32(base + reg);
91 : }
92 :
93 : /**
94 : * @brief Read value from the local APIC using the default mode.
95 : *
96 : * Returns a 32-bit value read from the local APIC, using the access
97 : * method determined by CONFIG_X2APIC (either xAPIC or x2APIC). Note
98 : * that 64-bit reads are only allowed in x2APIC mode and can only be
99 : * done by calling x86_read_x2apic() directly. (This is intentional.)
100 : *
101 : * @param reg the LOAPIC register number to read (LOAPIC_*)
102 : */
103 1 : static inline uint32_t x86_read_loapic(unsigned int reg)
104 : {
105 : #ifdef CONFIG_X2APIC
106 : return x86_read_x2apic(reg);
107 : #else
108 : return x86_read_xapic(reg);
109 : #endif
110 : }
111 :
112 : /**
113 : * @brief Write 64-bit value to the local APIC in x2APIC mode.
114 : *
115 : * @param reg the LOAPIC register number to write (one of LOAPIC_*)
116 : * @param val 64-bit value to write
117 : */
118 1 : static inline void x86_write_x2apic(unsigned int reg, uint64_t val)
119 : {
120 : reg >>= 4;
121 : z_x86_msr_write(X86_X2APIC_BASE_MSR + reg, val);
122 : }
123 :
124 : /**
125 : * @brief Write 32-bit value to the local APIC in xAPIC (MMIO) mode.
126 : *
127 : * @param reg the LOAPIC register number to write (one of LOAPIC_*)
128 : * @param val 32-bit value to write
129 : */
130 1 : static inline void x86_write_xapic(unsigned int reg, uint32_t val)
131 : {
132 : mm_reg_t base;
133 : base = DEVICE_MMIO_TOPLEVEL_GET(LOAPIC_REGS_STR);
134 : sys_write32(val, base + reg);
135 : }
136 :
137 : /**
138 : * @brief Write 32-bit value to the local APIC using the default mode.
139 : *
140 : * Write a 32-bit value to the local APIC, using the access method
141 : * determined by CONFIG_X2APIC (either xAPIC or x2APIC). Note that
142 : * 64-bit writes are only available in x2APIC mode and can only be
143 : * done by calling x86_write_x2apic() directly. (This is intentional.)
144 : *
145 : * @param reg the LOAPIC register number to write (one of LOAPIC_*)
146 : * @param val 32-bit value to write
147 : */
148 1 : static inline void x86_write_loapic(unsigned int reg, uint32_t val)
149 : {
150 : #ifdef CONFIG_X2APIC
151 : x86_write_x2apic(reg, val);
152 : #else
153 : x86_write_xapic(reg, val);
154 : #endif
155 : }
156 :
157 : /**
158 : * @brief Send an IPI.
159 : *
160 : * @param apic_id If applicable, the target CPU APIC ID (0 otherwise).
161 : * @param ipi Type of IPI: one of the LOAPIC_ICR_IPI_* constants.
162 : * @param vector If applicable, the target vector (0 otherwise).
163 : */
164 : static inline void z_loapic_ipi(uint8_t apic_id, uint32_t ipi, uint8_t vector)
165 : {
166 : ipi |= vector;
167 :
168 : #ifndef CONFIG_X2APIC
169 : /*
170 : * Legacy xAPIC mode: first wait for any previous IPI to be delivered.
171 : */
172 :
173 : while (x86_read_xapic(LOAPIC_ICRLO) & LOAPIC_ICR_BUSY) {
174 : }
175 :
176 : x86_write_xapic(LOAPIC_ICRHI, apic_id << 24);
177 : x86_write_xapic(LOAPIC_ICRLO, ipi);
178 : #else
179 : /*
180 : * x2APIC mode is greatly simplified: one write, no delivery status.
181 : */
182 :
183 : x86_write_x2apic(LOAPIC_ICRLO, (((uint64_t) apic_id) << 32) | ipi);
184 : #endif
185 : }
186 :
187 : #ifdef __cplusplus
188 : }
189 : #endif
190 :
191 : #endif /* _ASMLANGUAGE */
192 :
193 : #endif /* ZEPHYR_INCLUDE_DRIVERS_LOAPIC_H_ */
|