apic_vector.s revision 141538
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 141538 2005-02-08 20:25:07Z 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 <machine/asmacros.h> 40#include <machine/apicreg.h> 41#include <machine/smptests.h> 42 43#include "assym.s" 44 45/* 46 * Macros to create and destroy a trap frame. 47 */ 48#define PUSH_FRAME \ 49 pushl $0 ; /* dummy error code */ \ 50 pushl $0 ; /* dummy trap type */ \ 51 pushal ; /* 8 ints */ \ 52 pushl %ds ; /* save data and extra segments ... */ \ 53 pushl %es ; \ 54 pushl %fs 55 56#define POP_FRAME \ 57 popl %fs ; \ 58 popl %es ; \ 59 popl %ds ; \ 60 popal ; \ 61 addl $4+4,%esp 62 63/* 64 * I/O Interrupt Entry Point. Rather than having one entry point for 65 * each interrupt source, we use one entry point for each 32-bit word 66 * in the ISR. The handler determines the highest bit set in the ISR, 67 * translates that into a vector, and passes the vector to the 68 * lapic_handle_intr() function. 69 */ 70#define ISR_VEC(index, vec_name) \ 71 .text ; \ 72 SUPERALIGN_TEXT ; \ 73IDTVEC(vec_name) ; \ 74 PUSH_FRAME ; \ 75 movl $KDSEL, %eax ; /* reload with kernel's data segment */ \ 76 movl %eax, %ds ; \ 77 movl %eax, %es ; \ 78 movl $KPSEL, %eax ; /* reload with per-CPU data segment */ \ 79 movl %eax, %fs ; \ 80 FAKE_MCOUNT(TF_EIP(%esp)) ; \ 81 movl lapic, %edx ; /* pointer to local APIC */ \ 82 movl LA_ISR + 16 * (index)(%edx), %eax ; /* load ISR */ \ 83 bsrl %eax, %eax ; /* index of highset set bit in ISR */ \ 84 jz 2f ; \ 85 addl $(32 * index),%eax ; \ 861: ; \ 87 pushl %eax ; /* pass the IRQ */ \ 88 call lapic_handle_intr ; \ 89 addl $4, %esp ; /* discard parameter */ \ 90 MEXITCOUNT ; \ 91 jmp doreti ; \ 922: movl $-1, %eax ; /* send a vector of -1 */ \ 93 jmp 1b 94 95/* 96 * Handle "spurious INTerrupts". 97 * Notes: 98 * This is different than the "spurious INTerrupt" generated by an 99 * 8259 PIC for missing INTs. See the APIC documentation for details. 100 * This routine should NOT do an 'EOI' cycle. 101 */ 102 .text 103 SUPERALIGN_TEXT 104IDTVEC(spuriousint) 105 106 /* No EOI cycle used here */ 107 108 iret 109 110 ISR_VEC(1, apic_isr1) 111 ISR_VEC(2, apic_isr2) 112 ISR_VEC(3, apic_isr3) 113 ISR_VEC(4, apic_isr4) 114 ISR_VEC(5, apic_isr5) 115 ISR_VEC(6, apic_isr6) 116 ISR_VEC(7, apic_isr7) 117 118/* 119 * Local APIC periodic timer handler. 120 */ 121 .text 122 SUPERALIGN_TEXT 123IDTVEC(timerint) 124 PUSH_FRAME 125 movl $KDSEL, %eax /* reload with kernel's data segment */ 126 movl %eax, %ds 127 movl %eax, %es 128 movl $KPSEL, %eax 129 movl %eax, %fs 130 131 movl lapic, %edx 132 movl $0, LA_EOI(%edx) /* End Of Interrupt to APIC */ 133 134 FAKE_MCOUNT(TF_EIP(%esp)) 135 136 pushl $0 /* XXX convert trapframe to clockframe */ 137 call lapic_handle_timer 138 addl $4, %esp /* XXX convert clockframe to trapframe */ 139 MEXITCOUNT 140 jmp doreti 141 142#ifdef SMP 143/* 144 * Global address space TLB shootdown. 145 */ 146 .text 147 SUPERALIGN_TEXT 148IDTVEC(invltlb) 149 pushl %eax 150 pushl %ds 151 movl $KDSEL, %eax /* Kernel data selector */ 152 movl %eax, %ds 153 154#ifdef COUNT_XINVLTLB_HITS 155 pushl %fs 156 movl $KPSEL, %eax /* Private space selector */ 157 movl %eax, %fs 158 movl PCPU(CPUID), %eax 159 popl %fs 160 incl xhits_gbl(,%eax,4) 161#endif /* COUNT_XINVLTLB_HITS */ 162 163 movl %cr3, %eax /* invalidate the TLB */ 164 movl %eax, %cr3 165 166 movl lapic, %eax 167 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 168 169 lock 170 incl smp_tlb_wait 171 172 popl %ds 173 popl %eax 174 iret 175 176/* 177 * Single page TLB shootdown 178 */ 179 .text 180 SUPERALIGN_TEXT 181IDTVEC(invlpg) 182 pushl %eax 183 pushl %ds 184 movl $KDSEL, %eax /* Kernel data selector */ 185 movl %eax, %ds 186 187#ifdef COUNT_XINVLTLB_HITS 188 pushl %fs 189 movl $KPSEL, %eax /* Private space selector */ 190 movl %eax, %fs 191 movl PCPU(CPUID), %eax 192 popl %fs 193 incl xhits_pg(,%eax,4) 194#endif /* COUNT_XINVLTLB_HITS */ 195 196 movl smp_tlb_addr1, %eax 197 invlpg (%eax) /* invalidate single page */ 198 199 movl lapic, %eax 200 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 201 202 lock 203 incl smp_tlb_wait 204 205 popl %ds 206 popl %eax 207 iret 208 209/* 210 * Page range TLB shootdown. 211 */ 212 .text 213 SUPERALIGN_TEXT 214IDTVEC(invlrng) 215 pushl %eax 216 pushl %edx 217 pushl %ds 218 movl $KDSEL, %eax /* Kernel data selector */ 219 movl %eax, %ds 220 221#ifdef COUNT_XINVLTLB_HITS 222 pushl %fs 223 movl $KPSEL, %eax /* Private space selector */ 224 movl %eax, %fs 225 movl PCPU(CPUID), %eax 226 popl %fs 227 incl xhits_rng(,%eax,4) 228#endif /* COUNT_XINVLTLB_HITS */ 229 230 movl smp_tlb_addr1, %edx 231 movl smp_tlb_addr2, %eax 2321: invlpg (%edx) /* invalidate single page */ 233 addl $PAGE_SIZE, %edx 234 cmpl %eax, %edx 235 jb 1b 236 237 movl lapic, %eax 238 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 239 240 lock 241 incl smp_tlb_wait 242 243 popl %ds 244 popl %edx 245 popl %eax 246 iret 247 248/* 249 * Forward hardclock to another CPU. Pushes a clockframe and calls 250 * forwarded_hardclock(). 251 */ 252 .text 253 SUPERALIGN_TEXT 254IDTVEC(ipi_intr_bitmap_handler) 255 256 PUSH_FRAME 257 movl $KDSEL, %eax /* reload with kernel's data segment */ 258 movl %eax, %ds 259 movl %eax, %es 260 movl $KPSEL, %eax 261 movl %eax, %fs 262 263 movl lapic, %edx 264 movl $0, LA_EOI(%edx) /* End Of Interrupt to APIC */ 265 266 FAKE_MCOUNT(TF_EIP(%esp)) 267 268 pushl $0 /* XXX convert trapframe to clockframe */ 269 call ipi_bitmap_handler 270 addl $4, %esp /* XXX convert clockframe to trapframe */ 271 MEXITCOUNT 272 jmp doreti 273 274/* 275 * Executed by a CPU when it receives an Xcpustop IPI from another CPU, 276 * 277 * - Signals its receipt. 278 * - Waits for permission to restart. 279 * - Signals its restart. 280 */ 281 .text 282 SUPERALIGN_TEXT 283IDTVEC(cpustop) 284 pushl %ebp 285 movl %esp, %ebp 286 pushl %eax 287 pushl %ecx 288 pushl %edx 289 pushl %ds /* save current data segment */ 290 pushl %es 291 pushl %fs 292 293 movl $KDSEL, %eax 294 movl %eax, %ds /* use KERNEL data segment */ 295 movl %eax, %es 296 movl $KPSEL, %eax 297 movl %eax, %fs 298 299 movl lapic, %eax 300 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 301 302 movl PCPU(CPUID), %eax 303 imull $PCB_SIZE, %eax 304 leal CNAME(stoppcbs)(%eax), %eax 305 pushl %eax 306 call CNAME(savectx) /* Save process context */ 307 addl $4, %esp 308 309 movl PCPU(CPUID), %eax 310 311 lock 312 btsl %eax, CNAME(stopped_cpus) /* stopped_cpus |= (1<<id) */ 3131: 314 btl %eax, CNAME(started_cpus) /* while (!(started_cpus & (1<<id))) */ 315 jnc 1b 316 317 lock 318 btrl %eax, CNAME(started_cpus) /* started_cpus &= ~(1<<id) */ 319 lock 320 btrl %eax, CNAME(stopped_cpus) /* stopped_cpus &= ~(1<<id) */ 321 322 test %eax, %eax 323 jnz 2f 324 325 movl CNAME(cpustop_restartfunc), %eax 326 test %eax, %eax 327 jz 2f 328 movl $0, CNAME(cpustop_restartfunc) /* One-shot */ 329 330 call *%eax 3312: 332 popl %fs 333 popl %es 334 popl %ds /* restore previous data segment */ 335 popl %edx 336 popl %ecx 337 popl %eax 338 movl %ebp, %esp 339 popl %ebp 340 iret 341 342/* 343 * Executed by a CPU when it receives a RENDEZVOUS IPI from another CPU. 344 * 345 * - Calls the generic rendezvous action function. 346 */ 347 .text 348 SUPERALIGN_TEXT 349IDTVEC(rendezvous) 350 PUSH_FRAME 351 movl $KDSEL, %eax 352 movl %eax, %ds /* use KERNEL data segment */ 353 movl %eax, %es 354 movl $KPSEL, %eax 355 movl %eax, %fs 356 357 call smp_rendezvous_action 358 359 movl lapic, %eax 360 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 361 POP_FRAME 362 iret 363 364/* 365 * Clean up when we lose out on the lazy context switch optimization. 366 * ie: when we are about to release a PTD but a cpu is still borrowing it. 367 */ 368 SUPERALIGN_TEXT 369IDTVEC(lazypmap) 370 PUSH_FRAME 371 movl $KDSEL, %eax 372 movl %eax, %ds /* use KERNEL data segment */ 373 movl %eax, %es 374 movl $KPSEL, %eax 375 movl %eax, %fs 376 377 call pmap_lazyfix_action 378 379 movl lapic, %eax 380 movl $0, LA_EOI(%eax) /* End Of Interrupt to APIC */ 381 POP_FRAME 382 iret 383#endif /* SMP */ 384