2 * from: vector.s, 386BSD 0.1 unknown origin
3 * $FreeBSD: src/sys/i386/isa/apic_vector.s,v 1.47.2.5 2001/09/01 22:33:38 tegge Exp $
6 #include <machine/asmacros.h>
7 #include <machine/lock.h>
8 #include <machine/psl.h>
9 #include <machine/trap.h>
10 #include <machine/segments.h>
15 /* convert an absolute IRQ# into bitmask */
16 #define IRQ_LBIT(irq_num) (1UL << (irq_num & 0x3f))
19 #define IRQ_SBITS(irq_num) ((irq_num) & 0x3f)
21 /* convert an absolute IRQ# into gd_ipending index */
22 #define IRQ_LIDX(irq_num) ((irq_num) >> 6)
24 #define MSI_PUSH_FRAME \
25 PUSH_FRAME ; /* 15 regs + space for 5 extras */ \
26 movq $0,TF_XFLAGS(%rsp) ; \
27 movq $0,TF_TRAPNO(%rsp) ; \
28 movq $0,TF_ADDR(%rsp) ; \
29 movq $0,TF_FLAGS(%rsp) ; \
30 movq $0,TF_ERR(%rsp) ; \
34 * Interrupt call handlers run in the following sequence:
36 * - Push the trap frame required by doreti
37 * - If we cannot take the interrupt set its ipending bit and
39 * - If we can take the interrupt clear its ipending bit,
40 * call the handler and doreti.
42 * YYY can cache gd base opitner instead of using hidden %fs prefixes.
45 #define MSI_HANDLER(irq_num) \
48 IDTVEC(msi_intr##irq_num) ; \
50 FAKE_MCOUNT(TF_RIP(%rsp)) ; \
52 movl $0, LA_EOI(%rax) ; \
53 movq PCPU(curthread),%rbx ; \
54 testl $-1,TD_NEST_COUNT(%rbx) ; \
56 testl $-1,TD_CRITCOUNT(%rbx) ; \
59 /* in critical section, make interrupt pending */ \
60 /* set the pending bit and return, leave interrupt masked */ \
62 shlq $IRQ_SBITS(irq_num),%rcx ; \
63 movq $IRQ_LIDX(irq_num),%rdx ; \
64 orq %rcx,PCPU_E8(ipending,%rdx) ; \
65 orl $RQF_INTPEND,PCPU(reqflags) ; \
68 /* clear pending bit, run handler */ \
70 shlq $IRQ_SBITS(irq_num),%rcx ; \
72 movq $IRQ_LIDX(irq_num),%rdx ; \
73 andq %rcx,PCPU_E8(ipending,%rdx) ; \
74 pushq $irq_num ; /* trapframe -> intrframe */ \
75 movq %rsp, %rdi ; /* pass frame by reference */ \
76 incl TD_CRITCOUNT(%rbx) ; \
78 call ithread_fast_handler ; \
79 decl TD_CRITCOUNT(%rbx) ; \
80 addq $8, %rsp ; /* intrframe -> trapframe */ \