apic_vector.s revision 153135
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 153135 2005-12-05 21:44: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
106	movl	lapic, %edx
107	movl	$0, LA_EOI(%edx)	/* End Of Interrupt to APIC */
108
109	FAKE_MCOUNT(TF_EIP(%esp))
110
111	pushl	$0		/* XXX convert trapframe to clockframe */
112	call	lapic_handle_timer
113	addl	$4, %esp	/* XXX convert clockframe to trapframe */
114	MEXITCOUNT
115	jmp	doreti
116
117#ifdef SMP
118/*
119 * Global address space TLB shootdown.
120 */
121	.text
122	SUPERALIGN_TEXT
123IDTVEC(invltlb)
124	pushl	%eax
125	pushl	%ds
126	movl	$KDSEL, %eax		/* Kernel data selector */
127	movl	%eax, %ds
128
129#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
130	pushl	%fs
131	movl	$KPSEL, %eax		/* Private space selector */
132	movl	%eax, %fs
133	movl	PCPU(CPUID), %eax
134	popl	%fs
135#ifdef COUNT_XINVLTLB_HITS
136	incl	xhits_gbl(,%eax,4)
137#endif
138#ifdef COUNT_IPIS
139	movl	ipi_invltlb_counts(,%eax,4),%eax
140	incl	(%eax)
141#endif
142#endif
143
144	movl	%cr3, %eax		/* invalidate the TLB */
145	movl	%eax, %cr3
146
147	movl	lapic, %eax
148	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
149
150	lock
151	incl	smp_tlb_wait
152
153	popl	%ds
154	popl	%eax
155	iret
156
157/*
158 * Single page TLB shootdown
159 */
160	.text
161	SUPERALIGN_TEXT
162IDTVEC(invlpg)
163	pushl	%eax
164	pushl	%ds
165	movl	$KDSEL, %eax		/* Kernel data selector */
166	movl	%eax, %ds
167
168#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
169	pushl	%fs
170	movl	$KPSEL, %eax		/* Private space selector */
171	movl	%eax, %fs
172	movl	PCPU(CPUID), %eax
173	popl	%fs
174#ifdef COUNT_XINVLTLB_HITS
175	incl	xhits_pg(,%eax,4)
176#endif
177#ifdef COUNT_IPIS
178	movl	ipi_invlpg_counts(,%eax,4),%eax
179	incl	(%eax)
180#endif
181#endif
182
183	movl	smp_tlb_addr1, %eax
184	invlpg	(%eax)			/* invalidate single page */
185
186	movl	lapic, %eax
187	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
188
189	lock
190	incl	smp_tlb_wait
191
192	popl	%ds
193	popl	%eax
194	iret
195
196/*
197 * Page range TLB shootdown.
198 */
199	.text
200	SUPERALIGN_TEXT
201IDTVEC(invlrng)
202	pushl	%eax
203	pushl	%edx
204	pushl	%ds
205	movl	$KDSEL, %eax		/* Kernel data selector */
206	movl	%eax, %ds
207
208#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
209	pushl	%fs
210	movl	$KPSEL, %eax		/* Private space selector */
211	movl	%eax, %fs
212	movl	PCPU(CPUID), %eax
213	popl	%fs
214#ifdef COUNT_XINVLTLB_HITS
215	incl	xhits_rng(,%eax,4)
216#endif
217#ifdef COUNT_IPIS
218	movl	ipi_invlrng_counts(,%eax,4),%eax
219	incl	(%eax)
220#endif
221#endif
222
223	movl	smp_tlb_addr1, %edx
224	movl	smp_tlb_addr2, %eax
2251:	invlpg	(%edx)			/* invalidate single page */
226	addl	$PAGE_SIZE, %edx
227	cmpl	%eax, %edx
228	jb	1b
229
230	movl	lapic, %eax
231	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
232
233	lock
234	incl	smp_tlb_wait
235
236	popl	%ds
237	popl	%edx
238	popl	%eax
239	iret
240
241/*
242 * Forward hardclock to another CPU.  Pushes a clockframe and calls
243 * forwarded_hardclock().
244 */
245	.text
246	SUPERALIGN_TEXT
247IDTVEC(ipi_intr_bitmap_handler)
248	PUSH_FRAME
249	SET_KERNEL_SREGS
250
251	movl	lapic, %edx
252	movl	$0, LA_EOI(%edx)	/* End Of Interrupt to APIC */
253
254	FAKE_MCOUNT(TF_EIP(%esp))
255
256	pushl	$0		/* XXX convert trapframe to clockframe */
257	call	ipi_bitmap_handler
258	addl	$4, %esp	/* XXX convert clockframe to trapframe */
259	MEXITCOUNT
260	jmp	doreti
261
262/*
263 * Executed by a CPU when it receives an Xcpustop IPI from another CPU,
264 *
265 *  - Signals its receipt.
266 *  - Waits for permission to restart.
267 *  - Signals its restart.
268 */
269	.text
270	SUPERALIGN_TEXT
271IDTVEC(cpustop)
272	PUSH_FRAME
273	SET_KERNEL_SREGS
274
275	movl	lapic, %eax
276	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
277
278	movl	PCPU(CPUID), %eax
279	imull	$PCB_SIZE, %eax
280	leal	CNAME(stoppcbs)(%eax), %eax
281	pushl	%eax
282	call	CNAME(savectx)		/* Save process context */
283	addl	$4, %esp
284
285	movl	PCPU(CPUID), %eax
286
287	lock
288	btsl	%eax, CNAME(stopped_cpus) /* stopped_cpus |= (1<<id) */
2891:
290	btl	%eax, CNAME(started_cpus) /* while (!(started_cpus & (1<<id))) */
291	jnc	1b
292
293	lock
294	btrl	%eax, CNAME(started_cpus) /* started_cpus &= ~(1<<id) */
295	lock
296	btrl	%eax, CNAME(stopped_cpus) /* stopped_cpus &= ~(1<<id) */
297
298	test	%eax, %eax
299	jnz	2f
300
301	movl	CNAME(cpustop_restartfunc), %eax
302	test	%eax, %eax
303	jz	2f
304	movl	$0, CNAME(cpustop_restartfunc)	/* One-shot */
305
306	call	*%eax
3072:
308	POP_FRAME
309	iret
310
311/*
312 * Executed by a CPU when it receives a RENDEZVOUS IPI from another CPU.
313 *
314 * - Calls the generic rendezvous action function.
315 */
316	.text
317	SUPERALIGN_TEXT
318IDTVEC(rendezvous)
319	PUSH_FRAME
320	SET_KERNEL_SREGS
321
322#ifdef COUNT_IPIS
323	movl	PCPU(CPUID), %eax
324	movl	ipi_rendezvous_counts(,%eax,4), %eax
325	incl	(%eax)
326#endif
327	call	smp_rendezvous_action
328
329	movl	lapic, %eax
330	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
331	POP_FRAME
332	iret
333
334/*
335 * Clean up when we lose out on the lazy context switch optimization.
336 * ie: when we are about to release a PTD but a cpu is still borrowing it.
337 */
338	SUPERALIGN_TEXT
339IDTVEC(lazypmap)
340	PUSH_FRAME
341	SET_KERNEL_SREGS
342
343#ifdef COUNT_IPIS
344	movl	PCPU(CPUID), %eax
345	movl	ipi_lazypmap_counts(,%eax,4), %eax
346	incl	(%eax)
347#endif
348	call	pmap_lazyfix_action
349
350	movl	lapic, %eax
351	movl	$0, LA_EOI(%eax)	/* End Of Interrupt to APIC */
352	POP_FRAME
353	iret
354#endif /* SMP */
355