xref: /openbsd/sys/arch/i386/i386/apicvec.s (revision 404b540a)
1/* $OpenBSD: apicvec.s,v 1.20 2009/08/10 16:40:50 oga Exp $ */
2/* $NetBSD: apicvec.s,v 1.1.2.2 2000/02/21 21:54:01 sommerfeld Exp $ */
3
4/*-
5 * Copyright (c) 2000 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by RedBack Networks Inc.
10 *
11 * Author: Bill Sommerfeld
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 *    notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 *    notice, this list of conditions and the following disclaimer in the
20 *    documentation and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include <machine/i82093reg.h>
36#include <machine/i82489reg.h>
37
38#ifdef __ELF__
39#define XINTR(vec) Xintr##vec
40#else
41#define XINTR(vec) _Xintr##vec
42#endif
43
44	.globl  _C_LABEL(apic_stray)
45
46#ifdef MULTIPROCESSOR
47	.globl	XINTR(ipi)
48XINTR(ipi):
49	pushl	$0
50	pushl	$T_ASTFLT
51	INTRENTRY
52	MAKE_FRAME
53	pushl	CPL
54	movl	_C_LABEL(lapic_ppr),%eax
55	movl	%eax,CPL
56	ioapic_asm_ack()
57	sti			/* safe to take interrupts.. */
58	call	_C_LABEL(i386_ipi_handler)
59	cli
60	popl	CPL
61	INTRFASTEXIT
62
63	.globl	XINTR(ipi_invltlb)
64	.p2align 4,0x90
65XINTR(ipi_invltlb):
66	pushl	%eax
67	pushl	%ds
68	movl	$GSEL(GDATA_SEL, SEL_KPL), %eax
69	movl	%eax, %ds
70
71	ioapic_asm_ack()
72
73	movl	%cr3, %eax
74	movl	%eax, %cr3
75
76	lock
77	decl	tlb_shoot_wait
78
79	popl	%ds
80	popl	%eax
81	iret
82
83	.globl	XINTR(ipi_invlpg)
84	.p2align 4,0x90
85XINTR(ipi_invlpg):
86	pushl	%eax
87	pushl	%ds
88	movl	$GSEL(GDATA_SEL, SEL_KPL), %eax
89	movl	%eax, %ds
90
91	ioapic_asm_ack()
92
93	movl	tlb_shoot_addr1, %eax
94	invlpg	(%eax)
95
96	lock
97	decl	tlb_shoot_wait
98
99	popl	%ds
100	popl	%eax
101	iret
102
103	.globl	XINTR(ipi_invlrange)
104	.p2align 4,0x90
105XINTR(ipi_invlrange):
106	pushl	%eax
107	pushl	%edx
108	pushl	%ds
109	movl	$GSEL(GDATA_SEL, SEL_KPL), %eax
110	movl	%eax, %ds
111
112	ioapic_asm_ack()
113
114	movl	tlb_shoot_addr1, %eax
115	movl	tlb_shoot_addr2, %edx
1161:	invlpg	(%eax)
117	addl	$PAGE_SIZE, %eax
118	cmpl	%edx, %eax
119	jb	1b
120
121	lock
122	decl	tlb_shoot_wait
123
124	popl	%ds
125	popl	%edx
126	popl	%eax
127	iret
128
129	.globl	XINTR(ipi_reloadcr3)
130	.p2align 4,0x90
131XINTR(ipi_reloadcr3):
132	pushl	%eax
133	pushl	%ds
134	movl	$GSEL(GDATA_SEL, SEL_KPL), %eax
135	movl	%eax, %ds
136	pushl	%fs
137	movl	$GSEL(GCPU_SEL, SEL_KPL),%eax
138	movw	%ax,%fs
139
140	ioapic_asm_ack()
141
142	movl	CPUVAR(CURPCB), %eax
143	movl	PCB_PMAP(%eax), %eax
144	movl	%eax, CPUVAR(CURPMAP)
145	movl	PM_PDIRPA(%eax), %eax
146	movl	%eax, %cr3
147
148	lock
149	decl	tlb_shoot_wait
150
151	popl	%fs
152	popl	%ds
153	popl	%eax
154	iret
155
156#endif
157
158	/*
159	 * Interrupt from the local APIC timer.
160	 */
161	.globl	XINTR(ltimer)
162XINTR(ltimer):
163	pushl	$0
164	pushl	$T_ASTFLT
165	INTRENTRY
166	MAKE_FRAME
167	pushl	CPL
168	movl	_C_LABEL(lapic_ppr),%eax
169	movl	%eax,CPL
170	ioapic_asm_ack()
171	sti
172	incl	CPUVAR(IDEPTH)
173#ifdef MULTIPROCESSOR
174	call	_C_LABEL(i386_softintlock)
175#endif
176	movl	%esp,%eax
177	pushl	%eax
178	call	_C_LABEL(lapic_clockintr)
179	addl	$4,%esp
180#ifdef MULTIPROCESSOR
181	call	_C_LABEL(i386_softintunlock)
182#endif
183	decl	CPUVAR(IDEPTH)
184	jmp	_C_LABEL(Xdoreti)
185
186	.globl	XINTR(softclock), XINTR(softnet), XINTR(softtty)
187XINTR(softclock):
188	pushl	$0
189	pushl	$T_ASTFLT
190	INTRENTRY
191	MAKE_FRAME
192	pushl	CPL
193	movl	$IPL_SOFTCLOCK,CPL
194	andl	$~(1<<SIR_CLOCK),CPUVAR(IPENDING)
195	ioapic_asm_ack()
196	sti
197	incl	CPUVAR(IDEPTH)
198#ifdef MULTIPROCESSOR
199	call	_C_LABEL(i386_softintlock)
200#endif
201	pushl	$I386_SOFTINTR_SOFTCLOCK
202	call	_C_LABEL(softintr_dispatch)
203	addl	$4,%esp
204#ifdef MULTIPROCESSOR
205	call	_C_LABEL(i386_softintunlock)
206#endif
207	decl	CPUVAR(IDEPTH)
208	jmp	_C_LABEL(Xdoreti)
209
210#define DONETISR(s, c) \
211	.globl  _C_LABEL(c)	;\
212	testl	$(1 << s),%edi	;\
213	jz	1f		;\
214	call	_C_LABEL(c)	;\
2151:
216
217XINTR(softnet):
218	pushl	$0
219	pushl	$T_ASTFLT
220	INTRENTRY
221	MAKE_FRAME
222	pushl	CPL
223	movl	$IPL_SOFTNET,CPL
224	andl	$~(1<<SIR_NET),CPUVAR(IPENDING)
225	ioapic_asm_ack()
226	sti
227	incl	CPUVAR(IDEPTH)
228#ifdef MULTIPROCESSOR
229	call	_C_LABEL(i386_softintlock)
230#endif
231	xorl	%edi,%edi
232	xchgl	_C_LABEL(netisr),%edi
233
234#include <net/netisr_dispatch.h>
235
236	pushl	$I386_SOFTINTR_SOFTNET
237	call	_C_LABEL(softintr_dispatch)
238	addl	$4,%esp
239#ifdef MULTIPROCESSOR
240	call	_C_LABEL(i386_softintunlock)
241#endif
242	decl	CPUVAR(IDEPTH)
243	jmp	_C_LABEL(Xdoreti)
244#undef DONETISR
245
246XINTR(softtty):
247	pushl	$0
248	pushl	$T_ASTFLT
249	INTRENTRY
250	MAKE_FRAME
251	pushl	CPL
252	movl	$IPL_SOFTTTY,CPL
253	andl	$~(1<<SIR_TTY),CPUVAR(IPENDING)
254	ioapic_asm_ack()
255	sti
256	incl	CPUVAR(IDEPTH)
257#ifdef MULTIPROCESSOR
258	call	_C_LABEL(i386_softintlock)
259#endif
260	pushl	$I386_SOFTINTR_SOFTTTY
261	call	_C_LABEL(softintr_dispatch)
262	addl	$4,%esp
263#ifdef MULTIPROCESSOR
264	call	_C_LABEL(i386_softintunlock)
265#endif
266	decl	CPUVAR(IDEPTH)
267	jmp	_C_LABEL(Xdoreti)
268
269#if NIOAPIC > 0
270
271#define voidop(num)
272
273	/*
274	 * I/O APIC interrupt.
275	 * We sort out which one is which based on the value of
276	 * the processor priority register.
277	 *
278	 * XXX use cmove when appropriate.
279	 */
280
281#define APICINTR(name, num, early_ack, late_ack, mask, unmask, level_mask) \
282_C_LABEL(Xintr_##name##num):						\
283	pushl	$0							;\
284	pushl	$T_ASTFLT						;\
285	INTRENTRY							;\
286	MAKE_FRAME							;\
287	pushl	CPL							;\
288	movl	_C_LABEL(lapic_ppr),%eax				;\
289	orl	$num,%eax						;\
290	movl	_C_LABEL(apic_maxlevel)(,%eax,4),%ebx			;\
291	movl	%ebx,CPL						;\
292	mask(num)			/* mask it in hardware */	;\
293	early_ack(num)			/* and allow other intrs */	;\
294	incl	MY_COUNT+V_INTR		/* statistical info */		;\
295	sti								;\
296	incl	_C_LABEL(apic_intrcount)(,%eax,4)			;\
297	movl	_C_LABEL(apic_intrhand)(,%eax,4),%ebx /* chain head */	;\
298	testl	%ebx,%ebx						;\
299	jz      _C_LABEL(Xstray_##name##num)				;\
300	APIC_STRAY_INIT			/* nobody claimed it yet */	;\
3017:									 \
302	LOCK_KERNEL(IF_PPL(%esp))					;\
303	movl	IH_ARG(%ebx),%eax	/* get handler arg */		;\
304	testl	%eax,%eax						;\
305	jnz	6f							;\
306	movl	%esp,%eax		/* 0 means frame pointer */	;\
3076:									 \
308	pushl	%eax							;\
309	call	*IH_FUN(%ebx)		/* call it */			;\
310	addl	$4,%esp			/* toss the arg */		;\
311	APIC_STRAY_INTEGRATE		/* maybe he claimed it */	;\
312	orl	%eax,%eax		/* should it be counted? */	;\
313	jz	4f							;\
314	addl	$1,IH_COUNT(%ebx)	/* count the intrs */		;\
315	adcl	$0,IH_COUNT+4(%ebx)					;\
3164:									 \
317	UNLOCK_KERNEL(IF_PPL(%esp))					;\
318	movl	IH_NEXT(%ebx),%ebx	/* next handler in chain */	;\
319	testl	%ebx,%ebx						;\
320	jnz	7b							;\
321	APIC_STRAY_TEST(name,num)	/* see if it's a stray */	;\
3228:									 \
323	unmask(num)			/* unmask it in hardware */	;\
324	late_ack(num)							;\
325	jmp	_C_LABEL(Xdoreti)					;\
326_C_LABEL(Xstray_##name##num):					 \
327	pushl	$num							;\
328	call	_C_LABEL(apic_stray)					;\
329	addl	$4,%esp							;\
330	jmp	8b							;\
331
332#if defined(DEBUG)
333#define APIC_STRAY_INIT \
334	xorl	%esi,%esi
335#define	APIC_STRAY_INTEGRATE \
336	orl	%eax,%esi
337#define APIC_STRAY_TEST(name,num) \
338	testl 	%esi,%esi						;\
339	jz 	_C_LABEL(Xstray_##name##num)
340#else /* !DEBUG */
341#define APIC_STRAY_INIT
342#define APIC_STRAY_INTEGRATE
343#define APIC_STRAY_TEST(name,num)
344#endif /* DEBUG */
345
346APICINTR(ioapic,0, voidop, ioapic_asm_ack, voidop, voidop, voidop)
347APICINTR(ioapic,1, voidop, ioapic_asm_ack, voidop, voidop, voidop)
348APICINTR(ioapic,2, voidop, ioapic_asm_ack, voidop, voidop, voidop)
349APICINTR(ioapic,3, voidop, ioapic_asm_ack, voidop, voidop, voidop)
350APICINTR(ioapic,4, voidop, ioapic_asm_ack, voidop, voidop, voidop)
351APICINTR(ioapic,5, voidop, ioapic_asm_ack, voidop, voidop, voidop)
352APICINTR(ioapic,6, voidop, ioapic_asm_ack, voidop, voidop, voidop)
353APICINTR(ioapic,7, voidop, ioapic_asm_ack, voidop, voidop, voidop)
354APICINTR(ioapic,8, voidop, ioapic_asm_ack, voidop, voidop, voidop)
355APICINTR(ioapic,9, voidop, ioapic_asm_ack, voidop, voidop, voidop)
356APICINTR(ioapic,10, voidop, ioapic_asm_ack, voidop, voidop, voidop)
357APICINTR(ioapic,11, voidop, ioapic_asm_ack, voidop, voidop, voidop)
358APICINTR(ioapic,12, voidop, ioapic_asm_ack, voidop, voidop, voidop)
359APICINTR(ioapic,13, voidop, ioapic_asm_ack, voidop, voidop, voidop)
360APICINTR(ioapic,14, voidop, ioapic_asm_ack, voidop, voidop, voidop)
361APICINTR(ioapic,15, voidop, ioapic_asm_ack, voidop, voidop, voidop)
362
363	.globl	_C_LABEL(Xintr_ioapic0),_C_LABEL(Xintr_ioapic1)
364	.globl	_C_LABEL(Xintr_ioapic2),_C_LABEL(Xintr_ioapic3)
365	.globl	_C_LABEL(Xintr_ioapic4),_C_LABEL(Xintr_ioapic5)
366	.globl	_C_LABEL(Xintr_ioapic6),_C_LABEL(Xintr_ioapic7)
367	.globl	_C_LABEL(Xintr_ioapic8),_C_LABEL(Xintr_ioapic9)
368	.globl	_C_LABEL(Xintr_ioapic10),_C_LABEL(Xintr_ioapic11)
369	.globl	_C_LABEL(Xintr_ioapic12),_C_LABEL(Xintr_ioapic13)
370	.globl	_C_LABEL(Xintr_ioapic14),_C_LABEL(Xintr_ioapic15)
371	.globl _C_LABEL(apichandler)
372
373_C_LABEL(apichandler):
374	.long	_C_LABEL(Xintr_ioapic0),_C_LABEL(Xintr_ioapic1)
375	.long	_C_LABEL(Xintr_ioapic2),_C_LABEL(Xintr_ioapic3)
376	.long	_C_LABEL(Xintr_ioapic4),_C_LABEL(Xintr_ioapic5)
377	.long	_C_LABEL(Xintr_ioapic6),_C_LABEL(Xintr_ioapic7)
378	.long	_C_LABEL(Xintr_ioapic8),_C_LABEL(Xintr_ioapic9)
379	.long	_C_LABEL(Xintr_ioapic10),_C_LABEL(Xintr_ioapic11)
380	.long	_C_LABEL(Xintr_ioapic12),_C_LABEL(Xintr_ioapic13)
381	.long	_C_LABEL(Xintr_ioapic14),_C_LABEL(Xintr_ioapic15)
382
383#endif
384
385