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 * 3. 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 <machine/psl.h>
43#include <machine/specialreg.h>
44#include <x86/apicreg.h>
45
46#include "assym.inc"
47
48	.text
49	SUPERALIGN_TEXT
50	/* End Of Interrupt to APIC */
51as_lapic_eoi:
52	cmpl	$0,x2apic_mode
53	jne	1f
54	movl	lapic_map,%eax
55	movl	$0,LA_EOI(%eax)
56	ret
571:
58	movl	$MSR_APIC_EOI,%ecx
59	xorl	%eax,%eax
60	xorl	%edx,%edx
61	wrmsr
62	ret
63
64/*
65 * I/O Interrupt Entry Point.  Rather than having one entry point for
66 * each interrupt source, we use one entry point for each 32-bit word
67 * in the ISR.  The handler determines the highest bit set in the ISR,
68 * translates that into a vector, and passes the vector to the
69 * lapic_handle_intr() function.
70 */
71	.macro	ISR_VEC	index, vec_name
72	.text
73	SUPERALIGN_TEXT
74	.globl	X\()\vec_name\()_pti, X\()\vec_name
75
76X\()\vec_name\()_pti:
77X\()\vec_name:
78	PUSH_FRAME
79	SET_KERNEL_SREGS
80	cld
81	KENTER
82	FAKE_MCOUNT(TF_EIP(%esp))
83	cmpl	$0,x2apic_mode
84	je	2f
85	movl	$(MSR_APIC_ISR0 + \index),%ecx
86	rdmsr
87	jmp	3f
882:
89	movl	lapic_map, %edx		/* pointer to local APIC */
90	movl	LA_ISR + 16 * \index(%edx), %eax	/* load ISR */
913:
92	bsrl	%eax, %eax	/* index of highest set bit in ISR */
93	jz	4f
94	addl	$(32 * \index),%eax
95	pushl	%esp
96	pushl	%eax		/* pass the IRQ */
97	movl	$lapic_handle_intr, %eax
98	call	*%eax
99	addl	$8, %esp	/* discard parameter */
1004:
101	MEXITCOUNT
102	jmp	doreti
103	.endm
104
105/*
106 * Handle "spurious INTerrupts".
107 * Notes:
108 *  This is different than the "spurious INTerrupt" generated by an
109 *   8259 PIC for missing INTs.  See the APIC documentation for details.
110 *  This routine should NOT do an 'EOI' cycle.
111 */
112	.text
113	SUPERALIGN_TEXT
114IDTVEC(spuriousint)
115
116	/* No EOI cycle used here */
117
118	iret
119
120	ISR_VEC	1, apic_isr1
121	ISR_VEC	2, apic_isr2
122	ISR_VEC	3, apic_isr3
123	ISR_VEC	4, apic_isr4
124	ISR_VEC	5, apic_isr5
125	ISR_VEC	6, apic_isr6
126	ISR_VEC	7, apic_isr7
127
128/*
129 * Local APIC periodic timer handler.
130 */
131	.text
132	SUPERALIGN_TEXT
133IDTVEC(timerint_pti)
134IDTVEC(timerint)
135	PUSH_FRAME
136	SET_KERNEL_SREGS
137	cld
138	KENTER
139	FAKE_MCOUNT(TF_EIP(%esp))
140	pushl	%esp
141	movl	$lapic_handle_timer, %eax
142	call	*%eax
143	add	$4, %esp
144	MEXITCOUNT
145	jmp	doreti
146
147/*
148 * Local APIC CMCI handler.
149 */
150	.text
151	SUPERALIGN_TEXT
152IDTVEC(cmcint_pti)
153IDTVEC(cmcint)
154	PUSH_FRAME
155	SET_KERNEL_SREGS
156	cld
157	KENTER
158	FAKE_MCOUNT(TF_EIP(%esp))
159	movl	$lapic_handle_cmc, %eax
160	call	*%eax
161	MEXITCOUNT
162	jmp	doreti
163
164/*
165 * Local APIC error interrupt handler.
166 */
167	.text
168	SUPERALIGN_TEXT
169IDTVEC(errorint_pti)
170IDTVEC(errorint)
171	PUSH_FRAME
172	SET_KERNEL_SREGS
173	cld
174	KENTER
175	FAKE_MCOUNT(TF_EIP(%esp))
176	movl	$lapic_handle_error, %eax
177	call	*%eax
178	MEXITCOUNT
179	jmp	doreti
180
181#ifdef XENHVM
182/*
183 * Xen event channel upcall interrupt handler.
184 * Only used when the hypervisor supports direct vector callbacks.
185 */
186	.text
187	SUPERALIGN_TEXT
188IDTVEC(xen_intr_upcall)
189	PUSH_FRAME
190	SET_KERNEL_SREGS
191	cld
192	KENTER
193	FAKE_MCOUNT(TF_EIP(%esp))
194	pushl	%esp
195	movl	$xen_intr_handle_upcall, %eax
196	call	*%eax
197	add	$4, %esp
198	MEXITCOUNT
199	jmp	doreti
200#endif
201
202#ifdef SMP
203/*
204 * Global address space TLB shootdown.
205 */
206	.text
207	SUPERALIGN_TEXT
208invltlb_ret:
209	call	as_lapic_eoi
210	jmp	doreti
211
212	SUPERALIGN_TEXT
213IDTVEC(invltlb)
214	PUSH_FRAME
215	SET_KERNEL_SREGS
216	cld
217	KENTER
218	movl	$invltlb_handler, %eax
219	call	*%eax
220	jmp	invltlb_ret
221
222/*
223 * Single page TLB shootdown
224 */
225	.text
226	SUPERALIGN_TEXT
227IDTVEC(invlpg)
228	PUSH_FRAME
229	SET_KERNEL_SREGS
230	cld
231	KENTER
232	movl	$invlpg_handler, %eax
233	call	*%eax
234	jmp	invltlb_ret
235
236/*
237 * Page range TLB shootdown.
238 */
239	.text
240	SUPERALIGN_TEXT
241IDTVEC(invlrng)
242	PUSH_FRAME
243	SET_KERNEL_SREGS
244	cld
245	KENTER
246	movl	$invlrng_handler, %eax
247	call	*%eax
248	jmp	invltlb_ret
249
250/*
251 * Invalidate cache.
252 */
253	.text
254	SUPERALIGN_TEXT
255IDTVEC(invlcache)
256	PUSH_FRAME
257	SET_KERNEL_SREGS
258	cld
259	KENTER
260	movl	$invlcache_handler, %eax
261	call	*%eax
262	jmp	invltlb_ret
263
264/*
265 * Handler for IPIs sent via the per-cpu IPI bitmap.
266 */
267	.text
268	SUPERALIGN_TEXT
269IDTVEC(ipi_intr_bitmap_handler)
270	PUSH_FRAME
271	SET_KERNEL_SREGS
272	cld
273	KENTER
274	call	as_lapic_eoi
275	FAKE_MCOUNT(TF_EIP(%esp))
276	movl	$ipi_bitmap_handler, %eax
277	call	*%eax
278	MEXITCOUNT
279	jmp	doreti
280
281/*
282 * Executed by a CPU when it receives an IPI_STOP from another CPU.
283 */
284	.text
285	SUPERALIGN_TEXT
286IDTVEC(cpustop)
287	PUSH_FRAME
288	SET_KERNEL_SREGS
289	cld
290	KENTER
291	call	as_lapic_eoi
292	movl	$cpustop_handler, %eax
293	call	*%eax
294	jmp	doreti
295
296/*
297 * Executed by a CPU when it receives an IPI_SUSPEND from another CPU.
298 */
299	.text
300	SUPERALIGN_TEXT
301IDTVEC(cpususpend)
302	PUSH_FRAME
303	SET_KERNEL_SREGS
304	cld
305	KENTER
306	call	as_lapic_eoi
307	movl	$cpususpend_handler, %eax
308	call	*%eax
309	jmp	doreti
310
311/*
312 * Executed by a CPU when it receives an IPI_SWI.
313 */
314	.text
315	SUPERALIGN_TEXT
316IDTVEC(ipi_swi)
317	PUSH_FRAME
318	SET_KERNEL_SREGS
319	cld
320	KENTER
321	call	as_lapic_eoi
322	FAKE_MCOUNT(TF_EIP(%esp))
323	movl	$ipi_swi_handler, %eax
324	call	*%eax
325	MEXITCOUNT
326	jmp	doreti
327
328/*
329 * Executed by a CPU when it receives a RENDEZVOUS IPI from another CPU.
330 *
331 * - Calls the generic rendezvous action function.
332 */
333	.text
334	SUPERALIGN_TEXT
335IDTVEC(rendezvous)
336	PUSH_FRAME
337	SET_KERNEL_SREGS
338	cld
339	KENTER
340#ifdef COUNT_IPIS
341	movl	PCPU(CPUID), %eax
342	movl	ipi_rendezvous_counts(,%eax,4), %eax
343	incl	(%eax)
344#endif
345	movl	$smp_rendezvous_action, %eax
346	call	*%eax
347	call	as_lapic_eoi
348	jmp	doreti
349
350#endif /* SMP */
351