xref: /openbsd-src/sys/arch/amd64/include/intr.h (revision fc30b644f1922d25f1f8a9187113a50ce3610714)
1*fc30b644Skettenis /*	$OpenBSD: intr.h,v 1.34 2024/05/26 13:37:31 kettenis Exp $	*/
2f5df1827Smickey /*	$NetBSD: intr.h,v 1.2 2003/05/04 22:01:56 fvdl Exp $	*/
3f5df1827Smickey 
4f5df1827Smickey /*-
5f5df1827Smickey  * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
6f5df1827Smickey  * All rights reserved.
7f5df1827Smickey  *
8f5df1827Smickey  * This code is derived from software contributed to The NetBSD Foundation
9f5df1827Smickey  * by Charles M. Hannum, and by Jason R. Thorpe.
10f5df1827Smickey  *
11f5df1827Smickey  * Redistribution and use in source and binary forms, with or without
12f5df1827Smickey  * modification, are permitted provided that the following conditions
13f5df1827Smickey  * are met:
14f5df1827Smickey  * 1. Redistributions of source code must retain the above copyright
15f5df1827Smickey  *    notice, this list of conditions and the following disclaimer.
16f5df1827Smickey  * 2. Redistributions in binary form must reproduce the above copyright
17f5df1827Smickey  *    notice, this list of conditions and the following disclaimer in the
18f5df1827Smickey  *    documentation and/or other materials provided with the distribution.
19f5df1827Smickey  *
20f5df1827Smickey  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21f5df1827Smickey  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22f5df1827Smickey  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23f5df1827Smickey  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24f5df1827Smickey  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25f5df1827Smickey  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26f5df1827Smickey  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27f5df1827Smickey  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28f5df1827Smickey  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29f5df1827Smickey  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30f5df1827Smickey  * POSSIBILITY OF SUCH DAMAGE.
31f5df1827Smickey  */
32f5df1827Smickey 
332fa72412Spirofti #ifndef _MACHINE_INTR_H_
342fa72412Spirofti #define _MACHINE_INTR_H_
35f5df1827Smickey 
36f5df1827Smickey #include <machine/intrdefs.h>
37f5df1827Smickey 
38f5df1827Smickey #ifndef _LOCORE
39f5df1827Smickey #include <machine/cpu.h>
40f5df1827Smickey 
416816c79aSderaadt #include <sys/evcount.h>
426816c79aSderaadt 
43f5df1827Smickey /*
44f5df1827Smickey  * Struct describing an interrupt source for a CPU. struct cpu_info
45f5df1827Smickey  * has an array of MAX_INTR_SOURCES of these. The index in the array
46f5df1827Smickey  * is equal to the stub number of the stubcode as present in vector.s
47f5df1827Smickey  *
48f5df1827Smickey  * The primary CPU's array of interrupt sources has its first 16
49f5df1827Smickey  * entries reserved for legacy ISA irq handlers. This means that
50f5df1827Smickey  * they have a 1:1 mapping for arrayindex:irq_num. This is not
51f5df1827Smickey  * true for interrupts that come in through IO APICs, to find
52f5df1827Smickey  * their source, go through ci->ci_isources[index].is_pic
53f5df1827Smickey  *
54f5df1827Smickey  * It's possible to always maintain a 1:1 mapping, but that means
55f5df1827Smickey  * limiting the total number of interrupt sources to MAX_INTR_SOURCES
56f5df1827Smickey  * (32), instead of 32 per CPU. It also would mean that having multiple
57f5df1827Smickey  * IO APICs which deliver interrupts from an equal pin number would
58f5df1827Smickey  * overlap if they were to be sent to the same CPU.
59f5df1827Smickey  */
60f5df1827Smickey 
61f5df1827Smickey struct intrstub {
62f5df1827Smickey 	void *ist_entry;
63f5df1827Smickey 	void *ist_recurse;
64f5df1827Smickey 	void *ist_resume;
65f5df1827Smickey };
66f5df1827Smickey 
67f5df1827Smickey struct intrsource {
68f5df1827Smickey 	int is_maxlevel;		/* max. IPL for this source */
69f5df1827Smickey 	int is_pin;			/* IRQ for legacy; pin for IO APIC */
70f5df1827Smickey 	struct intrhand *is_handlers;	/* handler chain */
71f5df1827Smickey 	struct pic *is_pic;		/* originating PIC */
72f5df1827Smickey 	void *is_recurse;		/* entry for spllower */
73f5df1827Smickey 	void *is_resume;		/* entry for doreti */
74f5df1827Smickey 	char is_evname[32];		/* event counter name */
75f5df1827Smickey 	int is_flags;			/* see below */
76f5df1827Smickey 	int is_type;			/* level, edge */
77f5df1827Smickey 	int is_idtvec;
78f5df1827Smickey 	int is_minlevel;
79f5df1827Smickey };
80f5df1827Smickey 
81f5df1827Smickey #define IS_LEGACY	0x0001		/* legacy ISA irq source */
82f5df1827Smickey #define IS_IPI		0x0002
83f5df1827Smickey #define IS_LOG		0x0004
84f5df1827Smickey 
85f5df1827Smickey 
86f5df1827Smickey /*
87f5df1827Smickey  * Interrupt handler chains.  *_intr_establish() insert a handler into
88f5df1827Smickey  * the list.  The handler is called with its (single) argument.
89f5df1827Smickey  */
90f5df1827Smickey 
91f5df1827Smickey struct intrhand {
92f5df1827Smickey 	int	(*ih_fun)(void *);
93f5df1827Smickey 	void	*ih_arg;
94f5df1827Smickey 	int	ih_level;
95483e3bc5Skettenis 	int	ih_flags;
96f5df1827Smickey 	struct	intrhand *ih_next;
97f5df1827Smickey 	int	ih_pin;
98f5df1827Smickey 	int	ih_slot;
99f5df1827Smickey 	struct cpu_info *ih_cpu;
100f5df1827Smickey 	int	ih_irq;
1016816c79aSderaadt 	struct evcount ih_count;
102f5df1827Smickey };
103f5df1827Smickey 
104f5df1827Smickey #define IMASK(ci,level) (ci)->ci_imask[(level)]
105f5df1827Smickey #define IUNMASK(ci,level) (ci)->ci_iunmask[(level)]
106f5df1827Smickey 
107f5df1827Smickey extern void Xspllower(int);
108f5df1827Smickey 
1090b57f6e9Sart int splraise(int);
1100b57f6e9Sart int spllower(int);
1110b57f6e9Sart void softintr(int);
112f5df1827Smickey 
113f5df1827Smickey /*
114f5df1827Smickey  * Convert spl level to local APIC level
115f5df1827Smickey  */
116f5df1827Smickey #define APIC_LEVEL(l)   ((l) << 4)
117f5df1827Smickey 
118f5df1827Smickey /*
119f5df1827Smickey  * compiler barrier: prevent reordering of instructions.
120f5df1827Smickey  * This prevents the compiler from reordering code around
121f5df1827Smickey  * this "instruction", acting as a sequence point for code generation.
122f5df1827Smickey  */
123f5df1827Smickey 
1242df76cc2Sguenther #define	__splbarrier() __asm volatile("":::"memory")
125f5df1827Smickey 
126f5df1827Smickey /*
127f5df1827Smickey  * Hardware interrupt masks
128f5df1827Smickey  */
129f5df1827Smickey #define	splbio()	splraise(IPL_BIO)
130f5df1827Smickey #define	splnet()	splraise(IPL_NET)
131f5df1827Smickey #define	spltty()	splraise(IPL_TTY)
132f5df1827Smickey #define	splaudio()	splraise(IPL_AUDIO)
133f5df1827Smickey #define	splclock()	splraise(IPL_CLOCK)
134f5df1827Smickey #define	splstatclock()	splclock()
135f5df1827Smickey #define splipi()	splraise(IPL_IPI)
136f5df1827Smickey 
137f5df1827Smickey /*
138f5df1827Smickey  * Software interrupt masks
139f5df1827Smickey  */
140f5df1827Smickey #define	splsoftclock()	splraise(IPL_SOFTCLOCK)
141f5df1827Smickey #define	splsoftnet()	splraise(IPL_SOFTNET)
142a2cd3cc4Skettenis #define	splsofttty()	splraise(IPL_SOFTTTY)
143f5df1827Smickey 
144f5df1827Smickey /*
145f5df1827Smickey  * Miscellaneous
146f5df1827Smickey  */
14793f0663eSbrad #define	splvm()		splraise(IPL_VM)
148f5df1827Smickey #define	splhigh()	splraise(IPL_HIGH)
149f5df1827Smickey #define	spl0()		spllower(IPL_NONE)
150f5df1827Smickey #define	splsched()	splraise(IPL_SCHED)
151f5df1827Smickey #define	splx(x)		spllower(x)
152f5df1827Smickey 
153f5df1827Smickey /* SPL asserts */
154f5df1827Smickey #ifdef DIAGNOSTIC
155f5df1827Smickey /*
156f5df1827Smickey  * Although this function is implemented in MI code, it must be in this MD
157f5df1827Smickey  * header because we don't want this header to include MI includes.
158f5df1827Smickey  */
159f5df1827Smickey void splassert_fail(int, int, const char *);
160f5df1827Smickey extern int splassert_ctl;
161f5df1827Smickey void splassert_check(int, const char *);
162f5df1827Smickey #define splassert(__wantipl) do {			\
163032bee17Sthib 	if (splassert_ctl > 0) {			\
164f5df1827Smickey 		splassert_check(__wantipl, __func__);	\
165f5df1827Smickey 	}						\
166f5df1827Smickey } while (0)
167312f6203Smiod #define splsoftassert(wantipl) splassert(wantipl)
168f5df1827Smickey #else
169f5df1827Smickey #define splassert(wantipl)	do { /* nada */ } while (0)
170312f6203Smiod #define splsoftassert(wantipl)	do { /* nada */ } while (0)
171f5df1827Smickey #endif
172f5df1827Smickey 
173f5df1827Smickey #define IPLSHIFT 4			/* The upper nibble of vectors is the IPL.      */
174f5df1827Smickey #define IPL(level) ((level) >> IPLSHIFT)	/* Extract the IPL.    */
175f5df1827Smickey 
176b5b9857bSart #include <machine/pic.h>
177b5b9857bSart 
178f5df1827Smickey /*
179f5df1827Smickey  * Stub declarations.
180f5df1827Smickey  */
181f5df1827Smickey 
182f5df1827Smickey extern void Xsoftclock(void);
183f5df1827Smickey extern void Xsoftnet(void);
184a2cd3cc4Skettenis extern void Xsofttty(void);
185f5df1827Smickey 
186f5df1827Smickey extern struct intrstub i8259_stubs[];
187f5df1827Smickey extern struct intrstub ioapic_edge_stubs[];
188f5df1827Smickey extern struct intrstub ioapic_level_stubs[];
189f5df1827Smickey 
190f5df1827Smickey struct cpu_info;
191f5df1827Smickey 
192177417ccSderaadt extern int intr_shared_edge;
193177417ccSderaadt 
194f5df1827Smickey extern char idt_allocmap[];
195f5df1827Smickey 
196f5df1827Smickey void intr_default_setup(void);
197f5df1827Smickey int x86_nmi(void);
198f5df1827Smickey void intr_calculatemasks(struct cpu_info *);
199f5df1827Smickey int intr_allocate_slot_cpu(struct cpu_info *, struct pic *, int, int *);
200f5df1827Smickey int intr_allocate_slot(struct pic *, int, int, int, struct cpu_info **, int *,
201f5df1827Smickey 	    int *);
20215db3095Sdlg void *intr_establish(int, struct pic *, int, int, int,
20315db3095Sdlg 	    struct cpu_info *, int (*)(void *), void *, const char *);
204f5df1827Smickey void intr_disestablish(struct intrhand *);
20558643530Sratchov int intr_handler(struct intrframe *, struct intrhand *);
206f5df1827Smickey void cpu_intr_init(struct cpu_info *);
207f5df1827Smickey void intr_printconfig(void);
208edc47eabSkettenis void intr_barrier(void *);
209*fc30b644Skettenis void intr_enable_wakeup(void);
210*fc30b644Skettenis void intr_disable_wakeup(void);
211f5df1827Smickey 
212f5df1827Smickey #ifdef MULTIPROCESSOR
213b8fe8d64Ssf void x86_send_ipi(struct cpu_info *, int);
214ae5427f4Sart int x86_fast_ipi(struct cpu_info *, int);
215f5df1827Smickey void x86_broadcast_ipi(int);
216f5df1827Smickey void x86_ipi_handler(void);
2175714d2eaSgwk void x86_setperf_ipi(struct cpu_info *);
218f5df1827Smickey 
219f5df1827Smickey extern void (*ipifunc[X86_NIPI])(struct cpu_info *);
220f5df1827Smickey #endif
221f5df1827Smickey 
222f5df1827Smickey #endif /* !_LOCORE */
223f5df1827Smickey 
224f5df1827Smickey /*
225f5df1827Smickey  * Generic software interrupt support.
226f5df1827Smickey  */
227f5df1827Smickey 
228f5df1827Smickey #define	X86_SOFTINTR_SOFTCLOCK		0
229f5df1827Smickey #define	X86_SOFTINTR_SOFTNET		1
230a2cd3cc4Skettenis #define	X86_SOFTINTR_SOFTTTY		2
231f5df1827Smickey #define	X86_NSOFTINTR			3
232f5df1827Smickey 
233f5df1827Smickey #ifndef _LOCORE
234f5df1827Smickey #include <sys/queue.h>
235f5df1827Smickey 
236f5df1827Smickey struct x86_soft_intrhand {
237f5df1827Smickey 	TAILQ_ENTRY(x86_soft_intrhand)
238f5df1827Smickey 		sih_q;
239f5df1827Smickey 	struct x86_soft_intr *sih_intrhead;
240f5df1827Smickey 	void	(*sih_fn)(void *);
241f5df1827Smickey 	void	*sih_arg;
242f5df1827Smickey 	int	sih_pending;
243f5df1827Smickey };
244f5df1827Smickey 
245f5df1827Smickey struct x86_soft_intr {
246f5df1827Smickey 	TAILQ_HEAD(, x86_soft_intrhand)
247f5df1827Smickey 			softintr_q;
248f5df1827Smickey 	int		softintr_ssir;
2491f723b73Soga 	struct mutex	softintr_lock;
250f5df1827Smickey };
251f5df1827Smickey 
252f5df1827Smickey void	*softintr_establish(int, void (*)(void *), void *);
253f5df1827Smickey void	softintr_disestablish(void *);
254f5df1827Smickey void	softintr_init(void);
255f5df1827Smickey void	softintr_dispatch(int);
256f5df1827Smickey 
257f5df1827Smickey #define	softintr_schedule(arg)						\
258f5df1827Smickey do {									\
259f5df1827Smickey 	struct x86_soft_intrhand *__sih = (arg);			\
260f5df1827Smickey 	struct x86_soft_intr *__si = __sih->sih_intrhead;		\
261f5df1827Smickey 									\
2621f723b73Soga 	mtx_enter(&__si->softintr_lock);				\
263f5df1827Smickey 	if (__sih->sih_pending == 0) {					\
264f5df1827Smickey 		TAILQ_INSERT_TAIL(&__si->softintr_q, __sih, sih_q);	\
265f5df1827Smickey 		__sih->sih_pending = 1;					\
266f5df1827Smickey 		softintr(__si->softintr_ssir);				\
267f5df1827Smickey 	}								\
2681f723b73Soga 	mtx_leave(&__si->softintr_lock);				\
269f5df1827Smickey } while (/*CONSTCOND*/ 0)
270f5df1827Smickey #endif /* _LOCORE */
271f5df1827Smickey 
2722fa72412Spirofti #endif /* !_MACHINE_INTR_H_ */
273