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$ 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#ifdef SMP 47#define LK lock ; 48#else 49#define LK 50#endif 51 52/* 53 * I/O Interrupt Entry Point. Rather than having one entry point for 54 * each interrupt source, we use one entry point for each 32-bit word 55 * in the ISR. The handler determines the highest bit set in the ISR, 56 * translates that into a vector, and passes the vector to the 57 * lapic_handle_intr() function. 58 */ 59#define ISR_VEC(index, vec_name) \ 60 .text ; \ 61 SUPERALIGN_TEXT ; \ 62IDTVEC(vec_name) ; \ 63 PUSH_FRAME ; \ 64 FAKE_MCOUNT(TF_RIP(%rsp)) ; \ 65 movq lapic, %rdx ; /* pointer to local APIC */ \ 66 movl LA_ISR + 16 * (index)(%rdx), %eax ; /* load ISR */ \ 67 bsrl %eax, %eax ; /* index of highest set bit in ISR */ \ 68 jz 1f ; \ 69 addl $(32 * index),%eax ; \ 70 movq %rsp, %rsi ; \ 71 movl %eax, %edi ; /* pass the IRQ */ \ 72 call lapic_handle_intr ; \ 731: ; \ 74 MEXITCOUNT ; \ 75 jmp doreti 76 77/* 78 * Handle "spurious INTerrupts". 79 * Notes: 80 * This is different than the "spurious INTerrupt" generated by an 81 * 8259 PIC for missing INTs. See the APIC documentation for details. 82 * This routine should NOT do an 'EOI' cycle. 83 */ 84 .text 85 SUPERALIGN_TEXT 86IDTVEC(spuriousint) 87 88 /* No EOI cycle used here */ 89 90 jmp doreti_iret 91 92 ISR_VEC(1, apic_isr1) 93 ISR_VEC(2, apic_isr2) 94 ISR_VEC(3, apic_isr3) 95 ISR_VEC(4, apic_isr4) 96 ISR_VEC(5, apic_isr5) 97 ISR_VEC(6, apic_isr6) 98 ISR_VEC(7, apic_isr7) 99 100/* 101 * Local APIC periodic timer handler. 102 */ 103 .text 104 SUPERALIGN_TEXT 105IDTVEC(timerint) 106 PUSH_FRAME 107 FAKE_MCOUNT(TF_RIP(%rsp)) 108 movq %rsp, %rdi 109 call lapic_handle_timer 110 MEXITCOUNT 111 jmp doreti 112 113/* 114 * Local APIC CMCI handler. 115 */ 116 .text 117 SUPERALIGN_TEXT 118IDTVEC(cmcint) 119 PUSH_FRAME 120 FAKE_MCOUNT(TF_RIP(%rsp)) 121 call lapic_handle_cmc 122 MEXITCOUNT 123 jmp doreti 124 125/* 126 * Local APIC error interrupt handler. 127 */ 128 .text 129 SUPERALIGN_TEXT 130IDTVEC(errorint) 131 PUSH_FRAME 132 FAKE_MCOUNT(TF_RIP(%rsp)) 133 call lapic_handle_error 134 MEXITCOUNT 135 jmp doreti 136 137#ifdef XENHVM 138/* 139 * Xen event channel upcall interrupt handler. 140 * Only used when the hypervisor supports direct vector callbacks. 141 */ 142 .text 143 SUPERALIGN_TEXT 144IDTVEC(xen_intr_upcall) 145 PUSH_FRAME 146 FAKE_MCOUNT(TF_RIP(%rsp)) 147 movq %rsp, %rdi 148 call xen_intr_handle_upcall 149 MEXITCOUNT 150 jmp doreti 151#endif 152 153#ifdef SMP 154/* 155 * Global address space TLB shootdown. 156 */ 157 .text 158 159 SUPERALIGN_TEXT 160invltlb_ret: 161 movq lapic, %rax 162 movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */ 163 POP_FRAME 164 jmp doreti_iret 165 166 SUPERALIGN_TEXT 167IDTVEC(invltlb_pcid) 168 PUSH_FRAME 169 170 call invltlb_pcid_handler 171 jmp invltlb_ret 172 173 174 SUPERALIGN_TEXT 175IDTVEC(invltlb) 176 PUSH_FRAME 177 178 call invltlb_handler 179 jmp invltlb_ret 180 181/* 182 * Single page TLB shootdown 183 */ 184 .text 185 SUPERALIGN_TEXT 186IDTVEC(invlpg_pcid) 187 PUSH_FRAME 188 189 call invlpg_pcid_handler 190 jmp invltlb_ret 191 192 SUPERALIGN_TEXT 193IDTVEC(invlpg) 194 PUSH_FRAME 195 196 call invlpg_handler 197 jmp invltlb_ret 198 199/* 200 * Page range TLB shootdown. 201 */ 202 .text 203 SUPERALIGN_TEXT 204IDTVEC(invlrng) 205 PUSH_FRAME 206 207 call invlrng_handler 208 jmp invltlb_ret 209 210/* 211 * Invalidate cache. 212 */ 213 .text 214 SUPERALIGN_TEXT 215IDTVEC(invlcache) 216 PUSH_FRAME 217 218 call invlcache_handler 219 jmp invltlb_ret 220 221/* 222 * Handler for IPIs sent via the per-cpu IPI bitmap. 223 */ 224 .text 225 SUPERALIGN_TEXT 226IDTVEC(ipi_intr_bitmap_handler) 227 PUSH_FRAME 228 229 movq lapic, %rdx 230 movl $0, LA_EOI(%rdx) /* End Of Interrupt to APIC */ 231 232 FAKE_MCOUNT(TF_RIP(%rsp)) 233 234 call ipi_bitmap_handler 235 MEXITCOUNT 236 jmp doreti 237 238/* 239 * Executed by a CPU when it receives an IPI_STOP from another CPU. 240 */ 241 .text 242 SUPERALIGN_TEXT 243IDTVEC(cpustop) 244 PUSH_FRAME 245 246 movq lapic, %rax 247 movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */ 248 249 call cpustop_handler 250 jmp doreti 251 252/* 253 * Executed by a CPU when it receives an IPI_SUSPEND from another CPU. 254 */ 255 .text 256 SUPERALIGN_TEXT 257IDTVEC(cpususpend) 258 PUSH_FRAME 259 260 call cpususpend_handler 261 movq lapic, %rax 262 movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */ 263 jmp doreti 264 265/* 266 * Executed by a CPU when it receives a RENDEZVOUS IPI from another CPU. 267 * 268 * - Calls the generic rendezvous action function. 269 */ 270 .text 271 SUPERALIGN_TEXT 272IDTVEC(rendezvous) 273 PUSH_FRAME 274#ifdef COUNT_IPIS 275 movl PCPU(CPUID), %eax 276 movq ipi_rendezvous_counts(,%rax,8), %rax 277 incq (%rax) 278#endif 279 call smp_rendezvous_action 280 movq lapic, %rax 281 movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */ 282 jmp doreti 283#endif /* SMP */ 284