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