apic_vector.s revision 255040
1/*- 2 * Copyright (c) 1989, 1990 William F. Jolitz. 3 * Copyright (c) 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 4. Neither the name of the University nor the names of its contributors 15 * may be used to endorse or promote products derived from this software 16 * without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * from: vector.s, 386BSD 0.1 unknown origin 31 * $FreeBSD: head/sys/i386/i386/apic_vector.s 255040 2013-08-29 19:52:18Z gibbs $ 32 */ 33 34/* 35 * Interrupt entry points for external interrupts triggered by I/O APICs 36 * as well as IPI handlers. 37 */ 38 39#include "opt_smp.h" 40 41#include <machine/asmacros.h> 42#include <x86/apicreg.h> 43 44#include "assym.s" 45 46/* 47 * I/O Interrupt Entry Point. Rather than having one entry point for 48 * each interrupt source, we use one entry point for each 32-bit word 49 * in the ISR. The handler determines the highest bit set in the ISR, 50 * translates that into a vector, and passes the vector to the 51 * lapic_handle_intr() function. 52 */ 53#define ISR_VEC(index, vec_name) \ 54 .text ; \ 55 SUPERALIGN_TEXT ; \ 56IDTVEC(vec_name) ; \ 57 PUSH_FRAME ; \ 58 SET_KERNEL_SREGS ; \ 59 cld ; \ 60 FAKE_MCOUNT(TF_EIP(%esp)) ; \ 61 movl lapic, %edx ; /* pointer to local APIC */ \ 62 movl LA_ISR + 16 * (index)(%edx), %eax ; /* load ISR */ \ 63 bsrl %eax, %eax ; /* index of highest set bit in ISR */ \ 64 jz 1f ; \ 65 addl $(32 * index),%eax ; \ 66 pushl %esp ; \ 67 pushl %eax ; /* pass the IRQ */ \ 68 call lapic_handle_intr ; \ 69 addl $8, %esp ; /* discard parameter */ \ 701: ; \ 71 MEXITCOUNT ; \ 72 jmp doreti 73 74/* 75 * Handle "spurious INTerrupts". 76 * Notes: 77 * This is different than the "spurious INTerrupt" generated by an 78 * 8259 PIC for missing INTs. See the APIC documentation for details. 79 * This routine should NOT do an 'EOI' cycle. 80 */ 81 .text 82 SUPERALIGN_TEXT 83IDTVEC(spuriousint) 84 85 /* No EOI cycle used here */ 86 87 iret 88 89 ISR_VEC(1, apic_isr1) 90 ISR_VEC(2, apic_isr2) 91 ISR_VEC(3, apic_isr3) 92 ISR_VEC(4, apic_isr4) 93 ISR_VEC(5, apic_isr5) 94 ISR_VEC(6, apic_isr6) 95 ISR_VEC(7, apic_isr7) 96 97/* 98 * Local APIC periodic timer handler. 99 */ 100 .text 101 SUPERALIGN_TEXT 102IDTVEC(timerint) 103 PUSH_FRAME 104 SET_KERNEL_SREGS 105 cld 106 FAKE_MCOUNT(TF_EIP(%esp)) 107 pushl %esp 108 call lapic_handle_timer 109 add $4, %esp 110 MEXITCOUNT 111 jmp doreti 112 113/* 114 * Local APIC CMCI handler. 115 */ 116 .text 117 SUPERALIGN_TEXT 118IDTVEC(cmcint) 119 PUSH_FRAME 120 SET_KERNEL_SREGS 121 cld 122 FAKE_MCOUNT(TF_EIP(%esp)) 123 call lapic_handle_cmc 124 MEXITCOUNT 125 jmp doreti 126 127/* 128 * Local APIC error interrupt handler. 129 */ 130 .text 131 SUPERALIGN_TEXT 132IDTVEC(errorint) 133 PUSH_FRAME 134 SET_KERNEL_SREGS 135 cld 136 FAKE_MCOUNT(TF_EIP(%esp)) 137 call lapic_handle_error 138 MEXITCOUNT 139 jmp doreti 140 141#ifdef XENHVM 142/* 143 * Xen event channel upcall interrupt handler. 144 * Only used when the hypervisor supports direct vector callbacks. 145 */ 146 .text 147 SUPERALIGN_TEXT 148IDTVEC(xen_intr_upcall) 149 PUSH_FRAME 150 SET_KERNEL_SREGS 151 cld 152 FAKE_MCOUNT(TF_EIP(%esp)) 153 pushl %esp 154 call xen_intr_handle_upcall 155 add $4, %esp 156 MEXITCOUNT 157 jmp doreti 158#endif 159 160#ifdef SMP 161/* 162 * Global address space TLB shootdown. 163 */ 164 .text 165 SUPERALIGN_TEXT 166IDTVEC(invltlb) 167 pushl %eax 168 pushl %ds 169 movl $KDSEL, %eax /* Kernel data selector */ 170 movl %eax, %ds 171 172#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS) 173 pushl %fs 174 movl $KPSEL, %eax /* Private space selector */ 175 movl %eax, %fs 176 movl PCPU(CPUID), %eax 177 popl %fs 178#ifdef COUNT_XINVLTLB_HITS 179 incl xhits_gbl(,%eax,4) 180#endif 181#ifdef COUNT_IPIS 182 movl ipi_invltlb_counts(,%eax,4),%eax 183 incl (%eax) 184#endif 185#endif 186 187 movl %cr3, %eax /* invalidate the TLB */ 188 movl %eax, %cr3 189 190 movl lapic, %eax 191 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 192 193 lock 194 incl smp_tlb_wait 195 196 popl %ds 197 popl %eax 198 iret 199 200/* 201 * Single page TLB shootdown 202 */ 203 .text 204 SUPERALIGN_TEXT 205IDTVEC(invlpg) 206 pushl %eax 207 pushl %ds 208 movl $KDSEL, %eax /* Kernel data selector */ 209 movl %eax, %ds 210 211#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS) 212 pushl %fs 213 movl $KPSEL, %eax /* Private space selector */ 214 movl %eax, %fs 215 movl PCPU(CPUID), %eax 216 popl %fs 217#ifdef COUNT_XINVLTLB_HITS 218 incl xhits_pg(,%eax,4) 219#endif 220#ifdef COUNT_IPIS 221 movl ipi_invlpg_counts(,%eax,4),%eax 222 incl (%eax) 223#endif 224#endif 225 226 movl smp_tlb_addr1, %eax 227 invlpg (%eax) /* invalidate single page */ 228 229 movl lapic, %eax 230 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 231 232 lock 233 incl smp_tlb_wait 234 235 popl %ds 236 popl %eax 237 iret 238 239/* 240 * Page range TLB shootdown. 241 */ 242 .text 243 SUPERALIGN_TEXT 244IDTVEC(invlrng) 245 pushl %eax 246 pushl %edx 247 pushl %ds 248 movl $KDSEL, %eax /* Kernel data selector */ 249 movl %eax, %ds 250 251#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS) 252 pushl %fs 253 movl $KPSEL, %eax /* Private space selector */ 254 movl %eax, %fs 255 movl PCPU(CPUID), %eax 256 popl %fs 257#ifdef COUNT_XINVLTLB_HITS 258 incl xhits_rng(,%eax,4) 259#endif 260#ifdef COUNT_IPIS 261 movl ipi_invlrng_counts(,%eax,4),%eax 262 incl (%eax) 263#endif 264#endif 265 266 movl smp_tlb_addr1, %edx 267 movl smp_tlb_addr2, %eax 2681: invlpg (%edx) /* invalidate single page */ 269 addl $PAGE_SIZE, %edx 270 cmpl %eax, %edx 271 jb 1b 272 273 movl lapic, %eax 274 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 275 276 lock 277 incl smp_tlb_wait 278 279 popl %ds 280 popl %edx 281 popl %eax 282 iret 283 284/* 285 * Invalidate cache. 286 */ 287 .text 288 SUPERALIGN_TEXT 289IDTVEC(invlcache) 290 pushl %eax 291 pushl %ds 292 movl $KDSEL, %eax /* Kernel data selector */ 293 movl %eax, %ds 294 295#ifdef COUNT_IPIS 296 pushl %fs 297 movl $KPSEL, %eax /* Private space selector */ 298 movl %eax, %fs 299 movl PCPU(CPUID), %eax 300 popl %fs 301 movl ipi_invlcache_counts(,%eax,4),%eax 302 incl (%eax) 303#endif 304 305 wbinvd 306 307 movl lapic, %eax 308 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 309 310 lock 311 incl smp_tlb_wait 312 313 popl %ds 314 popl %eax 315 iret 316 317/* 318 * Handler for IPIs sent via the per-cpu IPI bitmap. 319 */ 320#ifndef XEN 321 .text 322 SUPERALIGN_TEXT 323IDTVEC(ipi_intr_bitmap_handler) 324 PUSH_FRAME 325 SET_KERNEL_SREGS 326 cld 327 328 movl lapic, %edx 329 movl $0, LA_EOI(%edx) /* End Of Interrupt to APIC */ 330 331 FAKE_MCOUNT(TF_EIP(%esp)) 332 333 call ipi_bitmap_handler 334 MEXITCOUNT 335 jmp doreti 336#endif 337/* 338 * Executed by a CPU when it receives an IPI_STOP from another CPU. 339 */ 340 .text 341 SUPERALIGN_TEXT 342IDTVEC(cpustop) 343 PUSH_FRAME 344 SET_KERNEL_SREGS 345 cld 346 347 movl lapic, %eax 348 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 349 350 call cpustop_handler 351 352 POP_FRAME 353 iret 354 355/* 356 * Executed by a CPU when it receives an IPI_SUSPEND from another CPU. 357 */ 358#ifndef XEN 359 .text 360 SUPERALIGN_TEXT 361IDTVEC(cpususpend) 362 PUSH_FRAME 363 SET_KERNEL_SREGS 364 cld 365 366 movl lapic, %eax 367 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 368 369 call cpususpend_handler 370 371 POP_FRAME 372 jmp doreti_iret 373#endif 374 375/* 376 * Executed by a CPU when it receives a RENDEZVOUS IPI from another CPU. 377 * 378 * - Calls the generic rendezvous action function. 379 */ 380 .text 381 SUPERALIGN_TEXT 382IDTVEC(rendezvous) 383 PUSH_FRAME 384 SET_KERNEL_SREGS 385 cld 386 387#ifdef COUNT_IPIS 388 movl PCPU(CPUID), %eax 389 movl ipi_rendezvous_counts(,%eax,4), %eax 390 incl (%eax) 391#endif 392 call smp_rendezvous_action 393 394 movl lapic, %eax 395 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 396 POP_FRAME 397 iret 398 399/* 400 * Clean up when we lose out on the lazy context switch optimization. 401 * ie: when we are about to release a PTD but a cpu is still borrowing it. 402 */ 403 SUPERALIGN_TEXT 404IDTVEC(lazypmap) 405 PUSH_FRAME 406 SET_KERNEL_SREGS 407 cld 408 409 call pmap_lazyfix_action 410 411 movl lapic, %eax 412 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 413 POP_FRAME 414 iret 415#endif /* SMP */ 416