apic_vector.s revision 208507
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 208507 2010-05-24 15:45:05Z jhb $ 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 <machine/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 FAKE_MCOUNT(TF_EIP(%esp)) ; \ 60 movl lapic, %edx ; /* pointer to local APIC */ \ 61 movl LA_ISR + 16 * (index)(%edx), %eax ; /* load ISR */ \ 62 bsrl %eax, %eax ; /* index of highset set bit in ISR */ \ 63 jz 2f ; \ 64 addl $(32 * index),%eax ; \ 651: ; \ 66 pushl %esp ; \ 67 pushl %eax ; /* pass the IRQ */ \ 68 call lapic_handle_intr ; \ 69 addl $8, %esp ; /* discard parameter */ \ 70 MEXITCOUNT ; \ 71 jmp doreti ; \ 722: movl $-1, %eax ; /* send a vector of -1 */ \ 73 jmp 1b 74 75/* 76 * Handle "spurious INTerrupts". 77 * Notes: 78 * This is different than the "spurious INTerrupt" generated by an 79 * 8259 PIC for missing INTs. See the APIC documentation for details. 80 * This routine should NOT do an 'EOI' cycle. 81 */ 82 .text 83 SUPERALIGN_TEXT 84IDTVEC(spuriousint) 85 86 /* No EOI cycle used here */ 87 88 iret 89 90 ISR_VEC(1, apic_isr1) 91 ISR_VEC(2, apic_isr2) 92 ISR_VEC(3, apic_isr3) 93 ISR_VEC(4, apic_isr4) 94 ISR_VEC(5, apic_isr5) 95 ISR_VEC(6, apic_isr6) 96 ISR_VEC(7, apic_isr7) 97 98/* 99 * Local APIC periodic timer handler. 100 */ 101 .text 102 SUPERALIGN_TEXT 103IDTVEC(timerint) 104 PUSH_FRAME 105 SET_KERNEL_SREGS 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 FAKE_MCOUNT(TF_EIP(%esp)) 122 call lapic_handle_cmc 123 MEXITCOUNT 124 jmp doreti 125 126/* 127 * Local APIC error interrupt handler. 128 */ 129 .text 130 SUPERALIGN_TEXT 131IDTVEC(errorint) 132 PUSH_FRAME 133 SET_KERNEL_SREGS 134 FAKE_MCOUNT(TF_EIP(%esp)) 135 call lapic_handle_error 136 MEXITCOUNT 137 jmp doreti 138 139#ifdef SMP 140/* 141 * Global address space TLB shootdown. 142 */ 143 .text 144 SUPERALIGN_TEXT 145IDTVEC(invltlb) 146 pushl %eax 147 pushl %ds 148 movl $KDSEL, %eax /* Kernel data selector */ 149 movl %eax, %ds 150 151#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS) 152 pushl %fs 153 movl $KPSEL, %eax /* Private space selector */ 154 movl %eax, %fs 155 movl PCPU(CPUID), %eax 156 popl %fs 157#ifdef COUNT_XINVLTLB_HITS 158 incl xhits_gbl(,%eax,4) 159#endif 160#ifdef COUNT_IPIS 161 movl ipi_invltlb_counts(,%eax,4),%eax 162 incl (%eax) 163#endif 164#endif 165 166 movl %cr3, %eax /* invalidate the TLB */ 167 movl %eax, %cr3 168 169 movl lapic, %eax 170 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 171 172 lock 173 incl smp_tlb_wait 174 175 popl %ds 176 popl %eax 177 iret 178 179/* 180 * Single page TLB shootdown 181 */ 182 .text 183 SUPERALIGN_TEXT 184IDTVEC(invlpg) 185 pushl %eax 186 pushl %ds 187 movl $KDSEL, %eax /* Kernel data selector */ 188 movl %eax, %ds 189 190#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS) 191 pushl %fs 192 movl $KPSEL, %eax /* Private space selector */ 193 movl %eax, %fs 194 movl PCPU(CPUID), %eax 195 popl %fs 196#ifdef COUNT_XINVLTLB_HITS 197 incl xhits_pg(,%eax,4) 198#endif 199#ifdef COUNT_IPIS 200 movl ipi_invlpg_counts(,%eax,4),%eax 201 incl (%eax) 202#endif 203#endif 204 205 movl smp_tlb_addr1, %eax 206 invlpg (%eax) /* invalidate single page */ 207 208 movl lapic, %eax 209 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 210 211 lock 212 incl smp_tlb_wait 213 214 popl %ds 215 popl %eax 216 iret 217 218/* 219 * Page range TLB shootdown. 220 */ 221 .text 222 SUPERALIGN_TEXT 223IDTVEC(invlrng) 224 pushl %eax 225 pushl %edx 226 pushl %ds 227 movl $KDSEL, %eax /* Kernel data selector */ 228 movl %eax, %ds 229 230#if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS) 231 pushl %fs 232 movl $KPSEL, %eax /* Private space selector */ 233 movl %eax, %fs 234 movl PCPU(CPUID), %eax 235 popl %fs 236#ifdef COUNT_XINVLTLB_HITS 237 incl xhits_rng(,%eax,4) 238#endif 239#ifdef COUNT_IPIS 240 movl ipi_invlrng_counts(,%eax,4),%eax 241 incl (%eax) 242#endif 243#endif 244 245 movl smp_tlb_addr1, %edx 246 movl smp_tlb_addr2, %eax 2471: invlpg (%edx) /* invalidate single page */ 248 addl $PAGE_SIZE, %edx 249 cmpl %eax, %edx 250 jb 1b 251 252 movl lapic, %eax 253 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 254 255 lock 256 incl smp_tlb_wait 257 258 popl %ds 259 popl %edx 260 popl %eax 261 iret 262 263/* 264 * Invalidate cache. 265 */ 266 .text 267 SUPERALIGN_TEXT 268IDTVEC(invlcache) 269 pushl %eax 270 pushl %ds 271 movl $KDSEL, %eax /* Kernel data selector */ 272 movl %eax, %ds 273 274#ifdef COUNT_IPIS 275 pushl %fs 276 movl $KPSEL, %eax /* Private space selector */ 277 movl %eax, %fs 278 movl PCPU(CPUID), %eax 279 popl %fs 280 movl ipi_invlcache_counts(,%eax,4),%eax 281 incl (%eax) 282#endif 283 284 wbinvd 285 286 movl lapic, %eax 287 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 288 289 lock 290 incl smp_tlb_wait 291 292 popl %ds 293 popl %eax 294 iret 295 296/* 297 * Handler for IPIs sent via the per-cpu IPI bitmap. 298 */ 299#ifndef XEN 300 .text 301 SUPERALIGN_TEXT 302IDTVEC(ipi_intr_bitmap_handler) 303 PUSH_FRAME 304 SET_KERNEL_SREGS 305 306 movl lapic, %edx 307 movl $0, LA_EOI(%edx) /* End Of Interrupt to APIC */ 308 309 FAKE_MCOUNT(TF_EIP(%esp)) 310 311 call ipi_bitmap_handler 312 MEXITCOUNT 313 jmp doreti 314#endif 315/* 316 * Executed by a CPU when it receives an IPI_STOP from another CPU. 317 */ 318 .text 319 SUPERALIGN_TEXT 320IDTVEC(cpustop) 321 PUSH_FRAME 322 SET_KERNEL_SREGS 323 324 movl lapic, %eax 325 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 326 327 call cpustop_handler 328 329 POP_FRAME 330 iret 331 332/* 333 * Executed by a CPU when it receives a RENDEZVOUS IPI from another CPU. 334 * 335 * - Calls the generic rendezvous action function. 336 */ 337 .text 338 SUPERALIGN_TEXT 339IDTVEC(rendezvous) 340 PUSH_FRAME 341 SET_KERNEL_SREGS 342 343#ifdef COUNT_IPIS 344 movl PCPU(CPUID), %eax 345 movl ipi_rendezvous_counts(,%eax,4), %eax 346 incl (%eax) 347#endif 348 call smp_rendezvous_action 349 350 movl lapic, %eax 351 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 352 POP_FRAME 353 iret 354 355/* 356 * Clean up when we lose out on the lazy context switch optimization. 357 * ie: when we are about to release a PTD but a cpu is still borrowing it. 358 */ 359 SUPERALIGN_TEXT 360IDTVEC(lazypmap) 361 PUSH_FRAME 362 SET_KERNEL_SREGS 363 364 call pmap_lazyfix_action 365 366 movl lapic, %eax 367 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 368 POP_FRAME 369 iret 370#endif /* SMP */ 371