1 /*-
2 * Copyright (c) 1989, 1990 William F. Jolitz.
3 * Copyright (c) 1990 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 4. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * from: vector.s, 386BSD 0.1 unknown origin
31 * $FreeBSD$
32 */
33
34 /*
35 * Interrupt entry points for external interrupts triggered by I/O APICs
36 * as well as IPI handlers.
37 */
38
39 #include "opt_smp.h"
40
41 #include <machine/asmacros.h>
42 #include <x86/apicreg.h>
43
44 #include "assym.s"
45
46 #ifdef SMP
47 #define LK lock ;
48 #else
49 #define LK
50 #endif
51
52 /*
53 * I/O Interrupt Entry Point. Rather than having one entry point for
54 * each interrupt source, we use one entry point for each 32-bit word
55 * in the ISR. The handler determines the highest bit set in the ISR,
56 * translates that into a vector, and passes the vector to the
57 * lapic_handle_intr() function.
58 */
59 #define ISR_VEC(index, vec_name) \
60 .text ; \
61 SUPERALIGN_TEXT ; \
62 IDTVEC(vec_name) ; \
63 PUSH_FRAME ; \
64 FAKE_MCOUNT(TF_RIP(%rsp)) ; \
65 movq lapic, %rdx ; /* pointer to local APIC */ \
66 movl LA_ISR + 16 * (index)(%rdx), %eax ; /* load ISR */ \
67 bsrl %eax, %eax ; /* index of highest set bit in ISR */ \
68 jz 1f ; \
69 addl $(32 * index),%eax ; \
70 movq %rsp, %rsi ; \
71 movl %eax, %edi ; /* pass the IRQ */ \
72 call lapic_handle_intr ; \
73 1: ; \
74 MEXITCOUNT ; \
75 jmp doreti
76
77 /*
78 * Handle "spurious INTerrupts".
79 * Notes:
80 * This is different than the "spurious INTerrupt" generated by an
81 * 8259 PIC for missing INTs. See the APIC documentation for details.
82 * This routine should NOT do an 'EOI' cycle.
83 */
84 .text
85 SUPERALIGN_TEXT
86 IDTVEC(spuriousint)
87
88 /* No EOI cycle used here */
89
90 jmp doreti_iret
91
92 ISR_VEC(1, apic_isr1)
93 ISR_VEC(2, apic_isr2)
94 ISR_VEC(3, apic_isr3)
95 ISR_VEC(4, apic_isr4)
96 ISR_VEC(5, apic_isr5)
97 ISR_VEC(6, apic_isr6)
98 ISR_VEC(7, apic_isr7)
99
100 /*
101 * Local APIC periodic timer handler.
102 */
103 .text
104 SUPERALIGN_TEXT
105 IDTVEC(timerint)
106 PUSH_FRAME
107 FAKE_MCOUNT(TF_RIP(%rsp))
108 movq %rsp, %rdi
109 call lapic_handle_timer
110 MEXITCOUNT
111 jmp doreti
112
113 /*
114 * Local APIC CMCI handler.
115 */
116 .text
117 SUPERALIGN_TEXT
118 IDTVEC(cmcint)
119 PUSH_FRAME
120 FAKE_MCOUNT(TF_RIP(%rsp))
121 call lapic_handle_cmc
122 MEXITCOUNT
123 jmp doreti
124
125 /*
126 * Local APIC error interrupt handler.
127 */
128 .text
129 SUPERALIGN_TEXT
130 IDTVEC(errorint)
131 PUSH_FRAME
132 FAKE_MCOUNT(TF_RIP(%rsp))
133 call lapic_handle_error
134 MEXITCOUNT
135 jmp doreti
136
137 #ifdef XENHVM
138 /*
139 * Xen event channel upcall interrupt handler.
140 * Only used when the hypervisor supports direct vector callbacks.
141 */
142 .text
143 SUPERALIGN_TEXT
144 IDTVEC(xen_intr_upcall)
145 PUSH_FRAME
146 FAKE_MCOUNT(TF_RIP(%rsp))
147 movq %rsp, %rdi
148 call xen_intr_handle_upcall
149 MEXITCOUNT
150 jmp doreti
151 #endif
152
153 #ifdef SMP
154 /*
155 * Global address space TLB shootdown.
156 */
157 .text
158
159 SUPERALIGN_TEXT
160 invltlb_ret:
161 movq lapic, %rax
162 movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */
163 POP_FRAME
164 jmp doreti_iret
165
166 SUPERALIGN_TEXT
167 IDTVEC(invltlb_pcid)
168 PUSH_FRAME
169
170 call invltlb_pcid_handler
171 jmp invltlb_ret
172
173
174 SUPERALIGN_TEXT
175 IDTVEC(invltlb)
176 PUSH_FRAME
177
178 call invltlb_handler
179 jmp invltlb_ret
180
181 /*
182 * Single page TLB shootdown
183 */
184 .text
185 SUPERALIGN_TEXT
186 IDTVEC(invlpg_pcid)
187 PUSH_FRAME
188
189 call invlpg_pcid_handler
190 jmp invltlb_ret
191
192 SUPERALIGN_TEXT
193 IDTVEC(invlpg)
194 PUSH_FRAME
195
196 call invlpg_handler
197 jmp invltlb_ret
198
199 /*
200 * Page range TLB shootdown.
201 */
202 .text
203 SUPERALIGN_TEXT
204 IDTVEC(invlrng)
205 PUSH_FRAME
206
207 call invlrng_handler
208 jmp invltlb_ret
209
210 /*
211 * Invalidate cache.
212 */
213 .text
214 SUPERALIGN_TEXT
215 IDTVEC(invlcache)
216 PUSH_FRAME
217
218 call invlcache_handler
219 jmp invltlb_ret
220
221 /*
222 * Handler for IPIs sent via the per-cpu IPI bitmap.
223 */
224 .text
225 SUPERALIGN_TEXT
226 IDTVEC(ipi_intr_bitmap_handler)
227 PUSH_FRAME
228
229 movq lapic, %rdx
230 movl $0, LA_EOI(%rdx) /* End Of Interrupt to APIC */
231
232 FAKE_MCOUNT(TF_RIP(%rsp))
233
234 call ipi_bitmap_handler
235 MEXITCOUNT
236 jmp doreti
237
238 /*
239 * Executed by a CPU when it receives an IPI_STOP from another CPU.
240 */
241 .text
242 SUPERALIGN_TEXT
243 IDTVEC(cpustop)
244 PUSH_FRAME
245
246 movq lapic, %rax
247 movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */
248
249 call cpustop_handler
250 jmp doreti
251
252 /*
253 * Executed by a CPU when it receives an IPI_SUSPEND from another CPU.
254 */
255 .text
256 SUPERALIGN_TEXT
257 IDTVEC(cpususpend)
258 PUSH_FRAME
259
260 call cpususpend_handler
261 movq lapic, %rax
262 movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */
263 jmp doreti
264
265 /*
266 * Executed by a CPU when it receives a RENDEZVOUS IPI from another CPU.
267 *
268 * - Calls the generic rendezvous action function.
269 */
270 .text
271 SUPERALIGN_TEXT
272 IDTVEC(rendezvous)
273 PUSH_FRAME
274 #ifdef COUNT_IPIS
275 movl PCPU(CPUID), %eax
276 movq ipi_rendezvous_counts(,%rax,8), %rax
277 incq (%rax)
278 #endif
279 call smp_rendezvous_action
280 movq lapic, %rax
281 movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */
282 jmp doreti
283 #endif /* SMP */
Cache object: 7c5beca9386055d8875c8b58fdb50826
|