xref: /openbsd-src/sys/arch/i386/include/intr.h (revision 2b0358df1d88d06ef4139321dd05bd5e05d91eaf)
1 /*	$OpenBSD: intr.h,v 1.37 2009/03/15 19:40:40 miod Exp $	*/
2 /*	$NetBSD: intr.h,v 1.5 1996/05/13 06:11:28 mycroft Exp $	*/
3 
4 /*
5  * Copyright (c) 1996 Charles M. Hannum.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by Charles M. Hannum.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #ifndef _I386_INTR_H_
34 #define _I386_INTR_H_
35 
36 #include <machine/intrdefs.h>
37 
38 #ifndef _LOCORE
39 #include <machine/cpu.h>
40 
41 extern volatile u_int32_t lapic_tpr;	/* Current interrupt priority level. */
42 
43 extern int imask[];	/* Bitmasks telling what interrupts are blocked. */
44 extern int iunmask[];	/* Bitmasks telling what interrupts are accepted. */
45 
46 #define IMASK(level) imask[IPL(level)]
47 #define IUNMASK(level) iunmask[IPL(level)]
48 
49 extern void Xspllower(void);
50 
51 extern int splraise(int);
52 extern int spllower(int);
53 extern void splx(int);
54 extern void softintr(int);
55 
56 /*
57  * compiler barrier: prevent reordering of instructions.
58  * XXX something similar will move to <sys/cdefs.h>
59  * or thereabouts.
60  * This prevents the compiler from reordering code around
61  * this "instruction", acting as a sequence point for code generation.
62  */
63 
64 #define	__splbarrier() __asm __volatile("":::"memory")
65 
66 /* SPL asserts */
67 #ifdef DIAGNOSTIC
68 /*
69  * Although this function is implemented in MI code, it must be in this MD
70  * header because we don't want this header to include MI includes.
71  */
72 void splassert_fail(int, int, const char *);
73 extern int splassert_ctl;
74 void splassert_check(int, const char *);
75 #define splassert(__wantipl) do {			\
76 	if (splassert_ctl > 0) {			\
77 		splassert_check(__wantipl, __func__);	\
78 	}						\
79 } while (0)
80 #define splsoftassert(wantipl) splassert(wantipl)
81 #else
82 #define splassert(wantipl)	do { /* nada */ } while (0)
83 #define splsoftassert(wantipl)	do { /* nada */ } while (0)
84 #endif
85 
86 /*
87  * Define the splraise and splx code in macros, so that the code can be
88  * reused in a profiling build in a way that does not cause recursion.
89  */
90 #define _SPLRAISE(ocpl, ncpl) 		\
91 	ocpl = lapic_tpr;		\
92 	if (ncpl > ocpl)		\
93 		lapic_tpr = ncpl
94 
95 
96 #define _SPLX(ncpl) 			\
97 	lapic_tpr = ncpl;		\
98 	if (curcpu()->ci_ipending & IUNMASK(ncpl))	\
99 		Xspllower()
100 
101 /*
102  * Hardware interrupt masks
103  */
104 #define	splbio()	splraise(IPL_BIO)
105 #define	splnet()	splraise(IPL_NET)
106 #define	spltty()	splraise(IPL_TTY)
107 #define	splaudio()	splraise(IPL_AUDIO)
108 #define	splclock()	splraise(IPL_CLOCK)
109 #define	splstatclock()	splhigh()
110 #define splipi()	splraise(IPL_IPI)
111 
112 /*
113  * Software interrupt masks
114  */
115 #define	splsoftclock()		splraise(IPL_SOFTCLOCK)
116 #define	splsoftnet()		splraise(IPL_SOFTNET)
117 #define	splsofttty()		splraise(IPL_SOFTTTY)
118 
119 /*
120  * Miscellaneous
121  */
122 #define	splvm()		splraise(IPL_VM)
123 #define	splhigh()	splraise(IPL_HIGH)
124 #define	splsched()	splraise(IPL_SCHED)
125 #define spllock() 	splhigh()
126 #define	spl0()		spllower(IPL_NONE)
127 
128 #define	setsoftnet()	softintr(SIR_NET)
129 #define	setsofttty()	softintr(SIR_TTY)
130 
131 struct cpu_info;
132 
133 #ifdef MULTIPROCESSOR
134 int i386_send_ipi(struct cpu_info *, int);
135 int i386_fast_ipi(struct cpu_info *, int);
136 void i386_broadcast_ipi(int);
137 void i386_multicast_ipi(int, int);
138 void i386_ipi_handler(void);
139 void i386_intlock(int);
140 void i386_intunlock(int);
141 void i386_softintlock(void);
142 void i386_softintunlock(void);
143 void i386_setperf_ipi(struct cpu_info *);
144 
145 extern void (*ipifunc[I386_NIPI])(struct cpu_info *);
146 #endif
147 
148 #endif /* !_LOCORE */
149 
150 /*
151  * Generic software interrupt support.
152  */
153 
154 #define	I386_SOFTINTR_SOFTCLOCK		0
155 #define	I386_SOFTINTR_SOFTNET		1
156 #define	I386_SOFTINTR_SOFTTTY		2
157 #define	I386_NSOFTINTR			3
158 
159 #ifndef _LOCORE
160 #include <sys/queue.h>
161 
162 struct i386_soft_intrhand {
163 	TAILQ_ENTRY(i386_soft_intrhand)
164 		sih_q;
165 	struct i386_soft_intr *sih_intrhead;
166 	void	(*sih_fn)(void *);
167 	void	*sih_arg;
168 	int	sih_pending;
169 };
170 
171 struct i386_soft_intr {
172 	TAILQ_HEAD(, i386_soft_intrhand)
173 		softintr_q;
174 	int softintr_ssir;
175 	struct simplelock softintr_slock;
176 };
177 
178 #define	i386_softintr_lock(si, s)					\
179 do {									\
180 	(s) = splhigh();						\
181 	simple_lock(&si->softintr_slock);				\
182 } while (/*CONSTCOND*/ 0)
183 
184 #define	i386_softintr_unlock(si, s)					\
185 do {									\
186 	simple_unlock(&si->softintr_slock);				\
187 	splx((s));							\
188 } while (/*CONSTCOND*/ 0)
189 
190 void	*softintr_establish(int, void (*)(void *), void *);
191 void	softintr_disestablish(void *);
192 void	softintr_init(void);
193 void	softintr_dispatch(int);
194 
195 #define	softintr_schedule(arg)						\
196 do {									\
197 	struct i386_soft_intrhand *__sih = (arg);			\
198 	struct i386_soft_intr *__si = __sih->sih_intrhead;		\
199 	int __s;							\
200 									\
201 	i386_softintr_lock(__si, __s);					\
202 	if (__sih->sih_pending == 0) {					\
203 		TAILQ_INSERT_TAIL(&__si->softintr_q, __sih, sih_q);	\
204 		__sih->sih_pending = 1;					\
205 		softintr(__si->softintr_ssir);				\
206 	}								\
207 	i386_softintr_unlock(__si, __s);					\
208 } while (/*CONSTCOND*/ 0)
209 #endif /* _LOCORE */
210 
211 #endif /* !_I386_INTR_H_ */
212