xref: /openbsd/sys/arch/i386/i386/apicvec.s (revision 81621933)
1/* $OpenBSD: apicvec.s,v 1.36 2022/12/08 01:25:44 guenther 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 "ioapic.h"
36
37#include <machine/i82093reg.h>
38#include <machine/i82489reg.h>
39
40	.globl  apic_stray
41
42#ifdef MULTIPROCESSOR
43IDTVEC(intripi)
44	subl	$8,%esp			/* space for tf_{err,trapno} */
45	INTRENTRY(ipi)
46	pushl	CPL
47	movl	lapic_ppr,%eax
48	movl	%eax,CPL
49	ioapic_asm_ack()
50	sti			/* safe to take interrupts.. */
51	call	i386_ipi_handler
52	cli
53	popl	CPL
54#ifdef DIAGNOSTIC
55	movl	$0xf8,%esi
56#endif
57	INTRFASTEXIT
58
59	.p2align 4,0xcc
60IDTVEC(intripi_invltlb)
61	pushl	%eax
62	pushl	%ds
63	movl	$GSEL(GDATA_SEL, SEL_KPL), %eax
64	movl	%eax, %ds
65
66	ioapic_asm_ack()
67
68	movl	%cr3, %eax
69	movl	%eax, %cr3
70
71	lock
72	decl	tlb_shoot_wait
73
74	popl	%ds
75	popl	%eax
76	iret
77
78	.p2align 4,0xcc
79IDTVEC(intripi_invlpg)
80	pushl	%eax
81	pushl	%ds
82	movl	$GSEL(GDATA_SEL, SEL_KPL), %eax
83	movl	%eax, %ds
84
85	ioapic_asm_ack()
86
87	movl	tlb_shoot_addr1, %eax
88	invlpg	(%eax)
89
90	lock
91	decl	tlb_shoot_wait
92
93	popl	%ds
94	popl	%eax
95	iret
96
97	.p2align 4,0xcc
98IDTVEC(intripi_invlrange)
99	pushl	%eax
100	pushl	%edx
101	pushl	%ds
102	movl	$GSEL(GDATA_SEL, SEL_KPL), %eax
103	movl	%eax, %ds
104
105	ioapic_asm_ack()
106
107	movl	tlb_shoot_addr1, %eax
108	movl	tlb_shoot_addr2, %edx
1091:	invlpg	(%eax)
110	addl	$PAGE_SIZE, %eax
111	cmpl	%edx, %eax
112	jb	1b
113
114	lock
115	decl	tlb_shoot_wait
116
117	popl	%ds
118	popl	%edx
119	popl	%eax
120	iret
121
122	.p2align 4,0xcc
123IDTVEC(intripi_reloadcr3)
124	pushl	%eax
125	pushl	%ds
126	movl	$GSEL(GDATA_SEL, SEL_KPL), %eax
127	movl	%eax, %ds
128	pushl	%fs
129	movl	$GSEL(GCPU_SEL, SEL_KPL),%eax
130	movw	%ax,%fs
131
132	ioapic_asm_ack()
133
134	movl	CPUVAR(CURPCB), %eax
135	movl	PCB_PMAP(%eax), %eax
136	movl	%eax, CPUVAR(CURPMAP)
137	movl	PM_PDIRPA(%eax), %eax
138	movl	%eax, %cr3
139
140	lock
141	decl	tlb_shoot_wait
142
143	popl	%fs
144	popl	%ds
145	popl	%eax
146	iret
147
148#endif
149
150	/*
151	 * Interrupt from the local APIC timer.
152	 */
153IDTVEC(intrltimer)
154	subl	$8,%esp			/* space for tf_{err,trapno} */
155	INTRENTRY(ltimer)
156	pushl	CPL
157	movl	lapic_ppr,%eax
158	movl	%eax,CPL
159	ioapic_asm_ack()
160	sti
161	incl	CPUVAR(IDEPTH)
162	movl	%esp,%eax
163	pushl	%eax
164	call	lapic_clockintr
165	addl	$4,%esp
166	decl	CPUVAR(IDEPTH)
167	jmp	Xdoreti
168
169KIDTVEC(intrsoftclock)
170	subl	$8,%esp			/* space for tf_{err,trapno} */
171	INTRENTRY(intrsoftclock)
172	pushl	CPL
173	movl	$IPL_SOFTCLOCK,CPL
174	andl	$~(1<<SIR_CLOCK),CPUVAR(IPENDING)
175	ioapic_asm_ack()
176	sti
177	incl	CPUVAR(IDEPTH)
178	pushl	$I386_SOFTINTR_SOFTCLOCK
179	call	softintr_dispatch
180	addl	$4,%esp
181	decl	CPUVAR(IDEPTH)
182	jmp	Xdoreti
183
184KIDTVEC(intrsoftnet)
185	subl	$8,%esp			/* space for tf_{err,trapno} */
186	INTRENTRY(intrsoftnet)
187	pushl	CPL
188	movl	$IPL_SOFTNET,CPL
189	andl	$~(1<<SIR_NET),CPUVAR(IPENDING)
190	ioapic_asm_ack()
191	sti
192	incl	CPUVAR(IDEPTH)
193	pushl	$I386_SOFTINTR_SOFTNET
194	call	softintr_dispatch
195	addl	$4,%esp
196	decl	CPUVAR(IDEPTH)
197	jmp	Xdoreti
198#undef DONETISR
199
200KIDTVEC(intrsofttty)
201	subl	$8,%esp			/* space for tf_{err,trapno} */
202	INTRENTRY(intrsofttty)
203	pushl	CPL
204	movl	$IPL_SOFTTTY,CPL
205	andl	$~(1<<SIR_TTY),CPUVAR(IPENDING)
206	ioapic_asm_ack()
207	sti
208	incl	CPUVAR(IDEPTH)
209	pushl	$I386_SOFTINTR_SOFTTTY
210	call	softintr_dispatch
211	addl	$4,%esp
212	decl	CPUVAR(IDEPTH)
213	jmp	Xdoreti
214
215#if NIOAPIC > 0
216
217#define voidop(num)
218
219	/*
220	 * I/O APIC interrupt.
221	 * We sort out which one is which based on the value of
222	 * the processor priority register.
223	 *
224	 * XXX use cmove when appropriate.
225	 */
226
227#define APICINTR(name, num, early_ack, late_ack, mask, unmask, level_mask) \
228IDTVEC(intr_##name##num)						\
229	subl	$8,%esp			/* space for tf_{err,trapno} */	;\
230	INTRENTRY(intr_##name##num)					;\
231	pushl	CPL							;\
232	movl	lapic_ppr,%eax						;\
233	orl	$num,%eax						;\
234	movl	apic_maxlevel(,%eax,4),%ebx				;\
235	movl	%ebx,CPL						;\
236	mask(num)			/* mask it in hardware */	;\
237	early_ack(num)			/* and allow other intrs */	;\
238	incl	uvmexp+V_INTR		/* statistical info */		;\
239	sti								;\
240	movl	apic_intrhand(,%eax,4),%ebx /* chain head */		;\
241	testl	%ebx,%ebx						;\
242	jz	Xstray_##name##num					;\
243	APIC_STRAY_INIT			/* nobody claimed it yet */	;\
2447:	incl	CPUVAR(IDEPTH)						;\
245	movl	%esp, %eax		/* save frame pointer in eax */	;\
246	pushl	%ebx			/* arg 2: ih structure */	;\
247	pushl	%eax			/* arg 1: frame pointer */	;\
248	call	intr_handler		/* call it */			;\
249	addl	$8, %esp		/* toss args */			;\
250	APIC_STRAY_INTEGRATE		/* maybe he claimed it */	;\
251	orl	%eax,%eax		/* should it be counted? */	;\
252	jz	4f							;\
253	addl	$1,IH_COUNT(%ebx)	/* count the intrs */		;\
254	adcl	$0,IH_COUNT+4(%ebx)					;\
255	cmpl	$0,intr_shared_edge					;\
256	jne	4f			/* if no shared edges ... */	;\
257	orl	%eax,%eax		/* ... 1 means stop trying */	;\
258	js	4f							;\
2591:	decl	CPUVAR(IDEPTH)						;\
260	jmp	8f							;\
2614:	decl	CPUVAR(IDEPTH)						;\
262	movl	IH_NEXT(%ebx),%ebx	/* next handler in chain */	;\
263	testl	%ebx,%ebx						;\
264	jnz	7b							;\
265	APIC_STRAY_TEST(name,num)	/* see if it's a stray */	;\
2668:									 \
267	unmask(num)			/* unmask it in hardware */	;\
268	late_ack(num)							;\
269	jmp	Xdoreti							;\
270Xstray_##name##num:						 \
271	pushl	$num							;\
272	call	apic_stray						;\
273	addl	$4,%esp							;\
274	jmp	8b							;\
275
276#if defined(DEBUG)
277#define APIC_STRAY_INIT \
278	xorl	%esi,%esi
279#define	APIC_STRAY_INTEGRATE \
280	orl	%eax,%esi
281#define APIC_STRAY_TEST(name,num) \
282	testl 	%esi,%esi						;\
283	jz 	Xstray_##name##num
284#else /* !DEBUG */
285#define APIC_STRAY_INIT
286#define APIC_STRAY_INTEGRATE
287#define APIC_STRAY_TEST(name,num)
288#endif /* DEBUG */
289
290APICINTR(ioapic,0, voidop, ioapic_asm_ack, voidop, voidop, voidop)
291APICINTR(ioapic,1, voidop, ioapic_asm_ack, voidop, voidop, voidop)
292APICINTR(ioapic,2, voidop, ioapic_asm_ack, voidop, voidop, voidop)
293APICINTR(ioapic,3, voidop, ioapic_asm_ack, voidop, voidop, voidop)
294APICINTR(ioapic,4, voidop, ioapic_asm_ack, voidop, voidop, voidop)
295APICINTR(ioapic,5, voidop, ioapic_asm_ack, voidop, voidop, voidop)
296APICINTR(ioapic,6, voidop, ioapic_asm_ack, voidop, voidop, voidop)
297APICINTR(ioapic,7, voidop, ioapic_asm_ack, voidop, voidop, voidop)
298APICINTR(ioapic,8, voidop, ioapic_asm_ack, voidop, voidop, voidop)
299APICINTR(ioapic,9, voidop, ioapic_asm_ack, voidop, voidop, voidop)
300APICINTR(ioapic,10, voidop, ioapic_asm_ack, voidop, voidop, voidop)
301APICINTR(ioapic,11, voidop, ioapic_asm_ack, voidop, voidop, voidop)
302APICINTR(ioapic,12, voidop, ioapic_asm_ack, voidop, voidop, voidop)
303APICINTR(ioapic,13, voidop, ioapic_asm_ack, voidop, voidop, voidop)
304APICINTR(ioapic,14, voidop, ioapic_asm_ack, voidop, voidop, voidop)
305APICINTR(ioapic,15, voidop, ioapic_asm_ack, voidop, voidop, voidop)
306
307	.globl	Xintr_ioapic0,Xintr_ioapic1
308	.globl	Xintr_ioapic2,Xintr_ioapic3
309	.globl	Xintr_ioapic4,Xintr_ioapic5
310	.globl	Xintr_ioapic6,Xintr_ioapic7
311	.globl	Xintr_ioapic8,Xintr_ioapic9
312	.globl	Xintr_ioapic10,Xintr_ioapic11
313	.globl	Xintr_ioapic12,Xintr_ioapic13
314	.globl	Xintr_ioapic14,Xintr_ioapic15
315	.globl apichandler
316
317apichandler:
318	.long	Xintr_ioapic0,Xintr_ioapic1
319	.long	Xintr_ioapic2,Xintr_ioapic3
320	.long	Xintr_ioapic4,Xintr_ioapic5
321	.long	Xintr_ioapic6,Xintr_ioapic7
322	.long	Xintr_ioapic8,Xintr_ioapic9
323	.long	Xintr_ioapic10,Xintr_ioapic11
324	.long	Xintr_ioapic12,Xintr_ioapic13
325	.long	Xintr_ioapic14,Xintr_ioapic15
326
327#endif
328
329