Blame view
arch/x86/kernel/irqinit.c
7.64 KB
778838600 x86: unify trivia... |
1 |
#include <linux/linkage.h> |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 6 |
#include <linux/errno.h> #include <linux/signal.h> #include <linux/sched.h> #include <linux/ioport.h> #include <linux/interrupt.h> |
778838600 x86: unify trivia... |
7 |
#include <linux/timex.h> |
1da177e4c Linux-2.6.12-rc2 |
8 |
#include <linux/random.h> |
47f16ca76 x86, irqinit: pre... |
9 |
#include <linux/kprobes.h> |
1da177e4c Linux-2.6.12-rc2 |
10 11 |
#include <linux/init.h> #include <linux/kernel_stat.h> |
edbaa603e driver-core: remo... |
12 |
#include <linux/device.h> |
1da177e4c Linux-2.6.12-rc2 |
13 |
#include <linux/bitops.h> |
778838600 x86: unify trivia... |
14 |
#include <linux/acpi.h> |
aa09e6cda x86: irqinit_32.c... |
15 16 |
#include <linux/io.h> #include <linux/delay.h> |
1da177e4c Linux-2.6.12-rc2 |
17 |
|
60063497a atomic: use <linu... |
18 |
#include <linux/atomic.h> |
1da177e4c Linux-2.6.12-rc2 |
19 |
#include <asm/system.h> |
1da177e4c Linux-2.6.12-rc2 |
20 |
#include <asm/timer.h> |
778838600 x86: unify trivia... |
21 |
#include <asm/hw_irq.h> |
1da177e4c Linux-2.6.12-rc2 |
22 |
#include <asm/pgtable.h> |
1da177e4c Linux-2.6.12-rc2 |
23 24 |
#include <asm/desc.h> #include <asm/apic.h> |
8e6dafd6c x86: refactor x86... |
25 |
#include <asm/setup.h> |
1da177e4c Linux-2.6.12-rc2 |
26 |
#include <asm/i8259.h> |
aa09e6cda x86: irqinit_32.c... |
27 |
#include <asm/traps.h> |
3879a6f32 x86: dtb: Add ear... |
28 |
#include <asm/prom.h> |
1da177e4c Linux-2.6.12-rc2 |
29 |
|
778838600 x86: unify trivia... |
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
/* * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts: * (these are usually mapped to vectors 0x30-0x3f) */ /* * The IO-APIC gives us many more interrupt sources. Most of these * are unused but an SMP system is supposed to have enough memory ... * sometimes (mostly wrt. hw bugs) we get corrupted vectors all * across the spectrum, so we really want to be prepared to get all * of these. Plus, more powerful systems might have more than 64 * IO-APIC registers. * * (these are usually mapped into the 0x30-0xff vector range) */ |
1da177e4c Linux-2.6.12-rc2 |
45 |
|
320fd9967 x86: unify native... |
46 |
#ifdef CONFIG_X86_32 |
1da177e4c Linux-2.6.12-rc2 |
47 48 49 50 51 52 53 54 55 56 57 |
/* * Note that on a 486, we don't want to do a SIGFPE on an irq13 * as the irq is unreliable, and exception 16 works correctly * (ie as explained in the intel literature). On a 386, you * can't use exception 16 due to bad IBM design, so we have to * rely on the less exact irq13. * * Careful.. Not only is IRQ13 unreliable, but it is also * leads to races. IBM designers who came up with it should * be shot. */ |
1da177e4c Linux-2.6.12-rc2 |
58 |
|
7d12e780e IRQ: Maintain reg... |
59 |
static irqreturn_t math_error_irq(int cpl, void *dev_id) |
1da177e4c Linux-2.6.12-rc2 |
60 |
{ |
aa09e6cda x86: irqinit_32.c... |
61 |
outb(0, 0xF0); |
1da177e4c Linux-2.6.12-rc2 |
62 63 |
if (ignore_fpu_irq || !boot_cpu_data.hard_math) return IRQ_NONE; |
9b6dba9e0 x86: Merge simd_m... |
64 |
math_error(get_irq_regs(), 0, 16); |
1da177e4c Linux-2.6.12-rc2 |
65 66 67 68 69 70 71 |
return IRQ_HANDLED; } /* * New motherboards sometimes make IRQ 13 be a PCI interrupt, * so allow interrupt sharing. */ |
6a61f6a55 x86: clean up str... |
72 73 |
static struct irqaction fpu_irq = { .handler = math_error_irq, |
6a61f6a55 x86: clean up str... |
74 |
.name = "fpu", |
9bbbff25b x86: Mark low lev... |
75 |
.flags = IRQF_NO_THREAD, |
6a61f6a55 x86: clean up str... |
76 |
}; |
1da177e4c Linux-2.6.12-rc2 |
77 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
78 |
|
2ae111cdd x86: apic interru... |
79 80 81 82 83 |
/* * IRQ2 is cascade interrupt to second interrupt controller */ static struct irqaction irq2 = { .handler = no_action, |
2ae111cdd x86: apic interru... |
84 |
.name = "cascade", |
9bbbff25b x86: Mark low lev... |
85 |
.flags = IRQF_NO_THREAD, |
2ae111cdd x86: apic interru... |
86 |
}; |
497c9a195 x86: make 32bit s... |
87 |
DEFINE_PER_CPU(vector_irq_t, vector_irq) = { |
97943390b x86, irq: Don't b... |
88 |
[0 ... NR_VECTORS - 1] = -1, |
497c9a195 x86: make 32bit s... |
89 |
}; |
b77b881f2 x86: fix lguest u... |
90 91 92 93 94 95 96 97 98 99 100 |
int vector_used_by_percpu_irq(unsigned int vector) { int cpu; for_each_online_cpu(cpu) { if (per_cpu(vector_irq, cpu)[vector] != -1) return 1; } return 0; } |
d9112f430 x86: Move pre_int... |
101 |
void __init init_ISA_irqs(void) |
1da177e4c Linux-2.6.12-rc2 |
102 |
{ |
011d578fd x86: Remove usele... |
103 104 |
struct irq_chip *chip = legacy_pic->chip; const char *name = chip->name; |
1da177e4c Linux-2.6.12-rc2 |
105 |
int i; |
598c73d25 x86: unify init_I... |
106 |
#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC) |
7371d9fcb x86: move init_IS... |
107 108 |
init_bsp_APIC(); #endif |
b81bb373a x86, pic: Make us... |
109 |
legacy_pic->init(0); |
1da177e4c Linux-2.6.12-rc2 |
110 |
|
011d578fd x86: Remove usele... |
111 |
for (i = 0; i < legacy_pic->nr_legacy_irqs; i++) |
2c778651f x86: Cleanup the ... |
112 |
irq_set_chip_and_handler_name(i, chip, handle_level_irq, name); |
7371d9fcb x86: move init_IS... |
113 |
} |
1da177e4c Linux-2.6.12-rc2 |
114 |
|
54e2603f1 x86: platform: Fi... |
115 |
void __init init_IRQ(void) |
66bcaf0bd x86: Move irq_ini... |
116 |
{ |
97943390b x86, irq: Don't b... |
117 118 119 |
int i; /* |
bcc7c1244 x86: ioapic: Add ... |
120 121 122 123 124 125 |
* We probably need a better place for this, but it works for * now ... */ x86_add_irq_domains(); /* |
97943390b x86, irq: Don't b... |
126 127 128 129 130 131 132 |
* On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15. * If these IRQ's are handled by legacy interrupt-controllers like PIC, * then this configuration will likely be static after the boot. If * these IRQ's are handled by more mordern controllers like IO-APIC, * then this vector space can be freed and re-used dynamically as the * irq's migrate etc. */ |
28c6a0ba3 x86, legacy_irq: ... |
133 |
for (i = 0; i < legacy_pic->nr_legacy_irqs; i++) |
97943390b x86, irq: Don't b... |
134 |
per_cpu(vector_irq, 0)[IRQ0_VECTOR + i] = i; |
66bcaf0bd x86: Move irq_ini... |
135 136 |
x86_init.irqs.intr_init(); } |
2ae111cdd x86: apic interru... |
137 |
|
36e9e1eab x86: Handle legac... |
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
/* * Setup the vector to irq mappings. */ void setup_vector_irq(int cpu) { #ifndef CONFIG_X86_IO_APIC int irq; /* * On most of the platforms, legacy PIC delivers the interrupts on the * boot cpu. But there are certain platforms where PIC interrupts are * delivered to multiple cpu's. If the legacy IRQ is handled by the * legacy PIC, for the new cpu that is coming online, setup the static * legacy vector to irq mapping: */ for (irq = 0; irq < legacy_pic->nr_legacy_irqs; irq++) per_cpu(vector_irq, cpu)[IRQ0_VECTOR + irq] = irq; #endif __setup_vector_irq(cpu); } |
36290d87f x86: introduce sm... |
159 160 |
static void __init smp_intr_init(void) { |
b0096bb0b x86: unify smp_in... |
161 162 |
#ifdef CONFIG_SMP #if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC) |
2ae111cdd x86: apic interru... |
163 164 165 166 167 |
/* * The reschedule interrupt is a CPU-to-CPU reschedule-helper * IPI, driven by wakeup. */ alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt); |
02cf94c37 x86: make x86_32 ... |
168 |
/* IPIs for invalidation */ |
3a09fb457 x86: Allocate 32 ... |
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
#define ALLOC_INVTLB_VEC(NR) \ alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+NR, \ invalidate_interrupt##NR) switch (NUM_INVALIDATE_TLB_VECTORS) { default: ALLOC_INVTLB_VEC(31); case 31: ALLOC_INVTLB_VEC(30); case 30: ALLOC_INVTLB_VEC(29); case 29: ALLOC_INVTLB_VEC(28); case 28: ALLOC_INVTLB_VEC(27); case 27: ALLOC_INVTLB_VEC(26); case 26: ALLOC_INVTLB_VEC(25); case 25: ALLOC_INVTLB_VEC(24); case 24: ALLOC_INVTLB_VEC(23); case 23: ALLOC_INVTLB_VEC(22); case 22: ALLOC_INVTLB_VEC(21); case 21: ALLOC_INVTLB_VEC(20); case 20: ALLOC_INVTLB_VEC(19); case 19: ALLOC_INVTLB_VEC(18); case 18: ALLOC_INVTLB_VEC(17); case 17: ALLOC_INVTLB_VEC(16); case 16: ALLOC_INVTLB_VEC(15); case 15: ALLOC_INVTLB_VEC(14); case 14: ALLOC_INVTLB_VEC(13); case 13: ALLOC_INVTLB_VEC(12); case 12: ALLOC_INVTLB_VEC(11); case 11: ALLOC_INVTLB_VEC(10); case 10: ALLOC_INVTLB_VEC(9); case 9: ALLOC_INVTLB_VEC(8); case 8: ALLOC_INVTLB_VEC(7); case 7: ALLOC_INVTLB_VEC(6); case 6: ALLOC_INVTLB_VEC(5); case 5: ALLOC_INVTLB_VEC(4); case 4: ALLOC_INVTLB_VEC(3); case 3: ALLOC_INVTLB_VEC(2); case 2: ALLOC_INVTLB_VEC(1); case 1: ALLOC_INVTLB_VEC(0); break; } |
2ae111cdd x86: apic interru... |
240 241 242 |
/* IPI for generic function call */ alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); |
b0096bb0b x86: unify smp_in... |
243 |
/* IPI for generic single function call */ |
b77b881f2 x86: fix lguest u... |
244 |
alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR, |
b0096bb0b x86: unify smp_in... |
245 |
call_function_single_interrupt); |
497c9a195 x86: make 32bit s... |
246 247 248 |
/* Low priority IPI to cleanup after moving an irq */ set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt); |
b77b881f2 x86: fix lguest u... |
249 |
set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors); |
4ef702c10 x86: fix panic wi... |
250 251 252 |
/* IPI used for rebooting/stopping */ alloc_intr_gate(REBOOT_VECTOR, reboot_interrupt); |
2ae111cdd x86: apic interru... |
253 |
#endif |
b0096bb0b x86: unify smp_in... |
254 |
#endif /* CONFIG_SMP */ |
36290d87f x86: introduce sm... |
255 |
} |
22813c452 x86: introduce ap... |
256 |
static void __init apic_intr_init(void) |
1da177e4c Linux-2.6.12-rc2 |
257 |
{ |
36290d87f x86: introduce sm... |
258 |
smp_intr_init(); |
2ae111cdd x86: apic interru... |
259 |
|
48b1fddbb Merge branch 'irq... |
260 |
#ifdef CONFIG_X86_THERMAL_VECTOR |
ab19c25ab x86: unify apic_i... |
261 |
alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); |
48b1fddbb Merge branch 'irq... |
262 |
#endif |
6effa8f6f x86, mce: Rename ... |
263 |
#ifdef CONFIG_X86_MCE_THRESHOLD |
ab19c25ab x86: unify apic_i... |
264 265 266 267 |
alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt); #endif #if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC) |
2ae111cdd x86: apic interru... |
268 269 |
/* self generated IPI for local APIC timer */ alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); |
4a4de9c7d x86: UV RTC: Rena... |
270 271 |
/* IPI for X86 platform specific use */ alloc_intr_gate(X86_PLATFORM_IPI_VECTOR, x86_platform_ipi); |
acaabe795 x86: UV, SGI RTC:... |
272 |
|
2ae111cdd x86: apic interru... |
273 274 275 |
/* IPI vectors for APIC spurious and error interrupts */ alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); |
2ae111cdd x86: apic interru... |
276 |
|
e360adbe2 irq_work: Add gen... |
277 278 279 |
/* IRQ work interrupts: */ # ifdef CONFIG_IRQ_WORK alloc_intr_gate(IRQ_WORK_VECTOR, irq_work_interrupt); |
47f16ca76 x86, irqinit: pre... |
280 |
# endif |
2ae111cdd x86: apic interru... |
281 |
#endif |
22813c452 x86: introduce ap... |
282 |
} |
2ae111cdd x86: apic interru... |
283 |
|
22813c452 x86: introduce ap... |
284 285 286 287 288 |
void __init native_init_IRQ(void) { int i; /* Execute any quirks before the call gates are initialised: */ |
d9112f430 x86: Move pre_int... |
289 |
x86_init.irqs.pre_vector_init(); |
22813c452 x86: introduce ap... |
290 |
|
77857dc07 x86: use used_vec... |
291 |
apic_intr_init(); |
22813c452 x86: introduce ap... |
292 293 294 295 296 |
/* * Cover the whole vector space, no vector can escape * us. (some of these will be overridden and become * 'special' SMP interrupts) */ |
d3496c85c x86: use identica... |
297 |
for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) { |
77857dc07 x86: use used_vec... |
298 299 |
/* IA32_SYSCALL_VECTOR could be used in trap_init already. */ if (!test_bit(i, used_vectors)) |
320fd9967 x86: unify native... |
300 |
set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]); |
22813c452 x86: introduce ap... |
301 |
} |
7856f6cce x86, mce: enable ... |
302 |
|
3879a6f32 x86: dtb: Add ear... |
303 |
if (!acpi_ioapic && !of_ioapic) |
2ae111cdd x86: apic interru... |
304 |
setup_irq(2, &irq2); |
320fd9967 x86: unify native... |
305 |
#ifdef CONFIG_X86_32 |
8e6dafd6c x86: refactor x86... |
306 |
/* |
1da177e4c Linux-2.6.12-rc2 |
307 308 309 310 311 312 313 |
* External FPU? Set up irq13 if so, for * original braindamaged IBM FERR coupling. */ if (boot_cpu_data.hard_math && !cpu_has_fpu) setup_irq(FPU_IRQ, &fpu_irq); irq_ctx_init(smp_processor_id()); |
320fd9967 x86: unify native... |
314 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
315 |
} |