#include "ioapic.h"
#include <machine/i82093reg.h>
#include <machine/i82489reg.h>
.globl apic_stray
#ifdef MULTIPROCESSOR
IDTVEC(intripi)
subl $8,%esp
INTRENTRY(ipi)
pushl CPL
movl lapic_ppr,%eax
movl %eax,CPL
ioapic_asm_ack()
sti
call i386_ipi_handler
cli
popl CPL
#ifdef DIAGNOSTIC
movl $0xf8,%esi
#endif
INTRFASTEXIT
.p2align 4,0xcc
IDTVEC(intripi_invltlb)
pushl %eax
pushl %ds
movl $GSEL(GDATA_SEL, SEL_KPL), %eax
movl %eax, %ds
ioapic_asm_ack()
movl %cr3, %eax
movl %eax, %cr3
movl tlb_shoot_cpu, %eax
lock
decl tlb_shoot_counts(,%eax,4) # decrement outstanding shoots
jnz 9f
xorl %eax, %eax
movl %eax, tlb_shoot_lock # release lock for next shooter
9:
popl %ds
popl %eax
iret
.p2align 4,0xcc
IDTVEC(intripi_invlpg)
pushl %eax
pushl %ds
movl $GSEL(GDATA_SEL, SEL_KPL), %eax
movl %eax, %ds
ioapic_asm_ack()
movl tlb_shoot_addr1, %eax
invlpg (%eax)
movl tlb_shoot_cpu, %eax
lock
decl tlb_shoot_counts(,%eax,4) # decrement outstanding shoots
jnz 9f
xorl %eax, %eax
movl %eax, tlb_shoot_lock # release lock for next shooter
9:
popl %ds
popl %eax
iret
.p2align 4,0xcc
IDTVEC(intripi_invlrange)
pushl %eax
pushl %edx
pushl %ds
movl $GSEL(GDATA_SEL, SEL_KPL), %eax
movl %eax, %ds
ioapic_asm_ack()
movl tlb_shoot_addr1, %eax
movl tlb_shoot_addr2, %edx
1: invlpg (%eax)
addl $PAGE_SIZE, %eax
cmpl %edx, %eax
jb 1b
movl tlb_shoot_cpu, %eax
lock
decl tlb_shoot_counts(,%eax,4) # decrement outstanding shoots
jnz 9f
xorl %eax, %eax
movl %eax, tlb_shoot_lock # release lock for next shooter
9:
popl %ds
popl %edx
popl %eax
iret
.p2align 4,0xcc
IDTVEC(intripi_reloadcr3)
pushl %eax
pushl %ds
movl $GSEL(GDATA_SEL, SEL_KPL), %eax
movl %eax, %ds
pushl %fs
movl $GSEL(GCPU_SEL, SEL_KPL),%eax
movw %ax,%fs
ioapic_asm_ack()
movl CPUVAR(CURPCB), %eax
movl PCB_PMAP(%eax), %eax
movl %eax, CPUVAR(CURPMAP)
movl PM_PDIRPA(%eax), %eax
movl %eax, %cr3
movl tlb_shoot_cpu, %eax
lock
decl tlb_shoot_counts(,%eax,4) # decrement outstanding shoots
jnz 9f
xorl %eax, %eax
movl %eax, tlb_shoot_lock # release lock for next shooter
9:
popl %fs
popl %ds
popl %eax
iret
#endif
IDTVEC(intrltimer)
subl $8,%esp
INTRENTRY(ltimer)
pushl CPL
movl lapic_ppr,%eax
movl %eax,CPL
ioapic_asm_ack()
sti
incl CPUVAR(IDEPTH)
movl %esp,%eax
pushl %eax
call lapic_clockintr
addl $4,%esp
decl CPUVAR(IDEPTH)
jmp Xdoreti
KIDTVEC(intrsoftclock)
subl $8,%esp
INTRENTRY(intrsoftclock)
pushl CPL
movl $IPL_SOFTCLOCK,CPL
andl $~(1<<SIR_CLOCK),CPUVAR(IPENDING)
ioapic_asm_ack()
sti
incl CPUVAR(IDEPTH)
pushl $SOFTINTR_CLOCK
call softintr_dispatch
addl $4,%esp
decl CPUVAR(IDEPTH)
jmp Xdoreti
KIDTVEC(intrsoftnet)
subl $8,%esp
INTRENTRY(intrsoftnet)
pushl CPL
movl $IPL_SOFTNET,CPL
andl $~(1<<SIR_NET),CPUVAR(IPENDING)
ioapic_asm_ack()
sti
incl CPUVAR(IDEPTH)
pushl $SOFTINTR_NET
call softintr_dispatch
addl $4,%esp
decl CPUVAR(IDEPTH)
jmp Xdoreti
#undef DONETISR
KIDTVEC(intrsofttty)
subl $8,%esp
INTRENTRY(intrsofttty)
pushl CPL
movl $IPL_SOFTTTY,CPL
andl $~(1<<SIR_TTY),CPUVAR(IPENDING)
ioapic_asm_ack()
sti
incl CPUVAR(IDEPTH)
pushl $SOFTINTR_TTY
call softintr_dispatch
addl $4,%esp
decl CPUVAR(IDEPTH)
jmp Xdoreti
#if NIOAPIC > 0
#define voidop(num)
#define APICINTR(name, num, early_ack, late_ack, mask, unmask, level_mask) \
IDTVEC(intr_##name##num) \
subl $8,%esp ;\
INTRENTRY(intr_##name##num) ;\
pushl CPL ;\
movl lapic_ppr,%eax ;\
orl $num,%eax ;\
movl apic_maxlevel(,%eax,4),%ebx ;\
movl %ebx,CPL ;\
mask(num) ;\
early_ack(num) ;\
incl uvmexp+V_INTR ;\
sti ;\
movl apic_intrhand(,%eax,4),%ebx ;\
testl %ebx,%ebx ;\
jz Xstray_##name##num ;\
APIC_STRAY_INIT ;\
7: incl CPUVAR(IDEPTH) ;\
movl %esp, %eax ;\
pushl %ebx ;\
pushl %eax ;\
call intr_handler ;\
addl $8, %esp ;\
APIC_STRAY_INTEGRATE ;\
orl %eax,%eax ;\
jz 4f ;\
addl $1,IH_COUNT(%ebx) ;\
adcl $0,IH_COUNT+4(%ebx) ;\
cmpl $0,intr_shared_edge ;\
jne 4f ;\
orl %eax,%eax ;\
js 4f ;\
1: decl CPUVAR(IDEPTH) ;\
jmp 8f ;\
4: decl CPUVAR(IDEPTH) ;\
movl IH_NEXT(%ebx),%ebx ;\
testl %ebx,%ebx ;\
jnz 7b ;\
APIC_STRAY_TEST(name,num) ;\
8: \
unmask(num) ;\
late_ack(num) ;\
jmp Xdoreti ;\
Xstray_##name##num: \
pushl $num ;\
call apic_stray ;\
addl $4,%esp ;\
jmp 8b ;\
#if defined(DEBUG)
#define APIC_STRAY_INIT \
xorl %esi,%esi
#define APIC_STRAY_INTEGRATE \
orl %eax,%esi
#define APIC_STRAY_TEST(name,num) \
testl %esi,%esi ;\
jz Xstray_##name##num
#else
#define APIC_STRAY_INIT
#define APIC_STRAY_INTEGRATE
#define APIC_STRAY_TEST(name,num)
#endif
APICINTR(ioapic,0, voidop, ioapic_asm_ack, voidop, voidop, voidop)
APICINTR(ioapic,1, voidop, ioapic_asm_ack, voidop, voidop, voidop)
APICINTR(ioapic,2, voidop, ioapic_asm_ack, voidop, voidop, voidop)
APICINTR(ioapic,3, voidop, ioapic_asm_ack, voidop, voidop, voidop)
APICINTR(ioapic,4, voidop, ioapic_asm_ack, voidop, voidop, voidop)
APICINTR(ioapic,5, voidop, ioapic_asm_ack, voidop, voidop, voidop)
APICINTR(ioapic,6, voidop, ioapic_asm_ack, voidop, voidop, voidop)
APICINTR(ioapic,7, voidop, ioapic_asm_ack, voidop, voidop, voidop)
APICINTR(ioapic,8, voidop, ioapic_asm_ack, voidop, voidop, voidop)
APICINTR(ioapic,9, voidop, ioapic_asm_ack, voidop, voidop, voidop)
APICINTR(ioapic,10, voidop, ioapic_asm_ack, voidop, voidop, voidop)
APICINTR(ioapic,11, voidop, ioapic_asm_ack, voidop, voidop, voidop)
APICINTR(ioapic,12, voidop, ioapic_asm_ack, voidop, voidop, voidop)
APICINTR(ioapic,13, voidop, ioapic_asm_ack, voidop, voidop, voidop)
APICINTR(ioapic,14, voidop, ioapic_asm_ack, voidop, voidop, voidop)
APICINTR(ioapic,15, voidop, ioapic_asm_ack, voidop, voidop, voidop)
.globl Xintr_ioapic0,Xintr_ioapic1
.globl Xintr_ioapic2,Xintr_ioapic3
.globl Xintr_ioapic4,Xintr_ioapic5
.globl Xintr_ioapic6,Xintr_ioapic7
.globl Xintr_ioapic8,Xintr_ioapic9
.globl Xintr_ioapic10,Xintr_ioapic11
.globl Xintr_ioapic12,Xintr_ioapic13
.globl Xintr_ioapic14,Xintr_ioapic15
.globl apichandler
apichandler:
.long Xintr_ioapic0,Xintr_ioapic1
.long Xintr_ioapic2,Xintr_ioapic3
.long Xintr_ioapic4,Xintr_ioapic5
.long Xintr_ioapic6,Xintr_ioapic7
.long Xintr_ioapic8,Xintr_ioapic9
.long Xintr_ioapic10,Xintr_ioapic11
.long Xintr_ioapic12,Xintr_ioapic13
.long Xintr_ioapic14,Xintr_ioapic15
#endif