apic_vector.s revision 158236
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: head/sys/i386/i386/apic_vector.s 158236 2006-05-01 21:36:47Z jhb $
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/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	FAKE_MCOUNT(TF_EIP(%esp)) ;					\
60	movl	lapic, %edx ;	/* pointer to local APIC */		\
61	movl	LA_ISR + 16 * (index)(%edx), %eax ;	/* load ISR */	\
62	bsrl	%eax, %eax ;	/* index of highset set bit in ISR */	\
63	jz	2f ;							\
64	addl	$(32 * index),%eax ;					\
651: ;									\
66	pushl	%eax ;		/* pass the IRQ */			\
67	call	lapic_handle_intr ;					\
68	addl	$4, %esp ;	/* discard parameter */			\
69	MEXITCOUNT ;							\
70	jmp	doreti ;						\
712:	movl	$-1, %eax ;	/* send a vector of -1 */		\
72	jmp	1b
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	FAKE_MCOUNT(TF_EIP(%esp))
106
107	call	lapic_handle_timer
108	MEXITCOUNT
109	jmp	doreti
110
111#ifdef SMP
112/*
113 * Global address space TLB shootdown.
114 */
115	.text
116	SUPERALIGN_TEXT
117IDTVEC(invltlb)
118	pushl	%eax
119	pushl	%ds
120	movl	$KDSEL, %eax		/* Kernel data selector */
121	movl	%eax, %ds
122
123#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
124	pushl	%fs
125	movl	$KPSEL, %eax		/* Private space selector */
126	movl	%eax, %fs
127	movl	PCPU(CPUID), %eax
128	popl	%fs
129#ifdef COUNT_XINVLTLB_HITS
130	incl	xhits_gbl(,%eax,4)
131#endif
132#ifdef COUNT_IPIS
133	movl	ipi_invltlb_counts(,%eax,4),%eax
134	incl	(%eax)
135#endif
136#endif
137
138	movl	%cr3, %eax		/* invalidate the TLB */
139	movl	%eax, %cr3
140
141	movl	lapic, %eax
142	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
143
144	lock
145	incl	smp_tlb_wait
146
147	popl	%ds
148	popl	%eax
149	iret
150
151/*
152 * Single page TLB shootdown
153 */
154	.text
155	SUPERALIGN_TEXT
156IDTVEC(invlpg)
157	pushl	%eax
158	pushl	%ds
159	movl	$KDSEL, %eax		/* Kernel data selector */
160	movl	%eax, %ds
161
162#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
163	pushl	%fs
164	movl	$KPSEL, %eax		/* Private space selector */
165	movl	%eax, %fs
166	movl	PCPU(CPUID), %eax
167	popl	%fs
168#ifdef COUNT_XINVLTLB_HITS
169	incl	xhits_pg(,%eax,4)
170#endif
171#ifdef COUNT_IPIS
172	movl	ipi_invlpg_counts(,%eax,4),%eax
173	incl	(%eax)
174#endif
175#endif
176
177	movl	smp_tlb_addr1, %eax
178	invlpg	(%eax)			/* invalidate single page */
179
180	movl	lapic, %eax
181	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
182
183	lock
184	incl	smp_tlb_wait
185
186	popl	%ds
187	popl	%eax
188	iret
189
190/*
191 * Page range TLB shootdown.
192 */
193	.text
194	SUPERALIGN_TEXT
195IDTVEC(invlrng)
196	pushl	%eax
197	pushl	%edx
198	pushl	%ds
199	movl	$KDSEL, %eax		/* Kernel data selector */
200	movl	%eax, %ds
201
202#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
203	pushl	%fs
204	movl	$KPSEL, %eax		/* Private space selector */
205	movl	%eax, %fs
206	movl	PCPU(CPUID), %eax
207	popl	%fs
208#ifdef COUNT_XINVLTLB_HITS
209	incl	xhits_rng(,%eax,4)
210#endif
211#ifdef COUNT_IPIS
212	movl	ipi_invlrng_counts(,%eax,4),%eax
213	incl	(%eax)
214#endif
215#endif
216
217	movl	smp_tlb_addr1, %edx
218	movl	smp_tlb_addr2, %eax
2191:	invlpg	(%edx)			/* invalidate single page */
220	addl	$PAGE_SIZE, %edx
221	cmpl	%eax, %edx
222	jb	1b
223
224	movl	lapic, %eax
225	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
226
227	lock
228	incl	smp_tlb_wait
229
230	popl	%ds
231	popl	%edx
232	popl	%eax
233	iret
234
235/*
236 * Invalidate cache.
237 */
238	.text
239	SUPERALIGN_TEXT
240IDTVEC(invlcache)
241	pushl	%eax
242	pushl	%ds
243	movl	$KDSEL, %eax		/* Kernel data selector */
244	movl	%eax, %ds
245
246#ifdef COUNT_IPIS
247	pushl	%fs
248	movl	$KPSEL, %eax		/* Private space selector */
249	movl	%eax, %fs
250	movl	PCPU(CPUID), %eax
251	popl	%fs
252	movl	ipi_invlcache_counts(,%eax,4),%eax
253	incl	(%eax)
254#endif
255
256	wbinvd
257
258	movl	lapic, %eax
259	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
260
261	lock
262	incl	smp_tlb_wait
263
264	popl	%ds
265	popl	%eax
266	iret
267
268/*
269 * Handler for IPIs sent via the per-cpu IPI bitmap.
270 */
271	.text
272	SUPERALIGN_TEXT
273IDTVEC(ipi_intr_bitmap_handler)
274	PUSH_FRAME
275	SET_KERNEL_SREGS
276
277	movl	lapic, %edx
278	movl	$0, LA_EOI(%edx)	/* End Of Interrupt to APIC */
279
280	FAKE_MCOUNT(TF_EIP(%esp))
281
282	call	ipi_bitmap_handler
283	MEXITCOUNT
284	jmp	doreti
285
286/*
287 * Executed by a CPU when it receives an IPI_STOP from another CPU.
288 */
289	.text
290	SUPERALIGN_TEXT
291IDTVEC(cpustop)
292	PUSH_FRAME
293	SET_KERNEL_SREGS
294
295	movl	lapic, %eax
296	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
297
298	call	cpustop_handler
299
300	POP_FRAME
301	iret
302
303/*
304 * Executed by a CPU when it receives a RENDEZVOUS IPI from another CPU.
305 *
306 * - Calls the generic rendezvous action function.
307 */
308	.text
309	SUPERALIGN_TEXT
310IDTVEC(rendezvous)
311	PUSH_FRAME
312	SET_KERNEL_SREGS
313
314#ifdef COUNT_IPIS
315	movl	PCPU(CPUID), %eax
316	movl	ipi_rendezvous_counts(,%eax,4), %eax
317	incl	(%eax)
318#endif
319	call	smp_rendezvous_action
320
321	movl	lapic, %eax
322	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
323	POP_FRAME
324	iret
325
326/*
327 * Clean up when we lose out on the lazy context switch optimization.
328 * ie: when we are about to release a PTD but a cpu is still borrowing it.
329 */
330	SUPERALIGN_TEXT
331IDTVEC(lazypmap)
332	PUSH_FRAME
333	SET_KERNEL_SREGS
334
335	call	pmap_lazyfix_action
336
337	movl	lapic, %eax
338	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
339	POP_FRAME
340	iret
341#endif /* SMP */
342