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