diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2008-01-30 07:30:20 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:30:20 -0500 |
commit | 0e078e2f5060e06f9b3f32e55665ea835343440e (patch) | |
tree | f0369a50e9594efa13a3c21da23b9cad84a9a0ed /arch | |
parent | 3a12d93dc0b46bc710317272bf91640d7a8b6f18 (diff) |
x86: prepare merging arch/x86/kernel/apic_32/64.c
Shuffle code around, so we get a readable diff.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/apic_32.c | 92 | ||||
-rw-r--r-- | arch/x86/kernel/apic_64.c | 1033 |
2 files changed, 596 insertions, 529 deletions
diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 3a069acb270c..420c15842e44 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c | |||
@@ -563,6 +563,9 @@ static void local_apic_timer_interrupt(void) | |||
563 | return; | 563 | return; |
564 | } | 564 | } |
565 | 565 | ||
566 | /* | ||
567 | * the NMI deadlock-detector uses this. | ||
568 | */ | ||
566 | per_cpu(irq_stat, cpu).apic_timer_irqs++; | 569 | per_cpu(irq_stat, cpu).apic_timer_irqs++; |
567 | 570 | ||
568 | evt->event_handler(evt); | 571 | evt->event_handler(evt); |
@@ -617,7 +620,7 @@ int setup_profiling_timer(unsigned int multiplier) | |||
617 | void clear_local_APIC(void) | 620 | void clear_local_APIC(void) |
618 | { | 621 | { |
619 | int maxlvt = lapic_get_maxlvt(); | 622 | int maxlvt = lapic_get_maxlvt(); |
620 | unsigned long v; | 623 | u32 v; |
621 | 624 | ||
622 | /* | 625 | /* |
623 | * Masking an LVT entry can trigger a local APIC error | 626 | * Masking an LVT entry can trigger a local APIC error |
@@ -1210,50 +1213,6 @@ int __init APIC_init_uniprocessor (void) | |||
1210 | } | 1213 | } |
1211 | 1214 | ||
1212 | /* | 1215 | /* |
1213 | * APIC command line parameters | ||
1214 | */ | ||
1215 | static int __init parse_lapic(char *arg) | ||
1216 | { | ||
1217 | enable_local_apic = 1; | ||
1218 | return 0; | ||
1219 | } | ||
1220 | early_param("lapic", parse_lapic); | ||
1221 | |||
1222 | static int __init parse_nolapic(char *arg) | ||
1223 | { | ||
1224 | enable_local_apic = -1; | ||
1225 | clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); | ||
1226 | return 0; | ||
1227 | } | ||
1228 | early_param("nolapic", parse_nolapic); | ||
1229 | |||
1230 | static int __init parse_disable_lapic_timer(char *arg) | ||
1231 | { | ||
1232 | local_apic_timer_disabled = 1; | ||
1233 | return 0; | ||
1234 | } | ||
1235 | early_param("nolapic_timer", parse_disable_lapic_timer); | ||
1236 | |||
1237 | static int __init parse_lapic_timer_c2_ok(char *arg) | ||
1238 | { | ||
1239 | local_apic_timer_c2_ok = 1; | ||
1240 | return 0; | ||
1241 | } | ||
1242 | early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok); | ||
1243 | |||
1244 | static int __init apic_set_verbosity(char *str) | ||
1245 | { | ||
1246 | if (strcmp("debug", str) == 0) | ||
1247 | apic_verbosity = APIC_DEBUG; | ||
1248 | else if (strcmp("verbose", str) == 0) | ||
1249 | apic_verbosity = APIC_VERBOSE; | ||
1250 | return 1; | ||
1251 | } | ||
1252 | |||
1253 | __setup("apic=", apic_set_verbosity); | ||
1254 | |||
1255 | |||
1256 | /* | ||
1257 | * Local APIC interrupts | 1216 | * Local APIC interrupts |
1258 | */ | 1217 | */ |
1259 | 1218 | ||
@@ -1565,3 +1524,46 @@ device_initcall(init_lapic_sysfs); | |||
1565 | static void apic_pm_activate(void) { } | 1524 | static void apic_pm_activate(void) { } |
1566 | 1525 | ||
1567 | #endif /* CONFIG_PM */ | 1526 | #endif /* CONFIG_PM */ |
1527 | |||
1528 | /* | ||
1529 | * APIC command line parameters | ||
1530 | */ | ||
1531 | static int __init parse_lapic(char *arg) | ||
1532 | { | ||
1533 | enable_local_apic = 1; | ||
1534 | return 0; | ||
1535 | } | ||
1536 | early_param("lapic", parse_lapic); | ||
1537 | |||
1538 | static int __init parse_nolapic(char *arg) | ||
1539 | { | ||
1540 | enable_local_apic = -1; | ||
1541 | clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); | ||
1542 | return 0; | ||
1543 | } | ||
1544 | early_param("nolapic", parse_nolapic); | ||
1545 | |||
1546 | static int __init parse_disable_lapic_timer(char *arg) | ||
1547 | { | ||
1548 | local_apic_timer_disabled = 1; | ||
1549 | return 0; | ||
1550 | } | ||
1551 | early_param("nolapic_timer", parse_disable_lapic_timer); | ||
1552 | |||
1553 | static int __init parse_lapic_timer_c2_ok(char *arg) | ||
1554 | { | ||
1555 | local_apic_timer_c2_ok = 1; | ||
1556 | return 0; | ||
1557 | } | ||
1558 | early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok); | ||
1559 | |||
1560 | static int __init apic_set_verbosity(char *str) | ||
1561 | { | ||
1562 | if (strcmp("debug", str) == 0) | ||
1563 | apic_verbosity = APIC_DEBUG; | ||
1564 | else if (strcmp("verbose", str) == 0) | ||
1565 | apic_verbosity = APIC_VERBOSE; | ||
1566 | return 1; | ||
1567 | } | ||
1568 | __setup("apic=", apic_set_verbosity); | ||
1569 | |||
diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 5bf329ed9d78..915808bd8a2a 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c | |||
@@ -44,6 +44,7 @@ | |||
44 | int apic_verbosity; | 44 | int apic_verbosity; |
45 | int disable_apic_timer __cpuinitdata; | 45 | int disable_apic_timer __cpuinitdata; |
46 | static int apic_calibrate_pmtmr __initdata; | 46 | static int apic_calibrate_pmtmr __initdata; |
47 | int disable_apic; | ||
47 | 48 | ||
48 | /* Local APIC timer works in C2? */ | 49 | /* Local APIC timer works in C2? */ |
49 | int local_apic_timer_c2_ok; | 50 | int local_apic_timer_c2_ok; |
@@ -60,10 +61,8 @@ static int lapic_next_event(unsigned long delta, | |||
60 | struct clock_event_device *evt); | 61 | struct clock_event_device *evt); |
61 | static void lapic_timer_setup(enum clock_event_mode mode, | 62 | static void lapic_timer_setup(enum clock_event_mode mode, |
62 | struct clock_event_device *evt); | 63 | struct clock_event_device *evt); |
63 | |||
64 | static void lapic_timer_broadcast(cpumask_t mask); | 64 | static void lapic_timer_broadcast(cpumask_t mask); |
65 | 65 | static void apic_pm_activate(void); | |
66 | static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen); | ||
67 | 66 | ||
68 | static struct clock_event_device lapic_clockevent = { | 67 | static struct clock_event_device lapic_clockevent = { |
69 | .name = "lapic", | 68 | .name = "lapic", |
@@ -78,6 +77,130 @@ static struct clock_event_device lapic_clockevent = { | |||
78 | }; | 77 | }; |
79 | static DEFINE_PER_CPU(struct clock_event_device, lapic_events); | 78 | static DEFINE_PER_CPU(struct clock_event_device, lapic_events); |
80 | 79 | ||
80 | /* | ||
81 | * Get the LAPIC version | ||
82 | */ | ||
83 | static inline int lapic_get_version(void) | ||
84 | { | ||
85 | return GET_APIC_VERSION(apic_read(APIC_LVR)); | ||
86 | } | ||
87 | |||
88 | /* | ||
89 | * Check, if the APIC is integrated or a seperate chip | ||
90 | */ | ||
91 | static inline int lapic_is_integrated(void) | ||
92 | { | ||
93 | return 1; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Check, whether this is a modern or a first generation APIC | ||
98 | */ | ||
99 | static int modern_apic(void) | ||
100 | { | ||
101 | /* AMD systems use old APIC versions, so check the CPU */ | ||
102 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD && | ||
103 | boot_cpu_data.x86 >= 0xf) | ||
104 | return 1; | ||
105 | return lapic_get_version() >= 0x14; | ||
106 | } | ||
107 | |||
108 | void apic_wait_icr_idle(void) | ||
109 | { | ||
110 | while (apic_read(APIC_ICR) & APIC_ICR_BUSY) | ||
111 | cpu_relax(); | ||
112 | } | ||
113 | |||
114 | u32 safe_apic_wait_icr_idle(void) | ||
115 | { | ||
116 | u32 send_status; | ||
117 | int timeout; | ||
118 | |||
119 | timeout = 0; | ||
120 | do { | ||
121 | send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; | ||
122 | if (!send_status) | ||
123 | break; | ||
124 | udelay(100); | ||
125 | } while (timeout++ < 1000); | ||
126 | |||
127 | return send_status; | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * enable_NMI_through_LVT0 - enable NMI through local vector table 0 | ||
132 | */ | ||
133 | void enable_NMI_through_LVT0(void *dummy) | ||
134 | { | ||
135 | unsigned int v; | ||
136 | |||
137 | /* unmask and set to NMI */ | ||
138 | v = APIC_DM_NMI; | ||
139 | apic_write(APIC_LVT0, v); | ||
140 | } | ||
141 | |||
142 | /** | ||
143 | * lapic_get_maxlvt - get the maximum number of local vector table entries | ||
144 | */ | ||
145 | int lapic_get_maxlvt(void) | ||
146 | { | ||
147 | unsigned int v, maxlvt; | ||
148 | |||
149 | v = apic_read(APIC_LVR); | ||
150 | maxlvt = GET_APIC_MAXLVT(v); | ||
151 | return maxlvt; | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * This function sets up the local APIC timer, with a timeout of | ||
156 | * 'clocks' APIC bus clock. During calibration we actually call | ||
157 | * this function twice on the boot CPU, once with a bogus timeout | ||
158 | * value, second time for real. The other (noncalibrating) CPUs | ||
159 | * call this function only once, with the real, calibrated value. | ||
160 | * | ||
161 | * We do reads before writes even if unnecessary, to get around the | ||
162 | * P5 APIC double write bug. | ||
163 | */ | ||
164 | |||
165 | static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) | ||
166 | { | ||
167 | unsigned int lvtt_value, tmp_value; | ||
168 | |||
169 | lvtt_value = LOCAL_TIMER_VECTOR; | ||
170 | if (!oneshot) | ||
171 | lvtt_value |= APIC_LVT_TIMER_PERIODIC; | ||
172 | if (!irqen) | ||
173 | lvtt_value |= APIC_LVT_MASKED; | ||
174 | |||
175 | apic_write(APIC_LVTT, lvtt_value); | ||
176 | |||
177 | /* | ||
178 | * Divide PICLK by 16 | ||
179 | */ | ||
180 | tmp_value = apic_read(APIC_TDCR); | ||
181 | apic_write(APIC_TDCR, (tmp_value | ||
182 | & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | ||
183 | | APIC_TDR_DIV_16); | ||
184 | |||
185 | if (!oneshot) | ||
186 | apic_write(APIC_TMICT, clocks); | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * Setup extended LVT (K8 specific) | ||
191 | */ | ||
192 | void setup_APIC_extended_lvt(unsigned char lvt_off, unsigned char vector, | ||
193 | unsigned char msg_type, unsigned char mask) | ||
194 | { | ||
195 | unsigned long reg = (lvt_off << 4) + K8_APIC_EXT_LVT_BASE; | ||
196 | unsigned int v = (mask << 16) | (msg_type << 8) | vector; | ||
197 | |||
198 | apic_write(reg, v); | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * Program the next event, relative to now | ||
203 | */ | ||
81 | static int lapic_next_event(unsigned long delta, | 204 | static int lapic_next_event(unsigned long delta, |
82 | struct clock_event_device *evt) | 205 | struct clock_event_device *evt) |
83 | { | 206 | { |
@@ -85,6 +208,9 @@ static int lapic_next_event(unsigned long delta, | |||
85 | return 0; | 208 | return 0; |
86 | } | 209 | } |
87 | 210 | ||
211 | /* | ||
212 | * Setup the lapic timer in periodic or oneshot mode | ||
213 | */ | ||
88 | static void lapic_timer_setup(enum clock_event_mode mode, | 214 | static void lapic_timer_setup(enum clock_event_mode mode, |
89 | struct clock_event_device *evt) | 215 | struct clock_event_device *evt) |
90 | { | 216 | { |
@@ -127,54 +253,236 @@ static void lapic_timer_broadcast(cpumask_t mask) | |||
127 | #endif | 253 | #endif |
128 | } | 254 | } |
129 | 255 | ||
130 | static void apic_pm_activate(void); | 256 | /* |
257 | * Setup the local APIC timer for this CPU. Copy the initilized values | ||
258 | * of the boot CPU and register the clock event in the framework. | ||
259 | */ | ||
260 | static void setup_APIC_timer(void) | ||
261 | { | ||
262 | struct clock_event_device *levt = &__get_cpu_var(lapic_events); | ||
131 | 263 | ||
132 | void apic_wait_icr_idle(void) | 264 | memcpy(levt, &lapic_clockevent, sizeof(*levt)); |
265 | levt->cpumask = cpumask_of_cpu(smp_processor_id()); | ||
266 | |||
267 | clockevents_register_device(levt); | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * In this function we calibrate APIC bus clocks to the external | ||
272 | * timer. Unfortunately we cannot use jiffies and the timer irq | ||
273 | * to calibrate, since some later bootup code depends on getting | ||
274 | * the first irq? Ugh. | ||
275 | * | ||
276 | * We want to do the calibration only once since we | ||
277 | * want to have local timer irqs syncron. CPUs connected | ||
278 | * by the same APIC bus have the very same bus frequency. | ||
279 | * And we want to have irqs off anyways, no accidental | ||
280 | * APIC irq that way. | ||
281 | */ | ||
282 | |||
283 | #define TICK_COUNT 100000000 | ||
284 | |||
285 | static void __init calibrate_APIC_clock(void) | ||
133 | { | 286 | { |
134 | while (apic_read(APIC_ICR) & APIC_ICR_BUSY) | 287 | unsigned apic, apic_start; |
135 | cpu_relax(); | 288 | unsigned long tsc, tsc_start; |
289 | int result; | ||
290 | |||
291 | local_irq_disable(); | ||
292 | |||
293 | /* | ||
294 | * Put whatever arbitrary (but long enough) timeout | ||
295 | * value into the APIC clock, we just want to get the | ||
296 | * counter running for calibration. | ||
297 | * | ||
298 | * No interrupt enable ! | ||
299 | */ | ||
300 | __setup_APIC_LVTT(250000000, 0, 0); | ||
301 | |||
302 | apic_start = apic_read(APIC_TMCCT); | ||
303 | #ifdef CONFIG_X86_PM_TIMER | ||
304 | if (apic_calibrate_pmtmr && pmtmr_ioport) { | ||
305 | pmtimer_wait(5000); /* 5ms wait */ | ||
306 | apic = apic_read(APIC_TMCCT); | ||
307 | result = (apic_start - apic) * 1000L / 5; | ||
308 | } else | ||
309 | #endif | ||
310 | { | ||
311 | rdtscll(tsc_start); | ||
312 | |||
313 | do { | ||
314 | apic = apic_read(APIC_TMCCT); | ||
315 | rdtscll(tsc); | ||
316 | } while ((tsc - tsc_start) < TICK_COUNT && | ||
317 | (apic_start - apic) < TICK_COUNT); | ||
318 | |||
319 | result = (apic_start - apic) * 1000L * tsc_khz / | ||
320 | (tsc - tsc_start); | ||
321 | } | ||
322 | |||
323 | local_irq_enable(); | ||
324 | |||
325 | printk(KERN_DEBUG "APIC timer calibration result %d\n", result); | ||
326 | |||
327 | printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n", | ||
328 | result / 1000 / 1000, result / 1000 % 1000); | ||
329 | |||
330 | /* Calculate the scaled math multiplication factor */ | ||
331 | lapic_clockevent.mult = div_sc(result, NSEC_PER_SEC, 32); | ||
332 | lapic_clockevent.max_delta_ns = | ||
333 | clockevent_delta2ns(0x7FFFFF, &lapic_clockevent); | ||
334 | lapic_clockevent.min_delta_ns = | ||
335 | clockevent_delta2ns(0xF, &lapic_clockevent); | ||
336 | |||
337 | calibration_result = result / HZ; | ||
136 | } | 338 | } |
137 | 339 | ||
138 | u32 safe_apic_wait_icr_idle(void) | 340 | void __init setup_boot_APIC_clock(void) |
139 | { | 341 | { |
140 | u32 send_status; | 342 | /* |
141 | int timeout; | 343 | * The local apic timer can be disabled via the kernel commandline. |
344 | * Register the lapic timer as a dummy clock event source on SMP | ||
345 | * systems, so the broadcast mechanism is used. On UP systems simply | ||
346 | * ignore it. | ||
347 | */ | ||
348 | if (disable_apic_timer) { | ||
349 | printk(KERN_INFO "Disabling APIC timer\n"); | ||
350 | /* No broadcast on UP ! */ | ||
351 | if (num_possible_cpus() > 1) | ||
352 | setup_APIC_timer(); | ||
353 | return; | ||
354 | } | ||
142 | 355 | ||
143 | timeout = 0; | 356 | printk(KERN_INFO "Using local APIC timer interrupts.\n"); |
144 | do { | 357 | calibrate_APIC_clock(); |
145 | send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; | ||
146 | if (!send_status) | ||
147 | break; | ||
148 | udelay(100); | ||
149 | } while (timeout++ < 1000); | ||
150 | 358 | ||
151 | return send_status; | 359 | /* |
360 | * If nmi_watchdog is set to IO_APIC, we need the | ||
361 | * PIT/HPET going. Otherwise register lapic as a dummy | ||
362 | * device. | ||
363 | */ | ||
364 | if (nmi_watchdog != NMI_IO_APIC) | ||
365 | lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY; | ||
366 | else | ||
367 | printk(KERN_WARNING "APIC timer registered as dummy," | ||
368 | " due to nmi_watchdog=1!\n"); | ||
369 | |||
370 | setup_APIC_timer(); | ||
152 | } | 371 | } |
153 | 372 | ||
154 | void enable_NMI_through_LVT0 (void * dummy) | 373 | /* |
374 | * AMD C1E enabled CPUs have a real nasty problem: Some BIOSes set the | ||
375 | * C1E flag only in the secondary CPU, so when we detect the wreckage | ||
376 | * we already have enabled the boot CPU local apic timer. Check, if | ||
377 | * disable_apic_timer is set and the DUMMY flag is cleared. If yes, | ||
378 | * set the DUMMY flag again and force the broadcast mode in the | ||
379 | * clockevents layer. | ||
380 | */ | ||
381 | void __cpuinit check_boot_apic_timer_broadcast(void) | ||
155 | { | 382 | { |
156 | unsigned int v; | 383 | if (!disable_apic_timer || |
384 | (lapic_clockevent.features & CLOCK_EVT_FEAT_DUMMY)) | ||
385 | return; | ||
157 | 386 | ||
158 | /* unmask and set to NMI */ | 387 | printk(KERN_INFO "AMD C1E detected late. Force timer broadcast.\n"); |
159 | v = APIC_DM_NMI; | 388 | lapic_clockevent.features |= CLOCK_EVT_FEAT_DUMMY; |
160 | apic_write(APIC_LVT0, v); | 389 | |
390 | local_irq_enable(); | ||
391 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE, &boot_cpu_id); | ||
392 | local_irq_disable(); | ||
161 | } | 393 | } |
162 | 394 | ||
163 | int lapic_get_maxlvt(void) | 395 | void __cpuinit setup_secondary_APIC_clock(void) |
164 | { | 396 | { |
165 | unsigned int v, maxlvt; | 397 | check_boot_apic_timer_broadcast(); |
398 | setup_APIC_timer(); | ||
399 | } | ||
166 | 400 | ||
167 | v = apic_read(APIC_LVR); | 401 | /* |
168 | maxlvt = GET_APIC_MAXLVT(v); | 402 | * The guts of the apic timer interrupt |
169 | return maxlvt; | 403 | */ |
404 | static void local_apic_timer_interrupt(void) | ||
405 | { | ||
406 | int cpu = smp_processor_id(); | ||
407 | struct clock_event_device *evt = &per_cpu(lapic_events, cpu); | ||
408 | |||
409 | /* | ||
410 | * Normally we should not be here till LAPIC has been initialized but | ||
411 | * in some cases like kdump, its possible that there is a pending LAPIC | ||
412 | * timer interrupt from previous kernel's context and is delivered in | ||
413 | * new kernel the moment interrupts are enabled. | ||
414 | * | ||
415 | * Interrupts are enabled early and LAPIC is setup much later, hence | ||
416 | * its possible that when we get here evt->event_handler is NULL. | ||
417 | * Check for event_handler being NULL and discard the interrupt as | ||
418 | * spurious. | ||
419 | */ | ||
420 | if (!evt->event_handler) { | ||
421 | printk(KERN_WARNING | ||
422 | "Spurious LAPIC timer interrupt on cpu %d\n", cpu); | ||
423 | /* Switch it off */ | ||
424 | lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, evt); | ||
425 | return; | ||
426 | } | ||
427 | |||
428 | /* | ||
429 | * the NMI deadlock-detector uses this. | ||
430 | */ | ||
431 | add_pda(apic_timer_irqs, 1); | ||
432 | |||
433 | evt->event_handler(evt); | ||
170 | } | 434 | } |
171 | 435 | ||
172 | void clear_local_APIC(void) | 436 | /* |
437 | * Local APIC timer interrupt. This is the most natural way for doing | ||
438 | * local interrupts, but local timer interrupts can be emulated by | ||
439 | * broadcast interrupts too. [in case the hw doesn't support APIC timers] | ||
440 | * | ||
441 | * [ if a single-CPU system runs an SMP kernel then we call the local | ||
442 | * interrupt as well. Thus we cannot inline the local irq ... ] | ||
443 | */ | ||
444 | void smp_apic_timer_interrupt(struct pt_regs *regs) | ||
173 | { | 445 | { |
174 | int maxlvt; | 446 | struct pt_regs *old_regs = set_irq_regs(regs); |
175 | unsigned int v; | ||
176 | 447 | ||
177 | maxlvt = lapic_get_maxlvt(); | 448 | /* |
449 | * NOTE! We'd better ACK the irq immediately, | ||
450 | * because timer handling can be slow. | ||
451 | */ | ||
452 | ack_APIC_irq(); | ||
453 | /* | ||
454 | * update_process_times() expects us to have done irq_enter(). | ||
455 | * Besides, if we don't timer interrupts ignore the global | ||
456 | * interrupt lock, which is the WrongThing (tm) to do. | ||
457 | */ | ||
458 | exit_idle(); | ||
459 | irq_enter(); | ||
460 | local_apic_timer_interrupt(); | ||
461 | irq_exit(); | ||
462 | set_irq_regs(old_regs); | ||
463 | } | ||
464 | |||
465 | int setup_profiling_timer(unsigned int multiplier) | ||
466 | { | ||
467 | return -EINVAL; | ||
468 | } | ||
469 | |||
470 | |||
471 | /* | ||
472 | * Local APIC start and shutdown | ||
473 | */ | ||
474 | |||
475 | /** | ||
476 | * clear_local_APIC - shutdown the local APIC | ||
477 | * | ||
478 | * This is called, when a CPU is disabled and before rebooting, so the state of | ||
479 | * the local APIC has no dangling leftovers. Also used to cleanout any BIOS | ||
480 | * leftovers during boot. | ||
481 | */ | ||
482 | void clear_local_APIC(void) | ||
483 | { | ||
484 | int maxlvt = lapic_get_maxlvt(); | ||
485 | u32 v; | ||
178 | 486 | ||
179 | /* | 487 | /* |
180 | * Masking an LVT entry can trigger a local APIC error | 488 | * Masking an LVT entry can trigger a local APIC error |
@@ -213,45 +521,9 @@ void clear_local_APIC(void) | |||
213 | apic_read(APIC_ESR); | 521 | apic_read(APIC_ESR); |
214 | } | 522 | } |
215 | 523 | ||
216 | void disconnect_bsp_APIC(int virt_wire_setup) | 524 | /** |
217 | { | 525 | * disable_local_APIC - clear and disable the local APIC |
218 | /* Go back to Virtual Wire compatibility mode */ | 526 | */ |
219 | unsigned long value; | ||
220 | |||
221 | /* For the spurious interrupt use vector F, and enable it */ | ||
222 | value = apic_read(APIC_SPIV); | ||
223 | value &= ~APIC_VECTOR_MASK; | ||
224 | value |= APIC_SPIV_APIC_ENABLED; | ||
225 | value |= 0xf; | ||
226 | apic_write(APIC_SPIV, value); | ||
227 | |||
228 | if (!virt_wire_setup) { | ||
229 | /* | ||
230 | * For LVT0 make it edge triggered, active high, | ||
231 | * external and enabled | ||
232 | */ | ||
233 | value = apic_read(APIC_LVT0); | ||
234 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | | ||
235 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | ||
236 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED ); | ||
237 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; | ||
238 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT); | ||
239 | apic_write(APIC_LVT0, value); | ||
240 | } else { | ||
241 | /* Disable LVT0 */ | ||
242 | apic_write(APIC_LVT0, APIC_LVT_MASKED); | ||
243 | } | ||
244 | |||
245 | /* For LVT1 make it edge triggered, active high, nmi and enabled */ | ||
246 | value = apic_read(APIC_LVT1); | ||
247 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | | ||
248 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | ||
249 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); | ||
250 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; | ||
251 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI); | ||
252 | apic_write(APIC_LVT1, value); | ||
253 | } | ||
254 | |||
255 | void disable_local_APIC(void) | 527 | void disable_local_APIC(void) |
256 | { | 528 | { |
257 | unsigned int value; | 529 | unsigned int value; |
@@ -335,18 +607,20 @@ int __init verify_local_APIC(void) | |||
335 | * compatibility mode, but most boxes are anymore. | 607 | * compatibility mode, but most boxes are anymore. |
336 | */ | 608 | */ |
337 | reg0 = apic_read(APIC_LVT0); | 609 | reg0 = apic_read(APIC_LVT0); |
338 | apic_printk(APIC_DEBUG,"Getting LVT0: %x\n", reg0); | 610 | apic_printk(APIC_DEBUG, "Getting LVT0: %x\n", reg0); |
339 | reg1 = apic_read(APIC_LVT1); | 611 | reg1 = apic_read(APIC_LVT1); |
340 | apic_printk(APIC_DEBUG, "Getting LVT1: %x\n", reg1); | 612 | apic_printk(APIC_DEBUG, "Getting LVT1: %x\n", reg1); |
341 | 613 | ||
342 | return 1; | 614 | return 1; |
343 | } | 615 | } |
344 | 616 | ||
617 | /** | ||
618 | * sync_Arb_IDs - synchronize APIC bus arbitration IDs | ||
619 | */ | ||
345 | void __init sync_Arb_IDs(void) | 620 | void __init sync_Arb_IDs(void) |
346 | { | 621 | { |
347 | /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */ | 622 | /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */ |
348 | unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR)); | 623 | if (modern_apic()) |
349 | if (ver >= 0x14) /* P4 or higher */ | ||
350 | return; | 624 | return; |
351 | 625 | ||
352 | /* | 626 | /* |
@@ -398,7 +672,10 @@ void __init init_bsp_APIC(void) | |||
398 | apic_write(APIC_LVT1, value); | 672 | apic_write(APIC_LVT1, value); |
399 | } | 673 | } |
400 | 674 | ||
401 | void __cpuinit setup_local_APIC (void) | 675 | /** |
676 | * setup_local_APIC - setup the local APIC | ||
677 | */ | ||
678 | void __cpuinit setup_local_APIC(void) | ||
402 | { | 679 | { |
403 | unsigned int value, maxlvt; | 680 | unsigned int value, maxlvt; |
404 | int i, j; | 681 | int i, j; |
@@ -520,6 +797,188 @@ void __cpuinit setup_local_APIC (void) | |||
520 | apic_pm_activate(); | 797 | apic_pm_activate(); |
521 | } | 798 | } |
522 | 799 | ||
800 | /* | ||
801 | * Detect and enable local APICs on non-SMP boards. | ||
802 | * Original code written by Keir Fraser. | ||
803 | * On AMD64 we trust the BIOS - if it says no APIC it is likely | ||
804 | * not correctly set up (usually the APIC timer won't work etc.) | ||
805 | */ | ||
806 | static int __init detect_init_APIC(void) | ||
807 | { | ||
808 | if (!cpu_has_apic) { | ||
809 | printk(KERN_INFO "No local APIC present\n"); | ||
810 | return -1; | ||
811 | } | ||
812 | |||
813 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; | ||
814 | boot_cpu_id = 0; | ||
815 | return 0; | ||
816 | } | ||
817 | |||
818 | /** | ||
819 | * init_apic_mappings - initialize APIC mappings | ||
820 | */ | ||
821 | void __init init_apic_mappings(void) | ||
822 | { | ||
823 | unsigned long apic_phys; | ||
824 | |||
825 | /* | ||
826 | * If no local APIC can be found then set up a fake all | ||
827 | * zeroes page to simulate the local APIC and another | ||
828 | * one for the IO-APIC. | ||
829 | */ | ||
830 | if (!smp_found_config && detect_init_APIC()) { | ||
831 | apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); | ||
832 | apic_phys = __pa(apic_phys); | ||
833 | } else | ||
834 | apic_phys = mp_lapic_addr; | ||
835 | |||
836 | set_fixmap_nocache(FIX_APIC_BASE, apic_phys); | ||
837 | apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", | ||
838 | APIC_BASE, apic_phys); | ||
839 | |||
840 | /* Put local APIC into the resource map. */ | ||
841 | lapic_resource.start = apic_phys; | ||
842 | lapic_resource.end = lapic_resource.start + PAGE_SIZE - 1; | ||
843 | insert_resource(&iomem_resource, &lapic_resource); | ||
844 | |||
845 | /* | ||
846 | * Fetch the APIC ID of the BSP in case we have a | ||
847 | * default configuration (or the MP table is broken). | ||
848 | */ | ||
849 | boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID)); | ||
850 | } | ||
851 | |||
852 | /* | ||
853 | * This initializes the IO-APIC and APIC hardware if this is | ||
854 | * a UP kernel. | ||
855 | */ | ||
856 | int __init APIC_init_uniprocessor(void) | ||
857 | { | ||
858 | if (disable_apic) { | ||
859 | printk(KERN_INFO "Apic disabled\n"); | ||
860 | return -1; | ||
861 | } | ||
862 | if (!cpu_has_apic) { | ||
863 | disable_apic = 1; | ||
864 | printk(KERN_INFO "Apic disabled by BIOS\n"); | ||
865 | return -1; | ||
866 | } | ||
867 | |||
868 | verify_local_APIC(); | ||
869 | |||
870 | phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id); | ||
871 | apic_write(APIC_ID, SET_APIC_ID(boot_cpu_id)); | ||
872 | |||
873 | setup_local_APIC(); | ||
874 | |||
875 | if (smp_found_config && !skip_ioapic_setup && nr_ioapics) | ||
876 | setup_IO_APIC(); | ||
877 | else | ||
878 | nr_ioapics = 0; | ||
879 | setup_boot_APIC_clock(); | ||
880 | check_nmi_watchdog(); | ||
881 | return 0; | ||
882 | } | ||
883 | |||
884 | /* | ||
885 | * Local APIC interrupts | ||
886 | */ | ||
887 | |||
888 | /* | ||
889 | * This interrupt should _never_ happen with our APIC/SMP architecture | ||
890 | */ | ||
891 | asmlinkage void smp_spurious_interrupt(void) | ||
892 | { | ||
893 | unsigned int v; | ||
894 | exit_idle(); | ||
895 | irq_enter(); | ||
896 | /* | ||
897 | * Check if this really is a spurious interrupt and ACK it | ||
898 | * if it is a vectored one. Just in case... | ||
899 | * Spurious interrupts should not be ACKed. | ||
900 | */ | ||
901 | v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1)); | ||
902 | if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f))) | ||
903 | ack_APIC_irq(); | ||
904 | |||
905 | add_pda(irq_spurious_count, 1); | ||
906 | irq_exit(); | ||
907 | } | ||
908 | |||
909 | /* | ||
910 | * This interrupt should never happen with our APIC/SMP architecture | ||
911 | */ | ||
912 | asmlinkage void smp_error_interrupt(void) | ||
913 | { | ||
914 | unsigned int v, v1; | ||
915 | |||
916 | exit_idle(); | ||
917 | irq_enter(); | ||
918 | /* First tickle the hardware, only then report what went on. -- REW */ | ||
919 | v = apic_read(APIC_ESR); | ||
920 | apic_write(APIC_ESR, 0); | ||
921 | v1 = apic_read(APIC_ESR); | ||
922 | ack_APIC_irq(); | ||
923 | atomic_inc(&irq_err_count); | ||
924 | |||
925 | /* Here is what the APIC error bits mean: | ||
926 | 0: Send CS error | ||
927 | 1: Receive CS error | ||
928 | 2: Send accept error | ||
929 | 3: Receive accept error | ||
930 | 4: Reserved | ||
931 | 5: Send illegal vector | ||
932 | 6: Received illegal vector | ||
933 | 7: Illegal register address | ||
934 | */ | ||
935 | printk(KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n", | ||
936 | smp_processor_id(), v , v1); | ||
937 | irq_exit(); | ||
938 | } | ||
939 | |||
940 | void disconnect_bsp_APIC(int virt_wire_setup) | ||
941 | { | ||
942 | /* Go back to Virtual Wire compatibility mode */ | ||
943 | unsigned long value; | ||
944 | |||
945 | /* For the spurious interrupt use vector F, and enable it */ | ||
946 | value = apic_read(APIC_SPIV); | ||
947 | value &= ~APIC_VECTOR_MASK; | ||
948 | value |= APIC_SPIV_APIC_ENABLED; | ||
949 | value |= 0xf; | ||
950 | apic_write(APIC_SPIV, value); | ||
951 | |||
952 | if (!virt_wire_setup) { | ||
953 | /* | ||
954 | * For LVT0 make it edge triggered, active high, | ||
955 | * external and enabled | ||
956 | */ | ||
957 | value = apic_read(APIC_LVT0); | ||
958 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | | ||
959 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | ||
960 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); | ||
961 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; | ||
962 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT); | ||
963 | apic_write(APIC_LVT0, value); | ||
964 | } else { | ||
965 | /* Disable LVT0 */ | ||
966 | apic_write(APIC_LVT0, APIC_LVT_MASKED); | ||
967 | } | ||
968 | |||
969 | /* For LVT1 make it edge triggered, active high, nmi and enabled */ | ||
970 | value = apic_read(APIC_LVT1); | ||
971 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | | ||
972 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | ||
973 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); | ||
974 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; | ||
975 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI); | ||
976 | apic_write(APIC_LVT1, value); | ||
977 | } | ||
978 | |||
979 | /* | ||
980 | * Power management | ||
981 | */ | ||
523 | #ifdef CONFIG_PM | 982 | #ifdef CONFIG_PM |
524 | 983 | ||
525 | static struct { | 984 | static struct { |
@@ -653,337 +1112,6 @@ static void apic_pm_activate(void) { } | |||
653 | 1112 | ||
654 | #endif /* CONFIG_PM */ | 1113 | #endif /* CONFIG_PM */ |
655 | 1114 | ||
656 | static int __init apic_set_verbosity(char *str) | ||
657 | { | ||
658 | if (str == NULL) { | ||
659 | skip_ioapic_setup = 0; | ||
660 | ioapic_force = 1; | ||
661 | return 0; | ||
662 | } | ||
663 | if (strcmp("debug", str) == 0) | ||
664 | apic_verbosity = APIC_DEBUG; | ||
665 | else if (strcmp("verbose", str) == 0) | ||
666 | apic_verbosity = APIC_VERBOSE; | ||
667 | else { | ||
668 | printk(KERN_WARNING "APIC Verbosity level %s not recognised" | ||
669 | " use apic=verbose or apic=debug\n", str); | ||
670 | return -EINVAL; | ||
671 | } | ||
672 | |||
673 | return 0; | ||
674 | } | ||
675 | early_param("apic", apic_set_verbosity); | ||
676 | |||
677 | /* | ||
678 | * Detect and enable local APICs on non-SMP boards. | ||
679 | * Original code written by Keir Fraser. | ||
680 | * On AMD64 we trust the BIOS - if it says no APIC it is likely | ||
681 | * not correctly set up (usually the APIC timer won't work etc.) | ||
682 | */ | ||
683 | |||
684 | static int __init detect_init_APIC (void) | ||
685 | { | ||
686 | if (!cpu_has_apic) { | ||
687 | printk(KERN_INFO "No local APIC present\n"); | ||
688 | return -1; | ||
689 | } | ||
690 | |||
691 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; | ||
692 | boot_cpu_id = 0; | ||
693 | return 0; | ||
694 | } | ||
695 | |||
696 | void __init init_apic_mappings(void) | ||
697 | { | ||
698 | unsigned long apic_phys; | ||
699 | |||
700 | /* | ||
701 | * If no local APIC can be found then set up a fake all | ||
702 | * zeroes page to simulate the local APIC and another | ||
703 | * one for the IO-APIC. | ||
704 | */ | ||
705 | if (!smp_found_config && detect_init_APIC()) { | ||
706 | apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); | ||
707 | apic_phys = __pa(apic_phys); | ||
708 | } else | ||
709 | apic_phys = mp_lapic_addr; | ||
710 | |||
711 | set_fixmap_nocache(FIX_APIC_BASE, apic_phys); | ||
712 | apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", | ||
713 | APIC_BASE, apic_phys); | ||
714 | |||
715 | /* Put local APIC into the resource map. */ | ||
716 | lapic_resource.start = apic_phys; | ||
717 | lapic_resource.end = lapic_resource.start + PAGE_SIZE - 1; | ||
718 | insert_resource(&iomem_resource, &lapic_resource); | ||
719 | |||
720 | /* | ||
721 | * Fetch the APIC ID of the BSP in case we have a | ||
722 | * default configuration (or the MP table is broken). | ||
723 | */ | ||
724 | boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID)); | ||
725 | } | ||
726 | |||
727 | /* | ||
728 | * This function sets up the local APIC timer, with a timeout of | ||
729 | * 'clocks' APIC bus clock. During calibration we actually call | ||
730 | * this function twice on the boot CPU, once with a bogus timeout | ||
731 | * value, second time for real. The other (noncalibrating) CPUs | ||
732 | * call this function only once, with the real, calibrated value. | ||
733 | * | ||
734 | * We do reads before writes even if unnecessary, to get around the | ||
735 | * P5 APIC double write bug. | ||
736 | */ | ||
737 | |||
738 | static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) | ||
739 | { | ||
740 | unsigned int lvtt_value, tmp_value; | ||
741 | |||
742 | lvtt_value = LOCAL_TIMER_VECTOR; | ||
743 | if (!oneshot) | ||
744 | lvtt_value |= APIC_LVT_TIMER_PERIODIC; | ||
745 | if (!irqen) | ||
746 | lvtt_value |= APIC_LVT_MASKED; | ||
747 | |||
748 | apic_write(APIC_LVTT, lvtt_value); | ||
749 | |||
750 | /* | ||
751 | * Divide PICLK by 16 | ||
752 | */ | ||
753 | tmp_value = apic_read(APIC_TDCR); | ||
754 | apic_write(APIC_TDCR, (tmp_value | ||
755 | & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | ||
756 | | APIC_TDR_DIV_16); | ||
757 | |||
758 | if (!oneshot) | ||
759 | apic_write(APIC_TMICT, clocks); | ||
760 | } | ||
761 | |||
762 | static void setup_APIC_timer(void) | ||
763 | { | ||
764 | struct clock_event_device *levt = &__get_cpu_var(lapic_events); | ||
765 | |||
766 | memcpy(levt, &lapic_clockevent, sizeof(*levt)); | ||
767 | levt->cpumask = cpumask_of_cpu(smp_processor_id()); | ||
768 | |||
769 | clockevents_register_device(levt); | ||
770 | } | ||
771 | |||
772 | /* | ||
773 | * In this function we calibrate APIC bus clocks to the external | ||
774 | * timer. Unfortunately we cannot use jiffies and the timer irq | ||
775 | * to calibrate, since some later bootup code depends on getting | ||
776 | * the first irq? Ugh. | ||
777 | * | ||
778 | * We want to do the calibration only once since we | ||
779 | * want to have local timer irqs syncron. CPUs connected | ||
780 | * by the same APIC bus have the very same bus frequency. | ||
781 | * And we want to have irqs off anyways, no accidental | ||
782 | * APIC irq that way. | ||
783 | */ | ||
784 | |||
785 | #define TICK_COUNT 100000000 | ||
786 | |||
787 | static void __init calibrate_APIC_clock(void) | ||
788 | { | ||
789 | unsigned apic, apic_start; | ||
790 | unsigned long tsc, tsc_start; | ||
791 | int result; | ||
792 | |||
793 | local_irq_disable(); | ||
794 | |||
795 | /* | ||
796 | * Put whatever arbitrary (but long enough) timeout | ||
797 | * value into the APIC clock, we just want to get the | ||
798 | * counter running for calibration. | ||
799 | * | ||
800 | * No interrupt enable ! | ||
801 | */ | ||
802 | __setup_APIC_LVTT(250000000, 0, 0); | ||
803 | |||
804 | apic_start = apic_read(APIC_TMCCT); | ||
805 | #ifdef CONFIG_X86_PM_TIMER | ||
806 | if (apic_calibrate_pmtmr && pmtmr_ioport) { | ||
807 | pmtimer_wait(5000); /* 5ms wait */ | ||
808 | apic = apic_read(APIC_TMCCT); | ||
809 | result = (apic_start - apic) * 1000L / 5; | ||
810 | } else | ||
811 | #endif | ||
812 | { | ||
813 | rdtscll(tsc_start); | ||
814 | |||
815 | do { | ||
816 | apic = apic_read(APIC_TMCCT); | ||
817 | rdtscll(tsc); | ||
818 | } while ((tsc - tsc_start) < TICK_COUNT && | ||
819 | (apic_start - apic) < TICK_COUNT); | ||
820 | |||
821 | result = (apic_start - apic) * 1000L * tsc_khz / | ||
822 | (tsc - tsc_start); | ||
823 | } | ||
824 | |||
825 | local_irq_enable(); | ||
826 | |||
827 | printk(KERN_DEBUG "APIC timer calibration result %d\n", result); | ||
828 | |||
829 | printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n", | ||
830 | result / 1000 / 1000, result / 1000 % 1000); | ||
831 | |||
832 | /* Calculate the scaled math multiplication factor */ | ||
833 | lapic_clockevent.mult = div_sc(result, NSEC_PER_SEC, 32); | ||
834 | lapic_clockevent.max_delta_ns = | ||
835 | clockevent_delta2ns(0x7FFFFF, &lapic_clockevent); | ||
836 | lapic_clockevent.min_delta_ns = | ||
837 | clockevent_delta2ns(0xF, &lapic_clockevent); | ||
838 | |||
839 | calibration_result = result / HZ; | ||
840 | } | ||
841 | |||
842 | void __init setup_boot_APIC_clock (void) | ||
843 | { | ||
844 | /* | ||
845 | * The local apic timer can be disabled via the kernel commandline. | ||
846 | * Register the lapic timer as a dummy clock event source on SMP | ||
847 | * systems, so the broadcast mechanism is used. On UP systems simply | ||
848 | * ignore it. | ||
849 | */ | ||
850 | if (disable_apic_timer) { | ||
851 | printk(KERN_INFO "Disabling APIC timer\n"); | ||
852 | /* No broadcast on UP ! */ | ||
853 | if (num_possible_cpus() > 1) | ||
854 | setup_APIC_timer(); | ||
855 | return; | ||
856 | } | ||
857 | |||
858 | printk(KERN_INFO "Using local APIC timer interrupts.\n"); | ||
859 | calibrate_APIC_clock(); | ||
860 | |||
861 | /* | ||
862 | * If nmi_watchdog is set to IO_APIC, we need the | ||
863 | * PIT/HPET going. Otherwise register lapic as a dummy | ||
864 | * device. | ||
865 | */ | ||
866 | if (nmi_watchdog != NMI_IO_APIC) | ||
867 | lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY; | ||
868 | else | ||
869 | printk(KERN_WARNING "APIC timer registered as dummy," | ||
870 | " due to nmi_watchdog=1!\n"); | ||
871 | |||
872 | setup_APIC_timer(); | ||
873 | } | ||
874 | |||
875 | /* | ||
876 | * AMD C1E enabled CPUs have a real nasty problem: Some BIOSes set the | ||
877 | * C1E flag only in the secondary CPU, so when we detect the wreckage | ||
878 | * we already have enabled the boot CPU local apic timer. Check, if | ||
879 | * disable_apic_timer is set and the DUMMY flag is cleared. If yes, | ||
880 | * set the DUMMY flag again and force the broadcast mode in the | ||
881 | * clockevents layer. | ||
882 | */ | ||
883 | void __cpuinit check_boot_apic_timer_broadcast(void) | ||
884 | { | ||
885 | if (!disable_apic_timer || | ||
886 | (lapic_clockevent.features & CLOCK_EVT_FEAT_DUMMY)) | ||
887 | return; | ||
888 | |||
889 | printk(KERN_INFO "AMD C1E detected late. Force timer broadcast.\n"); | ||
890 | lapic_clockevent.features |= CLOCK_EVT_FEAT_DUMMY; | ||
891 | |||
892 | local_irq_enable(); | ||
893 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE, &boot_cpu_id); | ||
894 | local_irq_disable(); | ||
895 | } | ||
896 | |||
897 | void __cpuinit setup_secondary_APIC_clock(void) | ||
898 | { | ||
899 | check_boot_apic_timer_broadcast(); | ||
900 | setup_APIC_timer(); | ||
901 | } | ||
902 | |||
903 | int setup_profiling_timer(unsigned int multiplier) | ||
904 | { | ||
905 | return -EINVAL; | ||
906 | } | ||
907 | |||
908 | void setup_APIC_extended_lvt(unsigned char lvt_off, unsigned char vector, | ||
909 | unsigned char msg_type, unsigned char mask) | ||
910 | { | ||
911 | unsigned long reg = (lvt_off << 4) + K8_APIC_EXT_LVT_BASE; | ||
912 | unsigned int v = (mask << 16) | (msg_type << 8) | vector; | ||
913 | apic_write(reg, v); | ||
914 | } | ||
915 | |||
916 | /* | ||
917 | * Local timer interrupt handler. It does both profiling and | ||
918 | * process statistics/rescheduling. | ||
919 | * | ||
920 | * We do profiling in every local tick, statistics/rescheduling | ||
921 | * happen only every 'profiling multiplier' ticks. The default | ||
922 | * multiplier is 1 and it can be changed by writing the new multiplier | ||
923 | * value into /proc/profile. | ||
924 | */ | ||
925 | |||
926 | static void smp_local_timer_interrupt(void) | ||
927 | { | ||
928 | int cpu = smp_processor_id(); | ||
929 | struct clock_event_device *evt = &per_cpu(lapic_events, cpu); | ||
930 | |||
931 | /* | ||
932 | * Normally we should not be here till LAPIC has been initialized but | ||
933 | * in some cases like kdump, its possible that there is a pending LAPIC | ||
934 | * timer interrupt from previous kernel's context and is delivered in | ||
935 | * new kernel the moment interrupts are enabled. | ||
936 | * | ||
937 | * Interrupts are enabled early and LAPIC is setup much later, hence | ||
938 | * its possible that when we get here evt->event_handler is NULL. | ||
939 | * Check for event_handler being NULL and discard the interrupt as | ||
940 | * spurious. | ||
941 | */ | ||
942 | if (!evt->event_handler) { | ||
943 | printk(KERN_WARNING | ||
944 | "Spurious LAPIC timer interrupt on cpu %d\n", cpu); | ||
945 | /* Switch it off */ | ||
946 | lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, evt); | ||
947 | return; | ||
948 | } | ||
949 | |||
950 | /* | ||
951 | * the NMI deadlock-detector uses this. | ||
952 | */ | ||
953 | add_pda(apic_timer_irqs, 1); | ||
954 | |||
955 | evt->event_handler(evt); | ||
956 | } | ||
957 | |||
958 | /* | ||
959 | * Local APIC timer interrupt. This is the most natural way for doing | ||
960 | * local interrupts, but local timer interrupts can be emulated by | ||
961 | * broadcast interrupts too. [in case the hw doesn't support APIC timers] | ||
962 | * | ||
963 | * [ if a single-CPU system runs an SMP kernel then we call the local | ||
964 | * interrupt as well. Thus we cannot inline the local irq ... ] | ||
965 | */ | ||
966 | void smp_apic_timer_interrupt(struct pt_regs *regs) | ||
967 | { | ||
968 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
969 | |||
970 | /* | ||
971 | * NOTE! We'd better ACK the irq immediately, | ||
972 | * because timer handling can be slow. | ||
973 | */ | ||
974 | ack_APIC_irq(); | ||
975 | /* | ||
976 | * update_process_times() expects us to have done irq_enter(). | ||
977 | * Besides, if we don't timer interrupts ignore the global | ||
978 | * interrupt lock, which is the WrongThing (tm) to do. | ||
979 | */ | ||
980 | exit_idle(); | ||
981 | irq_enter(); | ||
982 | smp_local_timer_interrupt(); | ||
983 | irq_exit(); | ||
984 | set_irq_regs(old_regs); | ||
985 | } | ||
986 | |||
987 | /* | 1115 | /* |
988 | * apic_is_clustered_box() -- Check if we can expect good TSC | 1116 | * apic_is_clustered_box() -- Check if we can expect good TSC |
989 | * | 1117 | * |
@@ -1032,91 +1160,28 @@ __cpuinit int apic_is_clustered_box(void) | |||
1032 | } | 1160 | } |
1033 | 1161 | ||
1034 | /* | 1162 | /* |
1035 | * This interrupt should _never_ happen with our APIC/SMP architecture | 1163 | * APIC command line parameters |
1036 | */ | ||
1037 | asmlinkage void smp_spurious_interrupt(void) | ||
1038 | { | ||
1039 | unsigned int v; | ||
1040 | exit_idle(); | ||
1041 | irq_enter(); | ||
1042 | /* | ||
1043 | * Check if this really is a spurious interrupt and ACK it | ||
1044 | * if it is a vectored one. Just in case... | ||
1045 | * Spurious interrupts should not be ACKed. | ||
1046 | */ | ||
1047 | v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1)); | ||
1048 | if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f))) | ||
1049 | ack_APIC_irq(); | ||
1050 | |||
1051 | add_pda(irq_spurious_count, 1); | ||
1052 | irq_exit(); | ||
1053 | } | ||
1054 | |||
1055 | /* | ||
1056 | * This interrupt should never happen with our APIC/SMP architecture | ||
1057 | */ | ||
1058 | |||
1059 | asmlinkage void smp_error_interrupt(void) | ||
1060 | { | ||
1061 | unsigned int v, v1; | ||
1062 | |||
1063 | exit_idle(); | ||
1064 | irq_enter(); | ||
1065 | /* First tickle the hardware, only then report what went on. -- REW */ | ||
1066 | v = apic_read(APIC_ESR); | ||
1067 | apic_write(APIC_ESR, 0); | ||
1068 | v1 = apic_read(APIC_ESR); | ||
1069 | ack_APIC_irq(); | ||
1070 | atomic_inc(&irq_err_count); | ||
1071 | |||
1072 | /* Here is what the APIC error bits mean: | ||
1073 | 0: Send CS error | ||
1074 | 1: Receive CS error | ||
1075 | 2: Send accept error | ||
1076 | 3: Receive accept error | ||
1077 | 4: Reserved | ||
1078 | 5: Send illegal vector | ||
1079 | 6: Received illegal vector | ||
1080 | 7: Illegal register address | ||
1081 | */ | ||
1082 | printk (KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n", | ||
1083 | smp_processor_id(), v , v1); | ||
1084 | irq_exit(); | ||
1085 | } | ||
1086 | |||
1087 | int disable_apic; | ||
1088 | |||
1089 | /* | ||
1090 | * This initializes the IO-APIC and APIC hardware if this is | ||
1091 | * a UP kernel. | ||
1092 | */ | 1164 | */ |
1093 | int __init APIC_init_uniprocessor (void) | 1165 | static int __init apic_set_verbosity(char *str) |
1094 | { | 1166 | { |
1095 | if (disable_apic) { | 1167 | if (str == NULL) { |
1096 | printk(KERN_INFO "Apic disabled\n"); | 1168 | skip_ioapic_setup = 0; |
1097 | return -1; | 1169 | ioapic_force = 1; |
1170 | return 0; | ||
1098 | } | 1171 | } |
1099 | if (!cpu_has_apic) { | 1172 | if (strcmp("debug", str) == 0) |
1100 | disable_apic = 1; | 1173 | apic_verbosity = APIC_DEBUG; |
1101 | printk(KERN_INFO "Apic disabled by BIOS\n"); | 1174 | else if (strcmp("verbose", str) == 0) |
1102 | return -1; | 1175 | apic_verbosity = APIC_VERBOSE; |
1176 | else { | ||
1177 | printk(KERN_WARNING "APIC Verbosity level %s not recognised" | ||
1178 | " use apic=verbose or apic=debug\n", str); | ||
1179 | return -EINVAL; | ||
1103 | } | 1180 | } |
1104 | 1181 | ||
1105 | verify_local_APIC(); | ||
1106 | |||
1107 | phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id); | ||
1108 | apic_write(APIC_ID, SET_APIC_ID(boot_cpu_id)); | ||
1109 | |||
1110 | setup_local_APIC(); | ||
1111 | |||
1112 | if (smp_found_config && !skip_ioapic_setup && nr_ioapics) | ||
1113 | setup_IO_APIC(); | ||
1114 | else | ||
1115 | nr_ioapics = 0; | ||
1116 | setup_boot_APIC_clock(); | ||
1117 | check_nmi_watchdog(); | ||
1118 | return 0; | 1182 | return 0; |
1119 | } | 1183 | } |
1184 | early_param("apic", apic_set_verbosity); | ||
1120 | 1185 | ||
1121 | static __init int setup_disableapic(char *str) | 1186 | static __init int setup_disableapic(char *str) |
1122 | { | 1187 | { |