]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/i386/i386/apic_vector.s
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / i386 / i386 / apic_vector.s
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 /*
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 ;                                               \
56 IDTVEC(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 */                 \
70 1: ;                                                                    \
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
83 IDTVEC(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
102 IDTVEC(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
118 IDTVEC(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
132 IDTVEC(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
148 IDTVEC(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
166 IDTVEC(invltlb)
167         pushl   %eax
168         pushl   %ds
169         movl    $KDSEL, %eax            /* Kernel data selector */
170         movl    %eax, %ds
171
172 #if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
173         pushl   %fs
174         movl    $KPSEL, %eax            /* Private space selector */
175         movl    %eax, %fs
176         movl    PCPU(CPUID), %eax
177         popl    %fs
178 #ifdef COUNT_XINVLTLB_HITS
179         incl    xhits_gbl(,%eax,4)
180 #endif
181 #ifdef COUNT_IPIS
182         movl    ipi_invltlb_counts(,%eax,4),%eax
183         incl    (%eax)
184 #endif
185 #endif
186
187         movl    %cr3, %eax              /* invalidate the TLB */
188         movl    %eax, %cr3
189
190         movl    lapic, %eax
191         movl    $0, LA_EOI(%eax)        /* End Of Interrupt to APIC */
192
193         lock
194         incl    smp_tlb_wait
195
196         popl    %ds
197         popl    %eax
198         iret
199
200 /*
201  * Single page TLB shootdown
202  */
203         .text
204         SUPERALIGN_TEXT
205 IDTVEC(invlpg)
206         pushl   %eax
207         pushl   %ds
208         movl    $KDSEL, %eax            /* Kernel data selector */
209         movl    %eax, %ds
210
211 #if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
212         pushl   %fs
213         movl    $KPSEL, %eax            /* Private space selector */
214         movl    %eax, %fs
215         movl    PCPU(CPUID), %eax
216         popl    %fs
217 #ifdef COUNT_XINVLTLB_HITS
218         incl    xhits_pg(,%eax,4)
219 #endif
220 #ifdef COUNT_IPIS
221         movl    ipi_invlpg_counts(,%eax,4),%eax
222         incl    (%eax)
223 #endif
224 #endif
225
226         movl    smp_tlb_addr1, %eax
227         invlpg  (%eax)                  /* invalidate single page */
228
229         movl    lapic, %eax
230         movl    $0, LA_EOI(%eax)        /* End Of Interrupt to APIC */
231
232         lock
233         incl    smp_tlb_wait
234
235         popl    %ds
236         popl    %eax
237         iret
238
239 /*
240  * Page range TLB shootdown.
241  */
242         .text
243         SUPERALIGN_TEXT
244 IDTVEC(invlrng)
245         pushl   %eax
246         pushl   %edx
247         pushl   %ds
248         movl    $KDSEL, %eax            /* Kernel data selector */
249         movl    %eax, %ds
250
251 #if defined(COUNT_XINVLTLB_HITS) || defined(COUNT_IPIS)
252         pushl   %fs
253         movl    $KPSEL, %eax            /* Private space selector */
254         movl    %eax, %fs
255         movl    PCPU(CPUID), %eax
256         popl    %fs
257 #ifdef COUNT_XINVLTLB_HITS
258         incl    xhits_rng(,%eax,4)
259 #endif
260 #ifdef COUNT_IPIS
261         movl    ipi_invlrng_counts(,%eax,4),%eax
262         incl    (%eax)
263 #endif
264 #endif
265
266         movl    smp_tlb_addr1, %edx
267         movl    smp_tlb_addr2, %eax
268 1:      invlpg  (%edx)                  /* invalidate single page */
269         addl    $PAGE_SIZE, %edx
270         cmpl    %eax, %edx
271         jb      1b
272
273         movl    lapic, %eax
274         movl    $0, LA_EOI(%eax)        /* End Of Interrupt to APIC */
275
276         lock
277         incl    smp_tlb_wait
278
279         popl    %ds
280         popl    %edx
281         popl    %eax
282         iret
283
284 /*
285  * Invalidate cache.
286  */
287         .text
288         SUPERALIGN_TEXT
289 IDTVEC(invlcache)
290         pushl   %eax
291         pushl   %ds
292         movl    $KDSEL, %eax            /* Kernel data selector */
293         movl    %eax, %ds
294
295 #ifdef COUNT_IPIS
296         pushl   %fs
297         movl    $KPSEL, %eax            /* Private space selector */
298         movl    %eax, %fs
299         movl    PCPU(CPUID), %eax
300         popl    %fs
301         movl    ipi_invlcache_counts(,%eax,4),%eax
302         incl    (%eax)
303 #endif
304
305         wbinvd
306
307         movl    lapic, %eax
308         movl    $0, LA_EOI(%eax)        /* End Of Interrupt to APIC */
309
310         lock
311         incl    smp_tlb_wait
312
313         popl    %ds
314         popl    %eax
315         iret
316
317 /*
318  * Handler for IPIs sent via the per-cpu IPI bitmap.
319  */
320 #ifndef XEN
321         .text
322         SUPERALIGN_TEXT
323 IDTVEC(ipi_intr_bitmap_handler) 
324         PUSH_FRAME
325         SET_KERNEL_SREGS
326         cld
327
328         movl    lapic, %edx
329         movl    $0, LA_EOI(%edx)        /* End Of Interrupt to APIC */
330         
331         FAKE_MCOUNT(TF_EIP(%esp))
332
333         call    ipi_bitmap_handler
334         MEXITCOUNT
335         jmp     doreti
336 #endif
337 /*
338  * Executed by a CPU when it receives an IPI_STOP from another CPU.
339  */
340         .text
341         SUPERALIGN_TEXT
342 IDTVEC(cpustop)
343         PUSH_FRAME
344         SET_KERNEL_SREGS
345         cld
346
347         movl    lapic, %eax
348         movl    $0, LA_EOI(%eax)        /* End Of Interrupt to APIC */
349
350         call    cpustop_handler
351
352         POP_FRAME
353         iret
354
355 /*
356  * Executed by a CPU when it receives an IPI_SUSPEND from another CPU.
357  */
358 #ifndef XEN
359         .text
360         SUPERALIGN_TEXT
361 IDTVEC(cpususpend)
362         PUSH_FRAME
363         SET_KERNEL_SREGS
364         cld
365
366         movl    lapic, %eax
367         movl    $0, LA_EOI(%eax)        /* End Of Interrupt to APIC */
368
369         call    cpususpend_handler
370
371         POP_FRAME
372         jmp     doreti_iret
373 #endif
374
375 /*
376  * Executed by a CPU when it receives a RENDEZVOUS IPI from another CPU.
377  *
378  * - Calls the generic rendezvous action function.
379  */
380         .text
381         SUPERALIGN_TEXT
382 IDTVEC(rendezvous)
383         PUSH_FRAME
384         SET_KERNEL_SREGS
385         cld
386
387 #ifdef COUNT_IPIS
388         movl    PCPU(CPUID), %eax
389         movl    ipi_rendezvous_counts(,%eax,4), %eax
390         incl    (%eax)
391 #endif
392         call    smp_rendezvous_action
393
394         movl    lapic, %eax
395         movl    $0, LA_EOI(%eax)        /* End Of Interrupt to APIC */
396         POP_FRAME
397         iret
398         
399 /*
400  * Clean up when we lose out on the lazy context switch optimization.
401  * ie: when we are about to release a PTD but a cpu is still borrowing it.
402  */
403         SUPERALIGN_TEXT
404 IDTVEC(lazypmap)
405         PUSH_FRAME
406         SET_KERNEL_SREGS
407         cld
408
409         call    pmap_lazyfix_action
410
411         movl    lapic, %eax
412         movl    $0, LA_EOI(%eax)        /* End Of Interrupt to APIC */
413         POP_FRAME
414         iret
415 #endif /* SMP */