apic_vector.s revision 208507
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 208507 2010-05-24 15:45:05Z 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	%esp		;                                       \
67	pushl	%eax ;		/* pass the IRQ */			\
68	call	lapic_handle_intr ;					\
69	addl	$8, %esp ;	/* discard parameter */			\
70	MEXITCOUNT ;							\
71	jmp	doreti ;						\
722:	movl	$-1, %eax ;	/* send a vector of -1 */		\
73	jmp	1b
74
75/*
76 * Handle "spurious INTerrupts".
77 * Notes:
78 *  This is different than the "spurious INTerrupt" generated by an
79 *   8259 PIC for missing INTs.  See the APIC documentation for details.
80 *  This routine should NOT do an 'EOI' cycle.
81 */
82	.text
83	SUPERALIGN_TEXT
84IDTVEC(spuriousint)
85
86	/* No EOI cycle used here */
87
88	iret
89
90	ISR_VEC(1, apic_isr1)
91	ISR_VEC(2, apic_isr2)
92	ISR_VEC(3, apic_isr3)
93	ISR_VEC(4, apic_isr4)
94	ISR_VEC(5, apic_isr5)
95	ISR_VEC(6, apic_isr6)
96	ISR_VEC(7, apic_isr7)
97
98/*
99 * Local APIC periodic timer handler.
100 */
101	.text
102	SUPERALIGN_TEXT
103IDTVEC(timerint)
104	PUSH_FRAME
105	SET_KERNEL_SREGS
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	FAKE_MCOUNT(TF_EIP(%esp))
122	call	lapic_handle_cmc
123	MEXITCOUNT
124	jmp	doreti
125
126/*
127 * Local APIC error interrupt handler.
128 */
129	.text
130	SUPERALIGN_TEXT
131IDTVEC(errorint)
132	PUSH_FRAME
133	SET_KERNEL_SREGS
134	FAKE_MCOUNT(TF_EIP(%esp))
135	call	lapic_handle_error
136	MEXITCOUNT
137	jmp	doreti
138
139#ifdef SMP
140/*
141 * Global address space TLB shootdown.
142 */
143	.text
144	SUPERALIGN_TEXT
145IDTVEC(invltlb)
146	pushl	%eax
147	pushl	%ds
148	movl	$KDSEL, %eax		/* Kernel data selector */
149	movl	%eax, %ds
150
151#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
152	pushl	%fs
153	movl	$KPSEL, %eax		/* Private space selector */
154	movl	%eax, %fs
155	movl	PCPU(CPUID), %eax
156	popl	%fs
157#ifdef COUNT_XINVLTLB_HITS
158	incl	xhits_gbl(,%eax,4)
159#endif
160#ifdef COUNT_IPIS
161	movl	ipi_invltlb_counts(,%eax,4),%eax
162	incl	(%eax)
163#endif
164#endif
165
166	movl	%cr3, %eax		/* invalidate the TLB */
167	movl	%eax, %cr3
168
169	movl	lapic, %eax
170	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
171
172	lock
173	incl	smp_tlb_wait
174
175	popl	%ds
176	popl	%eax
177	iret
178
179/*
180 * Single page TLB shootdown
181 */
182	.text
183	SUPERALIGN_TEXT
184IDTVEC(invlpg)
185	pushl	%eax
186	pushl	%ds
187	movl	$KDSEL, %eax		/* Kernel data selector */
188	movl	%eax, %ds
189
190#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
191	pushl	%fs
192	movl	$KPSEL, %eax		/* Private space selector */
193	movl	%eax, %fs
194	movl	PCPU(CPUID), %eax
195	popl	%fs
196#ifdef COUNT_XINVLTLB_HITS
197	incl	xhits_pg(,%eax,4)
198#endif
199#ifdef COUNT_IPIS
200	movl	ipi_invlpg_counts(,%eax,4),%eax
201	incl	(%eax)
202#endif
203#endif
204
205	movl	smp_tlb_addr1, %eax
206	invlpg	(%eax)			/* invalidate single page */
207
208	movl	lapic, %eax
209	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
210
211	lock
212	incl	smp_tlb_wait
213
214	popl	%ds
215	popl	%eax
216	iret
217
218/*
219 * Page range TLB shootdown.
220 */
221	.text
222	SUPERALIGN_TEXT
223IDTVEC(invlrng)
224	pushl	%eax
225	pushl	%edx
226	pushl	%ds
227	movl	$KDSEL, %eax		/* Kernel data selector */
228	movl	%eax, %ds
229
230#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
231	pushl	%fs
232	movl	$KPSEL, %eax		/* Private space selector */
233	movl	%eax, %fs
234	movl	PCPU(CPUID), %eax
235	popl	%fs
236#ifdef COUNT_XINVLTLB_HITS
237	incl	xhits_rng(,%eax,4)
238#endif
239#ifdef COUNT_IPIS
240	movl	ipi_invlrng_counts(,%eax,4),%eax
241	incl	(%eax)
242#endif
243#endif
244
245	movl	smp_tlb_addr1, %edx
246	movl	smp_tlb_addr2, %eax
2471:	invlpg	(%edx)			/* invalidate single page */
248	addl	$PAGE_SIZE, %edx
249	cmpl	%eax, %edx
250	jb	1b
251
252	movl	lapic, %eax
253	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
254
255	lock
256	incl	smp_tlb_wait
257
258	popl	%ds
259	popl	%edx
260	popl	%eax
261	iret
262
263/*
264 * Invalidate cache.
265 */
266	.text
267	SUPERALIGN_TEXT
268IDTVEC(invlcache)
269	pushl	%eax
270	pushl	%ds
271	movl	$KDSEL, %eax		/* Kernel data selector */
272	movl	%eax, %ds
273
274#ifdef COUNT_IPIS
275	pushl	%fs
276	movl	$KPSEL, %eax		/* Private space selector */
277	movl	%eax, %fs
278	movl	PCPU(CPUID), %eax
279	popl	%fs
280	movl	ipi_invlcache_counts(,%eax,4),%eax
281	incl	(%eax)
282#endif
283
284	wbinvd
285
286	movl	lapic, %eax
287	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
288
289	lock
290	incl	smp_tlb_wait
291
292	popl	%ds
293	popl	%eax
294	iret
295
296/*
297 * Handler for IPIs sent via the per-cpu IPI bitmap.
298 */
299#ifndef XEN
300	.text
301	SUPERALIGN_TEXT
302IDTVEC(ipi_intr_bitmap_handler)
303	PUSH_FRAME
304	SET_KERNEL_SREGS
305
306	movl	lapic, %edx
307	movl	$0, LA_EOI(%edx)	/* End Of Interrupt to APIC */
308
309	FAKE_MCOUNT(TF_EIP(%esp))
310
311	call	ipi_bitmap_handler
312	MEXITCOUNT
313	jmp	doreti
314#endif
315/*
316 * Executed by a CPU when it receives an IPI_STOP from another CPU.
317 */
318	.text
319	SUPERALIGN_TEXT
320IDTVEC(cpustop)
321	PUSH_FRAME
322	SET_KERNEL_SREGS
323
324	movl	lapic, %eax
325	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
326
327	call	cpustop_handler
328
329	POP_FRAME
330	iret
331
332/*
333 * Executed by a CPU when it receives a RENDEZVOUS IPI from another CPU.
334 *
335 * - Calls the generic rendezvous action function.
336 */
337	.text
338	SUPERALIGN_TEXT
339IDTVEC(rendezvous)
340	PUSH_FRAME
341	SET_KERNEL_SREGS
342
343#ifdef COUNT_IPIS
344	movl	PCPU(CPUID), %eax
345	movl	ipi_rendezvous_counts(,%eax,4), %eax
346	incl	(%eax)
347#endif
348	call	smp_rendezvous_action
349
350	movl	lapic, %eax
351	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
352	POP_FRAME
353	iret
354
355/*
356 * Clean up when we lose out on the lazy context switch optimization.
357 * ie: when we are about to release a PTD but a cpu is still borrowing it.
358 */
359	SUPERALIGN_TEXT
360IDTVEC(lazypmap)
361	PUSH_FRAME
362	SET_KERNEL_SREGS
363
364	call	pmap_lazyfix_action
365
366	movl	lapic, %eax
367	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
368	POP_FRAME
369	iret
370#endif /* SMP */
371