2 * Copyright (c) 1989, 1990 William F. Jolitz.
3 * Copyright (c) 1990 The Regents of the University of California.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
30 * from: vector.s, 386BSD 0.1 unknown origin
35 * Interrupt entry points for external interrupts triggered by I/O APICs
36 * as well as IPI handlers.
41 #include <machine/asmacros.h>
42 #include <x86/apicreg.h>
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.
59 #define ISR_VEC(index, vec_name) \
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 */ \
69 addl $(32 * index),%eax ; \
71 movl %eax, %edi ; /* pass the IRQ */ \
72 call lapic_handle_intr ; \
78 * Handle "spurious INTerrupts".
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.
88 /* No EOI cycle used here */
101 * Local APIC periodic timer handler.
107 FAKE_MCOUNT(TF_RIP(%rsp))
109 call lapic_handle_timer
114 * Local APIC CMCI handler.
120 FAKE_MCOUNT(TF_RIP(%rsp))
121 call lapic_handle_cmc
126 * Local APIC error interrupt handler.
132 FAKE_MCOUNT(TF_RIP(%rsp))
133 call lapic_handle_error
139 * Xen event channel upcall interrupt handler.
140 * Only used when the hypervisor supports direct vector callbacks.
144 IDTVEC(xen_intr_upcall)
146 FAKE_MCOUNT(TF_RIP(%rsp))
148 call xen_intr_handle_upcall
155 * Global address space TLB shootdown.
159 #define NAKE_INTR_CS 24
164 andq $~0x80,%rax /* PGE */
168 invltlb_ret_clear_pm_save:
169 movq smp_tlb_pmap,%rdx
172 testb $SEL_RPL_MASK,NAKE_INTR_CS(%rsp)
176 movl PCPU(CPUID),%eax
180 LK btcl %eax,PM_SAVE(%rdx)
186 movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */
193 #if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
195 movl PCPU(CPUID), %eax
196 #ifdef COUNT_XINVLTLB_HITS
197 incl xhits_gbl(,%rax,4)
200 movq ipi_invltlb_counts(,%rax,8),%rax
211 movq $smp_tlb_invpcid,%rdx
218 * Only invalidate TLB for entries with current PCID.
220 cmpl $0,invpcid_works
222 /* Use invpcid if available. */
223 movl $1,%eax /* INVPCID_CTX */
224 /* invpcid (%rdx),%rax */
225 .byte 0x66,0x0f,0x38,0x82,0x02
226 jmp invltlb_ret_clear_pm_save
228 /* Otherwise reload %cr3 twice. */
232 movq %rdx,%cr3 /* Invalidate, bit 63 is zero. */
236 jmp invltlb_ret_clear_pm_save
240 #if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
242 movl PCPU(CPUID), %eax
243 #ifdef COUNT_XINVLTLB_HITS
244 incl xhits_gbl(,%rax,4)
247 movq ipi_invltlb_counts(,%rax,8),%rax
254 movq %cr3, %rax /* invalidate the TLB */
259 * Single page TLB shootdown
264 #if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
266 movl PCPU(CPUID), %eax
267 #ifdef COUNT_XINVLTLB_HITS
268 incl xhits_pg(,%rax,4)
271 movq ipi_invlpg_counts(,%rax,8),%rax
279 movq $smp_tlb_invpcid,%rdx
280 cmpl $0,invpcid_works
283 /* kernel pmap - use invlpg to invalidate global mapping */
290 * PCID supported, but INVPCID is not.
291 * Temporarily switch to the target address space and do INVLPG.
308 * Invalidate the TLB entry using INVPCID_ADDR.
312 /* invpcid (%rdx),%rax */
313 .byte 0x66,0x0f,0x38,0x82,0x02
317 * PCID is not supported or kernel pmap.
318 * Invalidate single page using INVLPG.
327 #if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
329 movl PCPU(CPUID), %eax
330 #ifdef COUNT_XINVLTLB_HITS
331 incl xhits_pg(,%rax,4)
334 movq ipi_invlpg_counts(,%rax,8),%rax
341 movq smp_tlb_invpcid+8,%rax
342 invlpg (%rax) /* invalidate single page */
346 * Page range TLB shootdown.
351 #if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
353 movl PCPU(CPUID), %eax
354 #ifdef COUNT_XINVLTLB_HITS
355 incl xhits_rng(,%rax,4)
358 movq ipi_invlrng_counts(,%rax,8),%rax
366 movq $smp_tlb_invpcid,%rdx
367 cmpl $0,pmap_pcid_enabled
368 je invlrng_single_page
370 /* kernel pmap - use invlpg to invalidate global mapping */
372 je invlrng_single_page
375 cmpl $0,invpcid_works
387 movq smp_tlb_addr2,%rax
405 movq smp_tlb_addr2,%rcx
407 shrq $PAGE_SHIFT,%rcx
409 // invpcid (%rdx),%rax
410 .byte 0x66,0x0f,0x38,0x82,0x02
411 addq $PAGE_SIZE,8(%rsp)
420 movq smp_tlb_addr2,%rax
421 1: invlpg (%rdx) /* invalidate single page */
435 movl PCPU(CPUID), %eax
436 movq ipi_invlcache_counts(,%rax,8),%rax
446 * Handler for IPIs sent via the per-cpu IPI bitmap.
450 IDTVEC(ipi_intr_bitmap_handler)
454 movl $0, LA_EOI(%rdx) /* End Of Interrupt to APIC */
456 FAKE_MCOUNT(TF_RIP(%rsp))
458 call ipi_bitmap_handler
463 * Executed by a CPU when it receives an IPI_STOP from another CPU.
471 movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */
477 * Executed by a CPU when it receives an IPI_SUSPEND from another CPU.
484 call cpususpend_handler
486 movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */
490 * Executed by a CPU when it receives a RENDEZVOUS IPI from another CPU.
492 * - Calls the generic rendezvous action function.
499 movl PCPU(CPUID), %eax
500 movq ipi_rendezvous_counts(,%rax,8), %rax
503 call smp_rendezvous_action
505 movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */