1 /* $NetBSD: intr.h,v 1.28 2002/10/05 21:25:24 fvdl Exp $ */ 2 3 /*- 4 * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Charles M. Hannum, and by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #ifndef _I386_INTR_H_ 40 #define _I386_INTR_H_ 41 42 /* 43 * Interrupt priority levels. 44 * 45 * There are tty, network and disk drivers that use free() at interrupt 46 * time, so imp > (tty | net | bio). 47 * 48 * Since run queues may be manipulated by both the statclock and tty, 49 * network, and disk drivers, clock > imp. 50 * 51 * IPL_HIGH must block everything that can manipulate a run queue. 52 * 53 * We need serial drivers to run at the absolute highest priority to 54 * avoid overruns, so serial > high. 55 */ 56 #define IPL_NONE 0x00 /* nothing */ 57 #define IPL_SOFTCLOCK 0x50 /* timeouts */ 58 #define IPL_SOFTNET 0x60 /* protocol stacks */ 59 #define IPL_BIO 0x70 /* block I/O */ 60 #define IPL_NET 0x80 /* network */ 61 #define IPL_SOFTSERIAL 0x90 /* serial */ 62 #define IPL_TTY 0xa0 /* terminal */ 63 #define IPL_IMP 0xb0 /* memory allocation */ 64 #define IPL_AUDIO 0xc0 /* audio */ 65 #define IPL_CLOCK 0xd0 /* clock */ 66 #define IPL_HIGH 0xd0 /* everything */ 67 #define IPL_SERIAL 0xd0 /* serial */ 68 #define IPL_IPI 0xe0 /* inter-processor interrupts */ 69 #define NIPL 16 70 71 /* Interrupt sharing types. */ 72 #define IST_NONE 0 /* none */ 73 #define IST_PULSE 1 /* pulsed */ 74 #define IST_EDGE 2 /* edge-triggered */ 75 #define IST_LEVEL 3 /* level-triggered */ 76 77 /* Soft interrupt masks. */ 78 #define SIR_CLOCK 31 79 #define SIR_NET 30 80 #define SIR_SERIAL 29 81 82 /* Hack for CLKF_INTR(). */ 83 #define IPL_TAGINTR 28 84 85 #ifndef _LOCORE 86 87 extern volatile u_int32_t lapic_tpr; 88 extern volatile u_int32_t ipending; 89 90 extern int imasks[NIPL]; 91 extern int iunmask[NIPL]; 92 93 #define CPSHIFT 4 94 #define IMASK(level) imasks[(level)>>CPSHIFT] 95 #define IUNMASK(level) iunmask[(level)>>CPSHIFT] 96 97 extern void Xspllower __P((void)); 98 99 static __inline int splraise __P((int)); 100 static __inline void spllower __P((int)); 101 static __inline void softintr __P((int)); 102 103 /* 104 * compiler barrier: prevent reordering of instructions. 105 * XXX something similar will move to <sys/cdefs.h> 106 * or thereabouts. 107 * This prevents the compiler from reordering code around 108 * this "instruction", acting as a sequence point for code generation. 109 */ 110 111 #define __splbarrier() __asm __volatile("" : : : "memory") 112 113 /* 114 * Add a mask to cpl, and return the old value of cpl. 115 */ 116 static __inline int 117 splraise(int ncpl) 118 { 119 register int ocpl = lapic_tpr; 120 121 if (ncpl > ocpl) 122 lapic_tpr = ncpl; 123 __splbarrier(); 124 return (ocpl); 125 } 126 127 /* 128 * Restore a value to cpl (unmasking interrupts). If any unmasked 129 * interrupts are pending, call Xspllower() to process them. 130 */ 131 static __inline void 132 spllower(int ncpl) 133 { 134 register int cmask; 135 136 __splbarrier(); 137 lapic_tpr = ncpl; 138 cmask = IUNMASK(ncpl); 139 if (ipending & cmask) 140 Xspllower(); 141 } 142 143 /* 144 * Hardware interrupt masks 145 */ 146 #define splbio() splraise(IPL_BIO) 147 #define splnet() splraise(IPL_NET) 148 #define spltty() splraise(IPL_TTY) 149 #define splaudio() splraise(IPL_AUDIO) 150 #define splclock() splraise(IPL_CLOCK) 151 #define splstatclock() splclock() 152 #define splserial() splraise(IPL_SERIAL) 153 #define splipi() splraise(IPL_IPI) 154 155 #define spllpt() spltty() 156 157 #define SPL_ASSERT_ATMOST(x) KDASSERT(lapic_tpr <= (x)) 158 #define spllpt() spltty() 159 160 /* 161 * Software interrupt masks 162 * 163 * NOTE: splsoftclock() is used by hardclock() to lower the priority from 164 * clock to softclock before it calls softclock(). 165 */ 166 #define spllowersoftclock() spllower(IPL_SOFTCLOCK) 167 168 #define splsoftclock() splraise(IPL_SOFTCLOCK) 169 #define splsoftnet() splraise(IPL_SOFTNET) 170 #define splsoftserial() splraise(IPL_SOFTSERIAL) 171 172 /* 173 * Miscellaneous 174 */ 175 #define splvm() splraise(IPL_IMP) 176 #define splhigh() splraise(IPL_HIGH) 177 #define spl0() spllower(IPL_NONE) 178 #define splsched() splhigh() 179 #define spllock() splhigh() 180 #define splx(x) spllower(x) 181 182 /* 183 * Software interrupt registration 184 * 185 * We hand-code this to ensure that it's atomic. 186 */ 187 static __inline void 188 softintr(register int sir) 189 { 190 __asm __volatile("lock ; orl %1, %0" : "=m"(ipending) : "ir" (1 << sir)); 191 } 192 193 #define setsoftnet() softintr(SIR_NET) 194 195 /* XXX does ipi goo belong here, or elsewhere? */ 196 197 #define I386_IPI_HALT 0x00000001 198 #define I386_IPI_MICROSET 0x00000002 199 #define I386_IPI_FLUSH_FPU 0x00000004 200 #define I386_IPI_SYNCH_FPU 0x00000008 201 #define I386_IPI_TLB 0x00000010 202 #define I386_IPI_MTRR 0x00000020 203 #define I386_IPI_GDT 0x00000040 204 205 #define I386_NIPI 7 206 207 #ifdef MULTIPROCESSOR 208 struct cpu_info; 209 210 int i386_send_ipi (struct cpu_info *, int); 211 void i386_broadcast_ipi (int); 212 void i386_multicast_ipi (int, int); 213 void i386_ipi_handler (void); 214 #endif 215 216 #endif /* !_LOCORE */ 217 218 /* 219 * Generic software interrupt support. 220 */ 221 222 #define I386_SOFTINTR_SOFTCLOCK 0 223 #define I386_SOFTINTR_SOFTNET 1 224 #define I386_SOFTINTR_SOFTSERIAL 2 225 #define I386_NSOFTINTR 3 226 227 #ifndef _LOCORE 228 #include <sys/queue.h> 229 230 struct i386_soft_intrhand { 231 TAILQ_ENTRY(i386_soft_intrhand) 232 sih_q; 233 struct i386_soft_intr *sih_intrhead; 234 void (*sih_fn)(void *); 235 void *sih_arg; 236 int sih_pending; 237 }; 238 239 struct i386_soft_intr { 240 TAILQ_HEAD(, i386_soft_intrhand) 241 softintr_q; 242 int softintr_ssir; 243 struct simplelock softintr_slock; 244 }; 245 246 #define i386_softintr_lock(si, s) \ 247 do { \ 248 /* XXX splhigh braindamage on i386 */ \ 249 (s) = splserial(); \ 250 simple_lock(&si->softintr_slock); \ 251 } while (/*CONSTCOND*/ 0) 252 253 #define i386_softintr_unlock(si, s) \ 254 do { \ 255 simple_unlock(&si->softintr_slock); \ 256 splx((s)); \ 257 } while (/*CONSTCOND*/ 0) 258 259 void *softintr_establish(int, void (*)(void *), void *); 260 void softintr_disestablish(void *); 261 void softintr_init(void); 262 void softintr_dispatch(int); 263 264 #define softintr_schedule(arg) \ 265 do { \ 266 struct i386_soft_intrhand *__sih = (arg); \ 267 struct i386_soft_intr *__si = __sih->sih_intrhead; \ 268 int __s; \ 269 \ 270 i386_softintr_lock(__si, __s); \ 271 if (__sih->sih_pending == 0) { \ 272 TAILQ_INSERT_TAIL(&__si->softintr_q, __sih, sih_q); \ 273 __sih->sih_pending = 1; \ 274 softintr(__si->softintr_ssir); \ 275 } \ 276 i386_softintr_unlock(__si, __s); \ 277 } while (/*CONSTCOND*/ 0) 278 #endif /* _LOCORE */ 279 280 #endif /* !_I386_INTR_H_ */ 281