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