apic_vector.s revision 302041
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: stable/10/sys/i386/i386/apic_vector.s 302041 2016-06-21 04:51:55Z sephe $ 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 166invltlb_ret: 167 movl lapic, %eax 168 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 169 POP_FRAME 170 iret 171 172 SUPERALIGN_TEXT 173IDTVEC(invltlb) 174 PUSH_FRAME 175 SET_KERNEL_SREGS 176 cld 177 178 call invltlb_handler 179 180 jmp invltlb_ret 181 182/* 183 * Single page TLB shootdown 184 */ 185 .text 186 SUPERALIGN_TEXT 187IDTVEC(invlpg) 188 PUSH_FRAME 189 SET_KERNEL_SREGS 190 cld 191 192 call invlpg_handler 193 194 jmp invltlb_ret 195 196/* 197 * Page range TLB shootdown. 198 */ 199 .text 200 SUPERALIGN_TEXT 201IDTVEC(invlrng) 202 PUSH_FRAME 203 SET_KERNEL_SREGS 204 cld 205 206 call invlrng_handler 207 208 jmp invltlb_ret 209 210/* 211 * Invalidate cache. 212 */ 213 .text 214 SUPERALIGN_TEXT 215IDTVEC(invlcache) 216 PUSH_FRAME 217 SET_KERNEL_SREGS 218 cld 219 220 call invlcache_handler 221 222 jmp invltlb_ret 223 224/* 225 * Handler for IPIs sent via the per-cpu IPI bitmap. 226 */ 227#ifndef XEN 228 .text 229 SUPERALIGN_TEXT 230IDTVEC(ipi_intr_bitmap_handler) 231 PUSH_FRAME 232 SET_KERNEL_SREGS 233 cld 234 235 movl lapic, %edx 236 movl $0, LA_EOI(%edx) /* End Of Interrupt to APIC */ 237 238 FAKE_MCOUNT(TF_EIP(%esp)) 239 240 call ipi_bitmap_handler 241 MEXITCOUNT 242 jmp doreti 243#endif 244/* 245 * Executed by a CPU when it receives an IPI_STOP from another CPU. 246 */ 247 .text 248 SUPERALIGN_TEXT 249IDTVEC(cpustop) 250 PUSH_FRAME 251 SET_KERNEL_SREGS 252 cld 253 254 movl lapic, %eax 255 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 256 257 call cpustop_handler 258 259 POP_FRAME 260 iret 261 262/* 263 * Executed by a CPU when it receives an IPI_SUSPEND from another CPU. 264 */ 265#ifndef XEN 266 .text 267 SUPERALIGN_TEXT 268IDTVEC(cpususpend) 269 PUSH_FRAME 270 SET_KERNEL_SREGS 271 cld 272 273 movl lapic, %eax 274 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 275 276 call cpususpend_handler 277 278 POP_FRAME 279 jmp doreti_iret 280#endif 281 282/* 283 * Executed by a CPU when it receives a RENDEZVOUS IPI from another CPU. 284 * 285 * - Calls the generic rendezvous action function. 286 */ 287 .text 288 SUPERALIGN_TEXT 289IDTVEC(rendezvous) 290 PUSH_FRAME 291 SET_KERNEL_SREGS 292 cld 293 294#ifdef COUNT_IPIS 295 movl PCPU(CPUID), %eax 296 movl ipi_rendezvous_counts(,%eax,4), %eax 297 incl (%eax) 298#endif 299 call smp_rendezvous_action 300 301 movl lapic, %eax 302 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 303 POP_FRAME 304 iret 305 306/* 307 * Clean up when we lose out on the lazy context switch optimization. 308 * ie: when we are about to release a PTD but a cpu is still borrowing it. 309 */ 310 SUPERALIGN_TEXT 311IDTVEC(lazypmap) 312 PUSH_FRAME 313 SET_KERNEL_SREGS 314 cld 315 316 call pmap_lazyfix_action 317 318 movl lapic, %eax 319 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 320 POP_FRAME 321 iret 322#endif /* SMP */ 323