Changeset View
Changeset View
Standalone View
Standalone View
sys/i386/i386/apic_vector.s
Show All 33 Lines | |||||
/* | /* | ||||
* Interrupt entry points for external interrupts triggered by I/O APICs | * Interrupt entry points for external interrupts triggered by I/O APICs | ||||
* as well as IPI handlers. | * as well as IPI handlers. | ||||
*/ | */ | ||||
#include "opt_smp.h" | #include "opt_smp.h" | ||||
#include <machine/asmacros.h> | #include <machine/asmacros.h> | ||||
#include <machine/psl.h> | |||||
#include <machine/specialreg.h> | #include <machine/specialreg.h> | ||||
#include <x86/apicreg.h> | #include <x86/apicreg.h> | ||||
#include "assym.inc" | #include "assym.inc" | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
/* End Of Interrupt to APIC */ | /* End Of Interrupt to APIC */ | ||||
Show All 12 Lines | |||||
/* | /* | ||||
* I/O Interrupt Entry Point. Rather than having one entry point for | * I/O Interrupt Entry Point. Rather than having one entry point for | ||||
* each interrupt source, we use one entry point for each 32-bit word | * each interrupt source, we use one entry point for each 32-bit word | ||||
* in the ISR. The handler determines the highest bit set in the ISR, | * in the ISR. The handler determines the highest bit set in the ISR, | ||||
* translates that into a vector, and passes the vector to the | * translates that into a vector, and passes the vector to the | ||||
* lapic_handle_intr() function. | * lapic_handle_intr() function. | ||||
*/ | */ | ||||
#define ISR_VEC(index, vec_name) \ | .macro ISR_VEC index, vec_name | ||||
.text ; \ | .text | ||||
SUPERALIGN_TEXT ; \ | SUPERALIGN_TEXT | ||||
IDTVEC(vec_name ## _pti) ; \ | .globl X\()\vec_name\()_pti, X\()\vec_name | ||||
IDTVEC(vec_name) ; \ | |||||
PUSH_FRAME ; \ | X\()\vec_name\()_pti: | ||||
SET_KERNEL_SREGS ; \ | X\()\vec_name: | ||||
cld ; \ | PUSH_FRAME | ||||
FAKE_MCOUNT(TF_EIP(%esp)) ; \ | SET_KERNEL_SREGS | ||||
cmpl $0,x2apic_mode ; \ | cld | ||||
je 1f ; \ | KENTER | ||||
movl $(MSR_APIC_ISR0 + index),%ecx ; \ | FAKE_MCOUNT(TF_EIP(%esp)) | ||||
rdmsr ; \ | cmpl $0,x2apic_mode | ||||
jmp 2f ; \ | je 2f | ||||
1: ; \ | movl $(MSR_APIC_ISR0 + \index),%ecx | ||||
movl lapic_map, %edx ;/* pointer to local APIC */ \ | rdmsr | ||||
movl LA_ISR + 16 * (index)(%edx), %eax ; /* load ISR */ \ | jmp 3f | ||||
2: ; \ | 2: | ||||
bsrl %eax, %eax ; /* index of highest set bit in ISR */ \ | movl lapic_map, %edx /* pointer to local APIC */ | ||||
jz 3f ; \ | movl LA_ISR + 16 * \index(%edx), %eax /* load ISR */ | ||||
addl $(32 * index),%eax ; \ | 3: | ||||
pushl %esp ; \ | bsrl %eax, %eax /* index of highest set bit in ISR */ | ||||
pushl %eax ; /* pass the IRQ */ \ | jz 4f | ||||
call lapic_handle_intr ; \ | addl $(32 * \index),%eax | ||||
addl $8, %esp ; /* discard parameter */ \ | pushl %esp | ||||
3: ; \ | pushl %eax /* pass the IRQ */ | ||||
MEXITCOUNT ; \ | movl $lapic_handle_intr, %eax | ||||
call *%eax | |||||
addl $8, %esp /* discard parameter */ | |||||
4: | |||||
MEXITCOUNT | |||||
jmp doreti | jmp doreti | ||||
.endm | |||||
/* | /* | ||||
* Handle "spurious INTerrupts". | * Handle "spurious INTerrupts". | ||||
* Notes: | * Notes: | ||||
* This is different than the "spurious INTerrupt" generated by an | * This is different than the "spurious INTerrupt" generated by an | ||||
* 8259 PIC for missing INTs. See the APIC documentation for details. | * 8259 PIC for missing INTs. See the APIC documentation for details. | ||||
* This routine should NOT do an 'EOI' cycle. | * This routine should NOT do an 'EOI' cycle. | ||||
*/ | */ | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
IDTVEC(spuriousint) | IDTVEC(spuriousint) | ||||
/* No EOI cycle used here */ | /* No EOI cycle used here */ | ||||
iret | iret | ||||
ISR_VEC(1, apic_isr1) | ISR_VEC 1, apic_isr1 | ||||
ISR_VEC(2, apic_isr2) | ISR_VEC 2, apic_isr2 | ||||
ISR_VEC(3, apic_isr3) | ISR_VEC 3, apic_isr3 | ||||
ISR_VEC(4, apic_isr4) | ISR_VEC 4, apic_isr4 | ||||
ISR_VEC(5, apic_isr5) | ISR_VEC 5, apic_isr5 | ||||
ISR_VEC(6, apic_isr6) | ISR_VEC 6, apic_isr6 | ||||
ISR_VEC(7, apic_isr7) | ISR_VEC 7, apic_isr7 | ||||
/* | /* | ||||
* Local APIC periodic timer handler. | * Local APIC periodic timer handler. | ||||
*/ | */ | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
IDTVEC(timerint_pti) | IDTVEC(timerint_pti) | ||||
IDTVEC(timerint) | IDTVEC(timerint) | ||||
PUSH_FRAME | PUSH_FRAME | ||||
SET_KERNEL_SREGS | SET_KERNEL_SREGS | ||||
cld | cld | ||||
KENTER | |||||
FAKE_MCOUNT(TF_EIP(%esp)) | FAKE_MCOUNT(TF_EIP(%esp)) | ||||
pushl %esp | pushl %esp | ||||
call lapic_handle_timer | movl $lapic_handle_timer, %eax | ||||
call *%eax | |||||
add $4, %esp | add $4, %esp | ||||
MEXITCOUNT | MEXITCOUNT | ||||
jmp doreti | jmp doreti | ||||
/* | /* | ||||
* Local APIC CMCI handler. | * Local APIC CMCI handler. | ||||
*/ | */ | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
IDTVEC(cmcint_pti) | IDTVEC(cmcint_pti) | ||||
IDTVEC(cmcint) | IDTVEC(cmcint) | ||||
PUSH_FRAME | PUSH_FRAME | ||||
SET_KERNEL_SREGS | SET_KERNEL_SREGS | ||||
cld | cld | ||||
KENTER | |||||
FAKE_MCOUNT(TF_EIP(%esp)) | FAKE_MCOUNT(TF_EIP(%esp)) | ||||
call lapic_handle_cmc | movl $lapic_handle_cmc, %eax | ||||
call *%eax | |||||
MEXITCOUNT | MEXITCOUNT | ||||
jmp doreti | jmp doreti | ||||
/* | /* | ||||
* Local APIC error interrupt handler. | * Local APIC error interrupt handler. | ||||
*/ | */ | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
IDTVEC(errorint_pti) | IDTVEC(errorint_pti) | ||||
IDTVEC(errorint) | IDTVEC(errorint) | ||||
PUSH_FRAME | PUSH_FRAME | ||||
SET_KERNEL_SREGS | SET_KERNEL_SREGS | ||||
cld | cld | ||||
KENTER | |||||
FAKE_MCOUNT(TF_EIP(%esp)) | FAKE_MCOUNT(TF_EIP(%esp)) | ||||
call lapic_handle_error | movl $lapic_handle_error, %eax | ||||
call *%eax | |||||
MEXITCOUNT | MEXITCOUNT | ||||
jmp doreti | jmp doreti | ||||
#ifdef XENHVM | #ifdef XENHVM | ||||
/* | /* | ||||
* Xen event channel upcall interrupt handler. | * Xen event channel upcall interrupt handler. | ||||
* Only used when the hypervisor supports direct vector callbacks. | * Only used when the hypervisor supports direct vector callbacks. | ||||
*/ | */ | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
IDTVEC(xen_intr_upcall) | IDTVEC(xen_intr_upcall) | ||||
PUSH_FRAME | PUSH_FRAME | ||||
SET_KERNEL_SREGS | SET_KERNEL_SREGS | ||||
cld | cld | ||||
KENTER | |||||
FAKE_MCOUNT(TF_EIP(%esp)) | FAKE_MCOUNT(TF_EIP(%esp)) | ||||
pushl %esp | pushl %esp | ||||
call xen_intr_handle_upcall | movl $xen_intr_handle_upcall, %eax | ||||
call *%eax | |||||
add $4, %esp | add $4, %esp | ||||
MEXITCOUNT | MEXITCOUNT | ||||
jmp doreti | jmp doreti | ||||
#endif | #endif | ||||
#ifdef SMP | #ifdef SMP | ||||
/* | /* | ||||
* Global address space TLB shootdown. | * Global address space TLB shootdown. | ||||
*/ | */ | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
invltlb_ret: | invltlb_ret: | ||||
call as_lapic_eoi | call as_lapic_eoi | ||||
jmp doreti | jmp doreti | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
IDTVEC(invltlb) | IDTVEC(invltlb) | ||||
PUSH_FRAME | PUSH_FRAME | ||||
SET_KERNEL_SREGS | SET_KERNEL_SREGS | ||||
cld | cld | ||||
KENTER | |||||
call invltlb_handler | movl $invltlb_handler, %eax | ||||
call *%eax | |||||
jmp invltlb_ret | jmp invltlb_ret | ||||
/* | /* | ||||
* Single page TLB shootdown | * Single page TLB shootdown | ||||
*/ | */ | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
IDTVEC(invlpg) | IDTVEC(invlpg) | ||||
PUSH_FRAME | PUSH_FRAME | ||||
SET_KERNEL_SREGS | SET_KERNEL_SREGS | ||||
cld | cld | ||||
KENTER | |||||
call invlpg_handler | movl $invlpg_handler, %eax | ||||
call *%eax | |||||
jmp invltlb_ret | jmp invltlb_ret | ||||
/* | /* | ||||
* Page range TLB shootdown. | * Page range TLB shootdown. | ||||
*/ | */ | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
IDTVEC(invlrng) | IDTVEC(invlrng) | ||||
PUSH_FRAME | PUSH_FRAME | ||||
SET_KERNEL_SREGS | SET_KERNEL_SREGS | ||||
cld | cld | ||||
KENTER | |||||
call invlrng_handler | movl $invlrng_handler, %eax | ||||
call *%eax | |||||
jmp invltlb_ret | jmp invltlb_ret | ||||
/* | /* | ||||
* Invalidate cache. | * Invalidate cache. | ||||
*/ | */ | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
IDTVEC(invlcache) | IDTVEC(invlcache) | ||||
PUSH_FRAME | PUSH_FRAME | ||||
SET_KERNEL_SREGS | SET_KERNEL_SREGS | ||||
cld | cld | ||||
KENTER | |||||
call invlcache_handler | movl $invlcache_handler, %eax | ||||
call *%eax | |||||
jmp invltlb_ret | jmp invltlb_ret | ||||
/* | /* | ||||
* Handler for IPIs sent via the per-cpu IPI bitmap. | * Handler for IPIs sent via the per-cpu IPI bitmap. | ||||
*/ | */ | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
IDTVEC(ipi_intr_bitmap_handler) | IDTVEC(ipi_intr_bitmap_handler) | ||||
PUSH_FRAME | PUSH_FRAME | ||||
SET_KERNEL_SREGS | SET_KERNEL_SREGS | ||||
cld | cld | ||||
KENTER | |||||
call as_lapic_eoi | call as_lapic_eoi | ||||
FAKE_MCOUNT(TF_EIP(%esp)) | FAKE_MCOUNT(TF_EIP(%esp)) | ||||
movl $ipi_bitmap_handler, %eax | |||||
call ipi_bitmap_handler | call *%eax | ||||
MEXITCOUNT | MEXITCOUNT | ||||
jmp doreti | jmp doreti | ||||
/* | /* | ||||
* Executed by a CPU when it receives an IPI_STOP from another CPU. | * Executed by a CPU when it receives an IPI_STOP from another CPU. | ||||
*/ | */ | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
IDTVEC(cpustop) | IDTVEC(cpustop) | ||||
PUSH_FRAME | PUSH_FRAME | ||||
SET_KERNEL_SREGS | SET_KERNEL_SREGS | ||||
cld | cld | ||||
KENTER | |||||
call as_lapic_eoi | call as_lapic_eoi | ||||
call cpustop_handler | movl $cpustop_handler, %eax | ||||
call *%eax | |||||
jmp doreti | jmp doreti | ||||
/* | /* | ||||
* Executed by a CPU when it receives an IPI_SUSPEND from another CPU. | * Executed by a CPU when it receives an IPI_SUSPEND from another CPU. | ||||
*/ | */ | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
IDTVEC(cpususpend) | IDTVEC(cpususpend) | ||||
PUSH_FRAME | PUSH_FRAME | ||||
SET_KERNEL_SREGS | SET_KERNEL_SREGS | ||||
cld | cld | ||||
KENTER | |||||
call as_lapic_eoi | call as_lapic_eoi | ||||
call cpususpend_handler | movl $cpususpend_handler, %eax | ||||
call *%eax | |||||
jmp doreti | jmp doreti | ||||
/* | /* | ||||
* Executed by a CPU when it receives a RENDEZVOUS IPI from another CPU. | * Executed by a CPU when it receives a RENDEZVOUS IPI from another CPU. | ||||
* | * | ||||
* - Calls the generic rendezvous action function. | * - Calls the generic rendezvous action function. | ||||
*/ | */ | ||||
.text | .text | ||||
SUPERALIGN_TEXT | SUPERALIGN_TEXT | ||||
IDTVEC(rendezvous) | IDTVEC(rendezvous) | ||||
PUSH_FRAME | PUSH_FRAME | ||||
SET_KERNEL_SREGS | SET_KERNEL_SREGS | ||||
cld | cld | ||||
KENTER | |||||
#ifdef COUNT_IPIS | #ifdef COUNT_IPIS | ||||
movl PCPU(CPUID), %eax | movl PCPU(CPUID), %eax | ||||
movl ipi_rendezvous_counts(,%eax,4), %eax | movl ipi_rendezvous_counts(,%eax,4), %eax | ||||
incl (%eax) | incl (%eax) | ||||
#endif | #endif | ||||
call smp_rendezvous_action | movl $smp_rendezvous_action, %eax | ||||
call *%eax | |||||
call as_lapic_eoi | call as_lapic_eoi | ||||
jmp doreti | jmp doreti | ||||
#endif /* SMP */ | #endif /* SMP */ |