7 * Interrupt controller descriptor. This is all we need
8 * to describe about the low-level hardware.
10 struct hw_interrupt_type
{
11 const char * typename
;
12 void (*startup
)(unsigned int irq
);
13 void (*shutdown
)(unsigned int irq
);
14 void (*handle
)(unsigned int irq
, struct pt_regs
* regs
);
15 void (*enable
)(unsigned int irq
);
16 void (*disable
)(unsigned int irq
);
23 #define IRQ_INPROGRESS 1 /* IRQ handler active - do not enter! */
24 #define IRQ_DISABLED 2 /* IRQ disabled - do not enter! */
25 #define IRQ_PENDING 4 /* IRQ pending - replay on enable */
26 #define IRQ_REPLAY 8 /* IRQ has been replayed but not acked yet */
27 #define IRQ_AUTODETECT 16 /* IRQ is being autodetected */
30 * This is the "IRQ descriptor", which contains various information
31 * about the irq, including what kind of hardware handling it has,
32 * whether it is disabled etc etc.
34 * Pad this out to 32 bytes for cache and indexing reasons.
37 unsigned int status
; /* IRQ status - IRQ_INPROGRESS, IRQ_DISABLED */
38 struct hw_interrupt_type
*handler
; /* handle/enable/disable functions */
39 struct irqaction
*action
; /* IRQ action list */
40 unsigned int depth
; /* Disable depth for nested irq disables */
44 * Special IRQ vectors used by the SMP architecture:
46 * (some of the following vectors are 'rare', they might be merged
47 * into a single vector to save vector space. TLB, reschedule and
48 * local APIC vectors are performance-critical.)
50 #define RESCHEDULE_VECTOR 0x30
51 #define INVALIDATE_TLB_VECTOR 0x31
52 #define STOP_CPU_VECTOR 0x40
53 #define LOCAL_TIMER_VECTOR 0x41
54 #define MTRR_CHANGE_VECTOR 0x50
57 * First vector available to drivers: (vectors 0x51-0xfe)
59 #define IRQ0_TRAP_VECTOR 0x51
62 * This IRQ should never happen, but we print a message nevertheless.
64 #define SPURIOUS_APIC_VECTOR 0xff
66 extern irq_desc_t irq_desc
[NR_IRQS
];
67 extern int irq_vector
[NR_IRQS
];
68 #define IO_APIC_VECTOR(irq) irq_vector[irq]
70 extern void init_IRQ_SMP(void);
71 extern int handle_IRQ_event(unsigned int, struct pt_regs
*, struct irqaction
*);
72 extern int setup_x86_irq(unsigned int, struct irqaction
*);
75 * Various low-level irq details needed by irq.c, process.c,
76 * time.c, io_apic.c and smp.c
78 * Interrupt entry/exit code at both C and assembly level
81 extern void no_action(int cpl
, void *dev_id
, struct pt_regs
*regs
);
82 extern void mask_irq(unsigned int irq
);
83 extern void unmask_irq(unsigned int irq
);
84 extern void disable_8259A_irq(unsigned int irq
);
85 extern int i8259A_irq_pending(unsigned int irq
);
86 extern void ack_APIC_irq(void);
87 extern void FASTCALL(send_IPI_self(int vector
));
88 extern void smp_send_mtrr(void);
89 extern void init_VISWS_APIC_irqs(void);
90 extern void setup_IO_APIC(void);
91 extern int IO_APIC_get_PCI_irq_vector(int bus
, int slot
, int fn
);
92 extern void make_8259A_irq(unsigned int irq
);
93 extern void send_IPI(int dest
, int vector
);
94 extern void init_pic_mode(void);
95 extern void print_IO_APIC(void);
97 extern unsigned long long io_apic_irqs
;
99 #define MAX_IRQ_SOURCES 128
100 #define MAX_MP_BUSSES 32
105 extern int mp_bus_id_to_type
[MAX_MP_BUSSES
];
106 extern int mp_bus_id_to_pci_bus
[MAX_MP_BUSSES
];
107 extern char ioapic_OEM_ID
[16];
108 extern char ioapic_Product_ID
[16];
110 extern spinlock_t irq_controller_lock
;
114 #include <asm/atomic.h>
116 static inline void irq_enter(int cpu
, unsigned int irq
)
119 while (test_bit(0,&global_irq_lock
)) {
124 static inline void irq_exit(int cpu
, unsigned int irq
)
129 #define IO_APIC_IRQ(x) ((1<<x) & io_apic_irqs)
133 #define irq_enter(cpu, irq) (++local_irq_count[cpu])
134 #define irq_exit(cpu, irq) (--local_irq_count[cpu])
136 #define IO_APIC_IRQ(x) (0)
141 #define STR(x) __STR(x)
154 "movl $" STR(__KERNEL_DS) ",%edx\n\t" \
158 #define IRQ_NAME2(nr) nr##_interrupt(void)
159 #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
161 #define GET_CURRENT \
162 "movl %esp, %ebx\n\t" \
163 "andl $-8192, %ebx\n\t"
168 * SMP has a few special interrupts for IPI messages
171 #define BUILD_SMP_INTERRUPT(x) \
172 asmlinkage void x(void); \
174 "\n"__ALIGN_STR"\n" \
175 SYMBOL_NAME_STR(x) ":\n\t" \
178 "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
179 "jmp ret_from_intr\n");
181 #define BUILD_SMP_TIMER_INTERRUPT(x) \
182 asmlinkage void x(struct pt_regs * regs); \
184 "\n"__ALIGN_STR"\n" \
185 SYMBOL_NAME_STR(x) ":\n\t" \
188 "movl %esp,%eax\n\t" \
190 "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
192 "jmp ret_from_intr\n");
196 #define BUILD_COMMON_IRQ() \
198 "\n" __ALIGN_STR"\n" \
199 "common_interrupt:\n\t" \
201 "pushl $ret_from_intr\n\t" \
202 "jmp "SYMBOL_NAME_STR(do_IRQ));
204 #define BUILD_IRQ(nr) \
205 asmlinkage void IRQ_NAME(nr); \
207 "\n"__ALIGN_STR"\n" \
208 SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
209 "pushl $"#nr"-256\n\t" \
210 "jmp common_interrupt");
213 * x86 profiling function, SMP safe. We might want to do this in
216 static inline void x86_do_profile (unsigned long eip
)
218 if (prof_buffer
&& current
->pid
) {
220 eip
-= (unsigned long) &_stext
;
223 * Don't ignore out-of-bounds EIP values silently,
224 * put them into the last histogram slot, so if
225 * present, they will show up as a sharp peak.
227 if (eip
> prof_len
-1)
229 atomic_inc((atomic_t
*)&prof_buffer
[eip
]);