ia64/xen-unstable

annotate xen/arch/x86/apic.c @ 19501:085d22289e1b

x86: imply 'noapic' from 'nolapic'

While in the comments to an earlier submitted (and already applied)
patch I claimed to have fixed the need to specify both "nolapic" and
"noapic" when "nolapic" alone should already have the intended effect,
this doesn't appear to be the case. Here are the missing bits.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Apr 02 13:02:13 2009 +0100 (2009-04-02)
parents 59274c49a029
children 6705898f768d
rev   line source
kaf24@1452 1 /*
kfraser@11541 2 * based on linux-2.6.17.13/arch/i386/kernel/apic.c
iap10@4548 3 *
kaf24@1452 4 * Local APIC handling, local APIC timers
kaf24@1452 5 *
kaf24@1452 6 * (c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
kaf24@1452 7 *
kaf24@1452 8 * Fixes
kaf24@1452 9 * Maciej W. Rozycki : Bits for genuine 82489DX APICs;
kaf24@1452 10 * thanks to Eric Gilmore
kaf24@1452 11 * and Rolf G. Tews
kaf24@1452 12 * for testing these extensively.
kfraser@11204 13 * Maciej W. Rozycki : Various updates and fixes.
kfraser@11204 14 * Mikael Pettersson : Power Management for UP-APIC.
iap10@4548 15 * Pavel Machek and
iap10@4548 16 * Mikael Pettersson : PM converted to driver model.
kaf24@1452 17 */
kaf24@1452 18
kaf24@1452 19 #include <xen/config.h>
kaf24@1506 20 #include <xen/perfc.h>
kaf24@1506 21 #include <xen/errno.h>
kaf24@1452 22 #include <xen/init.h>
kaf24@1506 23 #include <xen/mm.h>
kaf24@1452 24 #include <xen/sched.h>
kaf24@1452 25 #include <xen/irq.h>
kaf24@1452 26 #include <xen/delay.h>
kaf24@1506 27 #include <xen/smp.h>
kaf24@1506 28 #include <xen/softirq.h>
kaf24@1452 29 #include <asm/mc146818rtc.h>
kaf24@1452 30 #include <asm/msr.h>
kaf24@1452 31 #include <asm/atomic.h>
kaf24@1452 32 #include <asm/mpspec.h>
kaf24@1452 33 #include <asm/flushtlb.h>
kaf24@1452 34 #include <asm/hardirq.h>
kaf24@1452 35 #include <asm/apic.h>
kaf24@1452 36 #include <asm/io_apic.h>
kaf24@4804 37 #include <mach_apic.h>
kaf24@4804 38 #include <io_ports.h>
kaf24@1452 39
kaf24@4888 40 /*
kaf24@8847 41 * Knob to control our willingness to enable the local APIC.
kaf24@8847 42 */
keir@19039 43 static int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
kaf24@8847 44
kaf24@8847 45 /*
kaf24@4888 46 * Debug level
kaf24@4888 47 */
kaf24@4888 48 int apic_verbosity;
kaf24@4888 49
keir@17552 50 int x2apic_enabled __read_mostly = 0;
keir@17552 51
kaf24@8847 52
kaf24@8847 53 static void apic_pm_activate(void);
kaf24@8847 54
kfraser@11541 55 int modern_apic(void)
kfraser@11541 56 {
kfraser@11541 57 unsigned int lvr, version;
kfraser@11541 58 /* AMD systems use old APIC versions, so check the CPU */
kfraser@11541 59 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
kfraser@11541 60 boot_cpu_data.x86 >= 0xf)
kfraser@11541 61 return 1;
kfraser@11541 62 lvr = apic_read(APIC_LVR);
kfraser@11541 63 version = GET_APIC_VERSION(lvr);
kfraser@11541 64 return version >= 0x14;
kfraser@11541 65 }
kfraser@11541 66
kaf24@8847 67 /*
kaf24@8847 68 * 'what should we do if we get a hw irq event on an illegal vector'.
kaf24@8847 69 * each architecture has to answer this themselves.
kaf24@8847 70 */
kaf24@8847 71 void ack_bad_irq(unsigned int irq)
kaf24@8847 72 {
kaf24@8847 73 printk("unexpected IRQ trap at vector %02x\n", irq);
kaf24@8847 74 /*
kaf24@8847 75 * Currently unexpected vectors happen only on SMP and APIC.
kaf24@8847 76 * We _must_ ack these because every local APIC has only N
kaf24@8847 77 * irq slots per priority level, and a 'hanging, unacked' IRQ
kaf24@8847 78 * holds up an irq slot - in excessive cases (when multiple
kaf24@8847 79 * unexpected vectors occur) that might lock up the APIC
kaf24@8847 80 * completely.
kfraser@11541 81 * But only ack when the APIC is enabled -AK
kaf24@8847 82 */
kfraser@11541 83 if (cpu_has_apic)
kfraser@11541 84 ack_APIC_irq();
kaf24@8847 85 }
kaf24@8847 86
kaf24@8847 87 void __init apic_intr_init(void)
kaf24@8847 88 {
kaf24@8847 89 #ifdef CONFIG_SMP
kaf24@8847 90 smp_intr_init();
kaf24@8847 91 #endif
kaf24@8847 92 /* self generated IPI for local APIC timer */
kaf24@8847 93 set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
kaf24@8847 94
kaf24@8847 95 /* IPI vectors for APIC spurious and error interrupts */
kaf24@8847 96 set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
kaf24@8847 97 set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
kaf24@8847 98
keir@16940 99 /* Performance Counters Interrupt */
keir@16940 100 set_intr_gate(PMU_APIC_VECTOR, pmu_apic_interrupt);
keir@16940 101
keir@18948 102 /* CMCI Correctable Machine Check Interrupt */
keir@18948 103 set_intr_gate(CMCI_APIC_VECTOR, cmci_interrupt);
keir@18948 104
keir@18948 105 /* thermal monitor LVT interrupt, for P4 and latest Intel CPU*/
keir@18948 106 #ifdef CONFIG_X86_MCE_THERMAL
kaf24@8847 107 set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
kaf24@8847 108 #endif
kaf24@8847 109 }
kaf24@8847 110
kaf24@1452 111 /* Using APIC to generate smp_local_timer_interrupt? */
kaf24@1452 112 int using_apic_timer = 0;
kaf24@1452 113
kaf24@1452 114 static int enabled_via_apicbase;
kaf24@1452 115
kfraser@11541 116 void enable_NMI_through_LVT0 (void * dummy)
kfraser@11541 117 {
kfraser@11541 118 unsigned int v, ver;
kfraser@11541 119
kfraser@11541 120 ver = apic_read(APIC_LVR);
kfraser@11541 121 ver = GET_APIC_VERSION(ver);
kfraser@11541 122 v = APIC_DM_NMI; /* unmask and set to NMI */
kfraser@11541 123 if (!APIC_INTEGRATED(ver)) /* 82489DX */
kfraser@11541 124 v |= APIC_LVT_LEVEL_TRIGGER;
kfraser@11541 125 apic_write_around(APIC_LVT0, v);
kfraser@11541 126 }
kfraser@11541 127
kaf24@4804 128 int get_physical_broadcast(void)
kaf24@4804 129 {
kfraser@11541 130 if (modern_apic())
kaf24@4804 131 return 0xff;
kaf24@4804 132 else
kaf24@4804 133 return 0xf;
kaf24@4804 134 }
kaf24@4804 135
kaf24@1452 136 int get_maxlvt(void)
kaf24@1452 137 {
kaf24@1452 138 unsigned int v, ver, maxlvt;
kaf24@1452 139
kaf24@1452 140 v = apic_read(APIC_LVR);
kaf24@1452 141 ver = GET_APIC_VERSION(v);
kaf24@1452 142 /* 82489DXs do not report # of LVT entries. */
kaf24@1452 143 maxlvt = APIC_INTEGRATED(ver) ? GET_APIC_MAXLVT(v) : 2;
kaf24@1452 144 return maxlvt;
kaf24@1452 145 }
kaf24@1452 146
kaf24@1452 147 void clear_local_APIC(void)
kaf24@1452 148 {
kaf24@1452 149 int maxlvt;
kaf24@1452 150 unsigned long v;
kaf24@1452 151
kaf24@1452 152 maxlvt = get_maxlvt();
kaf24@1452 153
kaf24@1452 154 /*
kaf24@1452 155 * Masking an LVT entry on a P6 can trigger a local APIC error
kaf24@1452 156 * if the vector is zero. Mask LVTERR first to prevent this.
kaf24@1452 157 */
kaf24@1452 158 if (maxlvt >= 3) {
kaf24@1452 159 v = ERROR_APIC_VECTOR; /* any non-zero vector will do */
kaf24@1452 160 apic_write_around(APIC_LVTERR, v | APIC_LVT_MASKED);
kaf24@1452 161 }
kaf24@1452 162 /*
kaf24@1452 163 * Careful: we have to set masks only first to deassert
kaf24@1452 164 * any level-triggered sources.
kaf24@1452 165 */
kaf24@1452 166 v = apic_read(APIC_LVTT);
kaf24@1452 167 apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED);
kaf24@1452 168 v = apic_read(APIC_LVT0);
kaf24@1452 169 apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED);
kaf24@1452 170 v = apic_read(APIC_LVT1);
kaf24@1452 171 apic_write_around(APIC_LVT1, v | APIC_LVT_MASKED);
kaf24@1452 172 if (maxlvt >= 4) {
kaf24@1452 173 v = apic_read(APIC_LVTPC);
kaf24@1452 174 apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED);
kaf24@1452 175 }
kaf24@1452 176
kaf24@5211 177 /* lets not touch this if we didn't frob it */
keir@18948 178 #ifdef CONFIG_X86_MCE_THERMAL
kaf24@5211 179 if (maxlvt >= 5) {
kaf24@5211 180 v = apic_read(APIC_LVTTHMR);
kaf24@5211 181 apic_write_around(APIC_LVTTHMR, v | APIC_LVT_MASKED);
kaf24@5211 182 }
kaf24@5211 183 #endif
keir@18948 184
keir@18948 185 if (maxlvt >= 6) {
keir@18948 186 v = apic_read(APIC_CMCI);
keir@18948 187 apic_write_around(APIC_CMCI, v | APIC_LVT_MASKED);
keir@18948 188 }
kaf24@1452 189 /*
kaf24@1452 190 * Clean APIC state for other OSs:
kaf24@1452 191 */
kaf24@1452 192 apic_write_around(APIC_LVTT, APIC_LVT_MASKED);
kaf24@1452 193 apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
kaf24@1452 194 apic_write_around(APIC_LVT1, APIC_LVT_MASKED);
kaf24@1452 195 if (maxlvt >= 3)
kaf24@1452 196 apic_write_around(APIC_LVTERR, APIC_LVT_MASKED);
kaf24@1452 197 if (maxlvt >= 4)
kaf24@1452 198 apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
iap10@4548 199
keir@18948 200 #ifdef CONFIG_X86_MCE_THERMAL
kaf24@5211 201 if (maxlvt >= 5)
kaf24@5211 202 apic_write_around(APIC_LVTTHMR, APIC_LVT_MASKED);
kaf24@5211 203 #endif
keir@18948 204 if (maxlvt >= 6)
keir@18948 205 apic_write_around(APIC_CMCI, APIC_LVT_MASKED);
keir@18948 206
kaf24@1452 207 v = GET_APIC_VERSION(apic_read(APIC_LVR));
kfraser@11204 208 if (APIC_INTEGRATED(v)) { /* !82489DX */
iap10@4548 209 if (maxlvt > 3) /* Due to Pentium errata 3AP and 11AP. */
kaf24@1452 210 apic_write(APIC_ESR, 0);
kaf24@1452 211 apic_read(APIC_ESR);
kaf24@1452 212 }
kaf24@1452 213 }
kaf24@1452 214
kaf24@1452 215 void __init connect_bsp_APIC(void)
kaf24@1452 216 {
kaf24@1452 217 if (pic_mode) {
kaf24@1452 218 /*
kaf24@1452 219 * Do not trust the local APIC being empty at bootup.
kaf24@1452 220 */
kaf24@1452 221 clear_local_APIC();
kaf24@1452 222 /*
kaf24@1452 223 * PIC mode, enable APIC mode in the IMCR, i.e.
kaf24@1452 224 * connect BSP's local APIC to INT and NMI lines.
kaf24@1452 225 */
kaf24@4888 226 apic_printk(APIC_VERBOSE, "leaving PIC mode, "
kaf24@4888 227 "enabling APIC mode.\n");
kaf24@1452 228 outb(0x70, 0x22);
kaf24@1452 229 outb(0x01, 0x23);
kaf24@1452 230 }
kaf24@5211 231 enable_apic_mode();
kaf24@1452 232 }
kaf24@1452 233
kaf24@8847 234 void disconnect_bsp_APIC(int virt_wire_setup)
kaf24@1452 235 {
kaf24@1452 236 if (pic_mode) {
kaf24@1452 237 /*
kaf24@1452 238 * Put the board back into PIC mode (has an effect
kaf24@1452 239 * only on certain older boards). Note that APIC
kaf24@1452 240 * interrupts, including IPIs, won't work beyond
kaf24@1452 241 * this point! The only exception are INIT IPIs.
kaf24@1452 242 */
kaf24@4888 243 apic_printk(APIC_VERBOSE, "disabling APIC mode, "
kaf24@4888 244 "entering PIC mode.\n");
kaf24@1452 245 outb(0x70, 0x22);
kaf24@1452 246 outb(0x00, 0x23);
kaf24@1452 247 }
kaf24@8847 248 else {
kaf24@8847 249 /* Go back to Virtual Wire compatibility mode */
kaf24@8847 250 unsigned long value;
kaf24@8847 251
kaf24@8847 252 /* For the spurious interrupt use vector F, and enable it */
kaf24@8847 253 value = apic_read(APIC_SPIV);
kaf24@8847 254 value &= ~APIC_VECTOR_MASK;
kaf24@8847 255 value |= APIC_SPIV_APIC_ENABLED;
kaf24@8847 256 value |= 0xf;
kaf24@8847 257 apic_write_around(APIC_SPIV, value);
kaf24@8847 258
kaf24@8847 259 if (!virt_wire_setup) {
kaf24@8847 260 /* For LVT0 make it edge triggered, active high, external and enabled */
kaf24@8847 261 value = apic_read(APIC_LVT0);
kaf24@8847 262 value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
kaf24@8847 263 APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
kaf24@8847 264 APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED );
kaf24@8847 265 value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
kaf24@8847 266 value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
kaf24@8847 267 apic_write_around(APIC_LVT0, value);
kaf24@8847 268 }
kaf24@8847 269 else {
kaf24@8847 270 /* Disable LVT0 */
kaf24@8847 271 apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
kaf24@8847 272 }
kaf24@8847 273
kaf24@8847 274 /* For LVT1 make it edge triggered, active high, nmi and enabled */
kaf24@8847 275 value = apic_read(APIC_LVT1);
kaf24@8847 276 value &= ~(
kaf24@8847 277 APIC_MODE_MASK | APIC_SEND_PENDING |
kaf24@8847 278 APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
kaf24@8847 279 APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
kaf24@8847 280 value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
kaf24@8847 281 value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
kaf24@8847 282 apic_write_around(APIC_LVT1, value);
kaf24@8847 283 }
kaf24@1452 284 }
kaf24@1452 285
kaf24@1452 286 void disable_local_APIC(void)
kaf24@1452 287 {
kaf24@1452 288 unsigned long value;
kaf24@1452 289
kaf24@1452 290 clear_local_APIC();
kaf24@1452 291
kaf24@1452 292 /*
kaf24@1452 293 * Disable APIC (implies clearing of registers
kaf24@1452 294 * for 82489DX!).
kaf24@1452 295 */
kaf24@1452 296 value = apic_read(APIC_SPIV);
kaf24@1452 297 value &= ~APIC_SPIV_APIC_ENABLED;
kaf24@1452 298 apic_write_around(APIC_SPIV, value);
kaf24@1452 299
kaf24@1452 300 if (enabled_via_apicbase) {
kaf24@1452 301 unsigned int l, h;
kaf24@1452 302 rdmsr(MSR_IA32_APICBASE, l, h);
kaf24@1452 303 l &= ~MSR_IA32_APICBASE_ENABLE;
kaf24@1452 304 wrmsr(MSR_IA32_APICBASE, l, h);
kaf24@1452 305 }
kaf24@1452 306 }
kaf24@1452 307
kaf24@1452 308 /*
kaf24@1452 309 * This is to verify that we're looking at a real local APIC.
kaf24@1452 310 * Check these against your board if the CPUs aren't getting
kaf24@1452 311 * started for no apparent reason.
kaf24@1452 312 */
kaf24@1452 313 int __init verify_local_APIC(void)
kaf24@1452 314 {
kaf24@1452 315 unsigned int reg0, reg1;
kaf24@1452 316
kaf24@1452 317 /*
kaf24@1452 318 * The version register is read-only in a real APIC.
kaf24@1452 319 */
kaf24@1452 320 reg0 = apic_read(APIC_LVR);
kaf24@4888 321 apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg0);
keir@17552 322
keir@17552 323 /* We don't try writing LVR in x2APIC mode since that incurs #GP. */
keir@17552 324 if ( !x2apic_enabled )
keir@17552 325 apic_write(APIC_LVR, reg0 ^ APIC_LVR_MASK);
kaf24@1452 326 reg1 = apic_read(APIC_LVR);
kaf24@4888 327 apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg1);
kaf24@1452 328
kaf24@1452 329 /*
kaf24@1452 330 * The two version reads above should print the same
kaf24@1452 331 * numbers. If the second one is different, then we
kaf24@1452 332 * poke at a non-APIC.
kaf24@1452 333 */
kaf24@1452 334 if (reg1 != reg0)
kaf24@1452 335 return 0;
kaf24@1452 336
kaf24@1452 337 /*
kaf24@1452 338 * Check if the version looks reasonably.
kaf24@1452 339 */
kaf24@1452 340 reg1 = GET_APIC_VERSION(reg0);
kaf24@1452 341 if (reg1 == 0x00 || reg1 == 0xff)
kaf24@1452 342 return 0;
kaf24@1452 343 reg1 = get_maxlvt();
kaf24@1452 344 if (reg1 < 0x02 || reg1 == 0xff)
kaf24@1452 345 return 0;
kaf24@1452 346
kaf24@1452 347 /*
kaf24@1452 348 * The ID register is read/write in a real APIC.
kaf24@1452 349 */
kaf24@1452 350 reg0 = apic_read(APIC_ID);
kaf24@4888 351 apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0);
kaf24@1452 352
kaf24@1452 353 /*
kaf24@1452 354 * The next two are just to see if we have sane values.
kaf24@1452 355 * They're only really relevant if we're in Virtual Wire
kaf24@1452 356 * compatibility mode, but most boxes are anymore.
kaf24@1452 357 */
kaf24@1452 358 reg0 = apic_read(APIC_LVT0);
kaf24@4888 359 apic_printk(APIC_DEBUG, "Getting LVT0: %x\n", reg0);
kaf24@1452 360 reg1 = apic_read(APIC_LVT1);
kaf24@4888 361 apic_printk(APIC_DEBUG, "Getting LVT1: %x\n", reg1);
kaf24@1452 362
kaf24@1452 363 return 1;
kaf24@1452 364 }
kaf24@1452 365
kaf24@1452 366 void __init sync_Arb_IDs(void)
kaf24@1452 367 {
kfraser@11541 368 /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1
kfraser@11541 369 And not needed on AMD */
kfraser@11541 370 if (modern_apic())
iap10@4548 371 return;
kaf24@1452 372 /*
kaf24@1452 373 * Wait for idle.
kaf24@1452 374 */
kaf24@1452 375 apic_wait_icr_idle();
kaf24@1452 376
kaf24@4888 377 apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n");
kaf24@1452 378 apic_write_around(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG
kaf24@1452 379 | APIC_DM_INIT);
kaf24@1452 380 }
kaf24@1452 381
kaf24@1452 382 extern void __error_in_apic_c (void);
kaf24@1452 383
kaf24@4888 384 /*
kaf24@4888 385 * An initial setup of the virtual wire mode.
kaf24@4888 386 */
kaf24@1452 387 void __init init_bsp_APIC(void)
kaf24@1452 388 {
kaf24@4620 389 unsigned long value, ver;
kaf24@4620 390
kaf24@4620 391 /*
kaf24@4888 392 * Don't do the setup now if we have a SMP BIOS as the
kaf24@4888 393 * through-I/O-APIC virtual wire mode might be active.
kaf24@4620 394 */
kaf24@4620 395 if (smp_found_config || !cpu_has_apic)
kaf24@4620 396 return;
kaf24@4620 397
kaf24@4620 398 value = apic_read(APIC_LVR);
kaf24@4620 399 ver = GET_APIC_VERSION(value);
kaf24@4620 400
kaf24@4620 401 /*
kaf24@4620 402 * Do not trust the local APIC being empty at bootup.
kaf24@4620 403 */
kaf24@4620 404 clear_local_APIC();
kaf24@4620 405
kaf24@4620 406 /*
kaf24@4620 407 * Enable APIC.
kaf24@4620 408 */
kaf24@4620 409 value = apic_read(APIC_SPIV);
kaf24@4620 410 value &= ~APIC_VECTOR_MASK;
kaf24@4620 411 value |= APIC_SPIV_APIC_ENABLED;
kaf24@4620 412
kaf24@4620 413 /* This bit is reserved on P4/Xeon and should be cleared */
kaf24@4620 414 if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 15))
kaf24@4620 415 value &= ~APIC_SPIV_FOCUS_DISABLED;
kaf24@4620 416 else
kaf24@4620 417 value |= APIC_SPIV_FOCUS_DISABLED;
kaf24@4620 418 value |= SPURIOUS_APIC_VECTOR;
kaf24@4620 419 apic_write_around(APIC_SPIV, value);
kaf24@4620 420
kaf24@4620 421 /*
kaf24@4620 422 * Set up the virtual wire mode.
kaf24@4620 423 */
kaf24@4620 424 apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
kaf24@4620 425 value = APIC_DM_NMI;
kaf24@4620 426 if (!APIC_INTEGRATED(ver)) /* 82489DX */
kaf24@4620 427 value |= APIC_LVT_LEVEL_TRIGGER;
kaf24@4620 428 apic_write_around(APIC_LVT1, value);
kaf24@1452 429 }
kaf24@1452 430
kaf24@8847 431 void __devinit setup_local_APIC(void)
kaf24@1452 432 {
iap10@4548 433 unsigned long oldvalue, value, ver, maxlvt;
kfraser@11541 434 int i, j;
iap10@4548 435
iap10@4548 436 /* Pound the ESR really hard over the head with a big hammer - mbligh */
iap10@4548 437 if (esr_disable) {
iap10@4548 438 apic_write(APIC_ESR, 0);
iap10@4548 439 apic_write(APIC_ESR, 0);
iap10@4548 440 apic_write(APIC_ESR, 0);
iap10@4548 441 apic_write(APIC_ESR, 0);
iap10@4548 442 }
kaf24@1452 443
kaf24@1452 444 value = apic_read(APIC_LVR);
kaf24@1452 445 ver = GET_APIC_VERSION(value);
kaf24@1452 446
kaf24@1452 447 if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f)
kaf24@1452 448 __error_in_apic_c();
kaf24@1452 449
iap10@4548 450 /*
iap10@4548 451 * Double-check whether this APIC is really registered.
iap10@4548 452 */
iap10@4548 453 if (!apic_id_registered())
kaf24@1452 454 BUG();
kaf24@1452 455
kaf24@1452 456 /*
kaf24@1452 457 * Intel recommends to set DFR, LDR and TPR before enabling
kaf24@1452 458 * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
kaf24@1452 459 * document number 292116). So here it goes...
kaf24@1452 460 */
iap10@4548 461 init_apic_ldr();
kaf24@1452 462
kaf24@1452 463 /*
kaf24@1452 464 * Set Task Priority to 'accept all'. We never change this
kaf24@1452 465 * later on.
kaf24@1452 466 */
kaf24@1452 467 value = apic_read(APIC_TASKPRI);
kaf24@1452 468 value &= ~APIC_TPRI_MASK;
kaf24@1452 469 apic_write_around(APIC_TASKPRI, value);
kaf24@1452 470
kaf24@1452 471 /*
kfraser@11541 472 * After a crash, we no longer service the interrupts and a pending
kfraser@11541 473 * interrupt from previous kernel might still have ISR bit set.
kfraser@11541 474 *
kfraser@11541 475 * Most probably by now CPU has serviced that pending interrupt and
kfraser@11541 476 * it might not have done the ack_APIC_irq() because it thought,
kfraser@11541 477 * interrupt came from i8259 as ExtInt. LAPIC did not get EOI so it
kfraser@11541 478 * does not clear the ISR bit and cpu thinks it has already serivced
kfraser@11541 479 * the interrupt. Hence a vector might get locked. It was noticed
kfraser@11541 480 * for timer irq (vector 0x31). Issue an extra EOI to clear ISR.
kfraser@11541 481 */
kfraser@11541 482 for (i = APIC_ISR_NR - 1; i >= 0; i--) {
kfraser@11541 483 value = apic_read(APIC_ISR + i*0x10);
kfraser@11541 484 for (j = 31; j >= 0; j--) {
kfraser@11541 485 if (value & (1<<j))
kfraser@11541 486 ack_APIC_irq();
kfraser@11541 487 }
kfraser@11541 488 }
kfraser@11541 489
kfraser@11541 490 /*
kaf24@1452 491 * Now that we are all set up, enable the APIC
kaf24@1452 492 */
kaf24@1452 493 value = apic_read(APIC_SPIV);
kaf24@1452 494 value &= ~APIC_VECTOR_MASK;
kaf24@1452 495 /*
kaf24@1452 496 * Enable APIC
kaf24@1452 497 */
kaf24@1452 498 value |= APIC_SPIV_APIC_ENABLED;
kaf24@1452 499
iap10@4548 500 /*
iap10@4548 501 * Some unknown Intel IO/APIC (or APIC) errata is biting us with
iap10@4548 502 * certain networking cards. If high frequency interrupts are
iap10@4548 503 * happening on a particular IOAPIC pin, plus the IOAPIC routing
iap10@4548 504 * entry is masked/unmasked at a high rate as well then sooner or
iap10@4548 505 * later IOAPIC line gets 'stuck', no more interrupts are received
iap10@4548 506 * from the device. If focus CPU is disabled then the hang goes
iap10@4548 507 * away, oh well :-(
iap10@4548 508 *
iap10@4548 509 * [ This bug can be reproduced easily with a level-triggered
iap10@4548 510 * PCI Ne2000 networking cards and PII/PIII processors, dual
iap10@4548 511 * BX chipset. ]
iap10@4548 512 */
iap10@4548 513 /*
iap10@4548 514 * Actually disabling the focus CPU check just makes the hang less
iap10@4548 515 * frequent as it makes the interrupt distributon model be more
iap10@4548 516 * like LRU than MRU (the short-term load is more even across CPUs).
iap10@4548 517 * See also the comment in end_level_ioapic_irq(). --macro
iap10@4548 518 */
iap10@4548 519 #if 1
kaf24@1452 520 /* Enable focus processor (bit==0) */
kaf24@1452 521 value &= ~APIC_SPIV_FOCUS_DISABLED;
iap10@4548 522 #else
iap10@4548 523 /* Disable focus processor (bit==1) */
iap10@4548 524 value |= APIC_SPIV_FOCUS_DISABLED;
iap10@4548 525 #endif
iap10@4548 526 /*
iap10@4548 527 * Set spurious IRQ vector
iap10@4548 528 */
kaf24@1452 529 value |= SPURIOUS_APIC_VECTOR;
kaf24@1452 530 apic_write_around(APIC_SPIV, value);
kaf24@1452 531
kaf24@1452 532 /*
kaf24@1452 533 * Set up LVT0, LVT1:
kaf24@1452 534 *
kaf24@1452 535 * set up through-local-APIC on the BP's LINT0. This is not
kaf24@1452 536 * strictly necessery in pure symmetric-IO mode, but sometimes
kaf24@1452 537 * we delegate interrupts to the 8259A.
kaf24@1452 538 */
kaf24@1452 539 /*
kaf24@1452 540 * TODO: set up through-local-APIC from through-I/O-APIC? --macro
kaf24@1452 541 */
kaf24@1452 542 value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
iap10@4548 543 if (!smp_processor_id() && (pic_mode || !value)) {
kaf24@1452 544 value = APIC_DM_EXTINT;
kaf24@4888 545 apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n",
kaf24@4888 546 smp_processor_id());
kaf24@1452 547 } else {
kaf24@1452 548 value = APIC_DM_EXTINT | APIC_LVT_MASKED;
kaf24@4888 549 apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n",
kaf24@4888 550 smp_processor_id());
kaf24@1452 551 }
kaf24@1452 552 apic_write_around(APIC_LVT0, value);
kaf24@1452 553
kaf24@1452 554 /*
kaf24@1452 555 * only the BP should see the LINT1 NMI signal, obviously.
kaf24@1452 556 */
kaf24@1452 557 if (!smp_processor_id())
kaf24@1452 558 value = APIC_DM_NMI;
kaf24@1452 559 else
kaf24@1452 560 value = APIC_DM_NMI | APIC_LVT_MASKED;
kaf24@1452 561 if (!APIC_INTEGRATED(ver)) /* 82489DX */
kaf24@1452 562 value |= APIC_LVT_LEVEL_TRIGGER;
kaf24@1452 563 apic_write_around(APIC_LVT1, value);
kaf24@1452 564
iap10@4548 565 if (APIC_INTEGRATED(ver) && !esr_disable) { /* !82489DX */
kaf24@1452 566 maxlvt = get_maxlvt();
kaf24@1452 567 if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
kaf24@1452 568 apic_write(APIC_ESR, 0);
iap10@4548 569 oldvalue = apic_read(APIC_ESR);
kaf24@1452 570
iap10@4548 571 value = ERROR_APIC_VECTOR; // enables sending errors
kaf24@1452 572 apic_write_around(APIC_LVTERR, value);
iap10@4548 573 /*
iap10@4548 574 * spec says clear errors after enabling vector.
iap10@4548 575 */
kaf24@1452 576 if (maxlvt > 3)
kaf24@1452 577 apic_write(APIC_ESR, 0);
kaf24@1452 578 value = apic_read(APIC_ESR);
iap10@4548 579 if (value != oldvalue)
kaf24@4888 580 apic_printk(APIC_VERBOSE, "ESR value before enabling "
kaf24@4888 581 "vector: 0x%08lx after: 0x%08lx\n",
kaf24@4888 582 oldvalue, value);
kaf24@1452 583 } else {
iap10@4548 584 if (esr_disable)
iap10@4548 585 /*
iap10@4548 586 * Something untraceble is creating bad interrupts on
iap10@4548 587 * secondary quads ... for the moment, just leave the
iap10@4548 588 * ESR disabled - we can't do anything useful with the
iap10@4548 589 * errors anyway - mbligh
iap10@4548 590 */
iap10@4548 591 printk("Leaving ESR disabled.\n");
kaf24@4888 592 else
kaf24@4888 593 printk("No ESR for 82489DX.\n");
kaf24@1452 594 }
kaf24@1452 595
kaf24@8594 596 if (nmi_watchdog == NMI_LOCAL_APIC)
kaf24@8594 597 setup_apic_nmi_watchdog();
kaf24@8847 598 apic_pm_activate();
kaf24@1452 599 }
kaf24@1452 600
kfraser@15314 601 static struct {
kfraser@15314 602 int active;
kfraser@15314 603 /* r/w apic fields */
kfraser@15314 604 unsigned int apic_id;
kfraser@15314 605 unsigned int apic_taskpri;
kfraser@15314 606 unsigned int apic_ldr;
kfraser@15314 607 unsigned int apic_dfr;
kfraser@15314 608 unsigned int apic_spiv;
kfraser@15314 609 unsigned int apic_lvtt;
kfraser@15314 610 unsigned int apic_lvtpc;
keir@18948 611 unsigned int apic_lvtcmci;
kfraser@15314 612 unsigned int apic_lvt0;
kfraser@15314 613 unsigned int apic_lvt1;
kfraser@15314 614 unsigned int apic_lvterr;
kfraser@15314 615 unsigned int apic_tmict;
kfraser@15314 616 unsigned int apic_tdcr;
kfraser@15314 617 unsigned int apic_thmr;
kfraser@15314 618 } apic_pm_state;
kfraser@15314 619
kfraser@15314 620 int lapic_suspend(void)
kfraser@15314 621 {
kfraser@15314 622 unsigned long flags;
keir@18948 623 int maxlvt = get_maxlvt();
kfraser@15314 624 if (!apic_pm_state.active)
kfraser@15314 625 return 0;
kfraser@15314 626
kfraser@15314 627 apic_pm_state.apic_id = apic_read(APIC_ID);
kfraser@15314 628 apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI);
kfraser@15314 629 apic_pm_state.apic_ldr = apic_read(APIC_LDR);
keir@17552 630 if ( !x2apic_enabled )
keir@17552 631 apic_pm_state.apic_dfr = apic_read(APIC_DFR);
kfraser@15314 632 apic_pm_state.apic_spiv = apic_read(APIC_SPIV);
kfraser@15314 633 apic_pm_state.apic_lvtt = apic_read(APIC_LVTT);
kfraser@15314 634 apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC);
keir@18948 635
keir@18948 636 if (maxlvt >= 6) {
keir@18948 637 apic_pm_state.apic_lvtcmci = apic_read(APIC_CMCI);
keir@18948 638 }
keir@18948 639
kfraser@15314 640 apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0);
kfraser@15314 641 apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1);
kfraser@15314 642 apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR);
kfraser@15314 643 apic_pm_state.apic_tmict = apic_read(APIC_TMICT);
kfraser@15314 644 apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);
kfraser@15314 645 apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
kfraser@15314 646
kfraser@15314 647 local_irq_save(flags);
kfraser@15314 648 disable_local_APIC();
kfraser@15314 649 local_irq_restore(flags);
kfraser@15314 650 return 0;
kfraser@15314 651 }
kfraser@15314 652
kfraser@15314 653 int lapic_resume(void)
kfraser@15314 654 {
kfraser@15314 655 unsigned int l, h;
kfraser@15314 656 unsigned long flags;
keir@18948 657 int maxlvt = get_maxlvt();
kfraser@15314 658
kfraser@15314 659 if (!apic_pm_state.active)
kfraser@15314 660 return 0;
kfraser@15314 661
kfraser@15314 662 local_irq_save(flags);
kfraser@15314 663
kfraser@15314 664 /*
kfraser@15314 665 * Make sure the APICBASE points to the right address
kfraser@15314 666 *
kfraser@15314 667 * FIXME! This will be wrong if we ever support suspend on
kfraser@15314 668 * SMP! We'll need to do this as part of the CPU restore!
kfraser@15314 669 */
keir@17552 670 if ( !x2apic_enabled )
keir@17552 671 {
keir@17552 672 rdmsr(MSR_IA32_APICBASE, l, h);
keir@17552 673 l &= ~MSR_IA32_APICBASE_BASE;
keir@17552 674 l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
keir@17552 675 wrmsr(MSR_IA32_APICBASE, l, h);
keir@17552 676 }
keir@17552 677 else
keir@17552 678 enable_x2apic();
kfraser@15314 679
kfraser@15314 680 apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
kfraser@15314 681 apic_write(APIC_ID, apic_pm_state.apic_id);
keir@17552 682 if ( !x2apic_enabled )
keir@17552 683 apic_write(APIC_DFR, apic_pm_state.apic_dfr);
kfraser@15314 684 apic_write(APIC_LDR, apic_pm_state.apic_ldr);
kfraser@15314 685 apic_write(APIC_TASKPRI, apic_pm_state.apic_taskpri);
kfraser@15314 686 apic_write(APIC_SPIV, apic_pm_state.apic_spiv);
kfraser@15314 687 apic_write(APIC_LVT0, apic_pm_state.apic_lvt0);
kfraser@15314 688 apic_write(APIC_LVT1, apic_pm_state.apic_lvt1);
kfraser@15314 689 apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);
keir@18948 690
keir@18948 691 if (maxlvt >= 6) {
keir@18948 692 apic_write(APIC_CMCI, apic_pm_state.apic_lvtcmci);
keir@18948 693 }
keir@18948 694
kfraser@15314 695 apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
kfraser@15314 696 apic_write(APIC_LVTT, apic_pm_state.apic_lvtt);
kfraser@15314 697 apic_write(APIC_TDCR, apic_pm_state.apic_tdcr);
kfraser@15314 698 apic_write(APIC_TMICT, apic_pm_state.apic_tmict);
kfraser@15314 699 apic_write(APIC_ESR, 0);
kfraser@15314 700 apic_read(APIC_ESR);
kfraser@15314 701 apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr);
kfraser@15314 702 apic_write(APIC_ESR, 0);
kfraser@15314 703 apic_read(APIC_ESR);
kfraser@15314 704 local_irq_restore(flags);
kfraser@15314 705 return 0;
kfraser@15314 706 }
kfraser@15314 707
kfraser@15314 708
kfraser@11541 709 /*
kfraser@11541 710 * If Linux enabled the LAPIC against the BIOS default
kfraser@11541 711 * disable it down before re-entering the BIOS on shutdown.
kfraser@11541 712 * Otherwise the BIOS may get confused and not power-off.
kfraser@11541 713 * Additionally clear all LVT entries before disable_local_APIC
kfraser@11541 714 * for the case where Linux didn't enable the LAPIC.
kfraser@11541 715 */
kfraser@11541 716 void lapic_shutdown(void)
kfraser@11541 717 {
kfraser@11541 718 unsigned long flags;
kfraser@11541 719
kfraser@11541 720 if (!cpu_has_apic)
kfraser@11541 721 return;
kfraser@11541 722
kfraser@11541 723 local_irq_save(flags);
kfraser@11541 724 clear_local_APIC();
kfraser@11541 725
kfraser@11541 726 if (enabled_via_apicbase)
kfraser@11541 727 disable_local_APIC();
kfraser@11541 728
kfraser@11541 729 local_irq_restore(flags);
kfraser@11541 730 }
kfraser@11541 731
kfraser@15314 732 static void apic_pm_activate(void)
kfraser@15314 733 {
kfraser@15314 734 apic_pm_state.active = 1;
kfraser@15314 735 }
kaf24@8847 736
kaf24@1452 737 /*
kaf24@1452 738 * Detect and enable local APICs on non-SMP boards.
kaf24@1452 739 * Original code written by Keir Fraser.
kaf24@1452 740 */
kaf24@1452 741
kaf24@5211 742 static void __init lapic_disable(char *str)
kaf24@5211 743 {
kaf24@5211 744 enable_local_apic = -1;
keir@19039 745 setup_clear_cpu_cap(X86_FEATURE_APIC);
kaf24@5211 746 }
kaf24@5211 747 custom_param("nolapic", lapic_disable);
kaf24@5211 748
kaf24@5211 749 static void __init lapic_enable(char *str)
kaf24@5211 750 {
kaf24@5211 751 enable_local_apic = 1;
kaf24@5211 752 }
kaf24@5211 753 custom_param("lapic", lapic_enable);
kaf24@5211 754
kaf24@4888 755 static void __init apic_set_verbosity(char *str)
kaf24@4888 756 {
kaf24@4888 757 if (strcmp("debug", str) == 0)
kaf24@4888 758 apic_verbosity = APIC_DEBUG;
kaf24@4888 759 else if (strcmp("verbose", str) == 0)
kaf24@4888 760 apic_verbosity = APIC_VERBOSE;
kaf24@5211 761 else
kaf24@5211 762 printk(KERN_WARNING "APIC Verbosity level %s not recognised"
kaf24@5211 763 " use apic_verbosity=verbose or apic_verbosity=debug", str);
kaf24@4888 764 }
kaf24@5211 765 custom_param("apic_verbosity", apic_set_verbosity);
kaf24@4888 766
kaf24@1452 767 static int __init detect_init_APIC (void)
kaf24@1452 768 {
kaf24@1452 769 u32 h, l, features;
kaf24@1452 770
kaf24@5211 771 /* Disabled by kernel option? */
kaf24@5211 772 if (enable_local_apic < 0)
kaf24@5211 773 return -1;
kaf24@5211 774
kaf24@1452 775 switch (boot_cpu_data.x86_vendor) {
kaf24@1452 776 case X86_VENDOR_AMD:
iap10@4548 777 if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||
keir@16093 778 (boot_cpu_data.x86 >= 15 && boot_cpu_data.x86 <= 17))
kaf24@1452 779 break;
kaf24@1452 780 goto no_apic;
kaf24@1452 781 case X86_VENDOR_INTEL:
iap10@4548 782 if (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15 ||
kaf24@1452 783 (boot_cpu_data.x86 == 5 && cpu_has_apic))
kaf24@1452 784 break;
kaf24@1452 785 goto no_apic;
kaf24@1452 786 default:
kaf24@1452 787 goto no_apic;
kaf24@1452 788 }
kaf24@1452 789
kaf24@1452 790 if (!cpu_has_apic) {
kaf24@1452 791 /*
kaf24@5211 792 * Over-ride BIOS and try to enable the local
kaf24@5211 793 * APIC only if "lapic" specified.
kaf24@5211 794 */
kaf24@5211 795 if (enable_local_apic <= 0) {
kaf24@5211 796 printk("Local APIC disabled by BIOS -- "
kaf24@5211 797 "you can enable it with \"lapic\"\n");
kaf24@5211 798 return -1;
kaf24@5211 799 }
kaf24@5211 800 /*
kaf24@1452 801 * Some BIOSes disable the local APIC in the
kaf24@1452 802 * APIC_BASE MSR. This can only be done in
iap10@4548 803 * software for Intel P6 or later and AMD K7
iap10@4548 804 * (Model > 1) or later.
kaf24@1452 805 */
kaf24@1452 806 rdmsr(MSR_IA32_APICBASE, l, h);
kaf24@1452 807 if (!(l & MSR_IA32_APICBASE_ENABLE)) {
kaf24@1452 808 printk("Local APIC disabled by BIOS -- reenabling.\n");
kaf24@1452 809 l &= ~MSR_IA32_APICBASE_BASE;
kaf24@1452 810 l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
kaf24@1452 811 wrmsr(MSR_IA32_APICBASE, l, h);
kaf24@1452 812 enabled_via_apicbase = 1;
kaf24@1452 813 }
kaf24@1452 814 }
kaf24@4888 815 /*
kaf24@4888 816 * The APIC feature bit should now be enabled
kaf24@4888 817 * in `cpuid'
kaf24@4888 818 */
kaf24@1452 819 features = cpuid_edx(1);
kaf24@1452 820 if (!(features & (1 << X86_FEATURE_APIC))) {
kaf24@1452 821 printk("Could not enable APIC!\n");
kaf24@1452 822 return -1;
kaf24@1452 823 }
kaf24@4619 824
iap10@4548 825 set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
kaf24@1452 826 mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
kaf24@1452 827
kaf24@1452 828 /* The BIOS may have set up the APIC at some other address */
kaf24@1452 829 rdmsr(MSR_IA32_APICBASE, l, h);
kaf24@1452 830 if (l & MSR_IA32_APICBASE_ENABLE)
kaf24@1452 831 mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
kaf24@1452 832
kaf24@4619 833 if (nmi_watchdog != NMI_NONE)
kaf24@4619 834 nmi_watchdog = NMI_LOCAL_APIC;
kaf24@1452 835
kaf24@1452 836 printk("Found and enabled local APIC!\n");
iap10@4548 837
kaf24@8847 838 apic_pm_activate();
kaf24@8847 839
kaf24@1452 840 return 0;
kaf24@1452 841
iap10@4548 842 no_apic:
kaf24@1452 843 printk("No local APIC present or hardware disabled\n");
kaf24@1452 844 return -1;
kaf24@1452 845 }
kaf24@1452 846
keir@17552 847 void enable_x2apic(void)
keir@17552 848 {
keir@17552 849 u32 lo, hi;
keir@17552 850
keir@17552 851 rdmsr(MSR_IA32_APICBASE, lo, hi);
keir@17552 852 if ( !(lo & MSR_IA32_APICBASE_EXTD) )
keir@17552 853 {
keir@17552 854 lo |= MSR_IA32_APICBASE_ENABLE | MSR_IA32_APICBASE_EXTD;
keir@17552 855 wrmsr(MSR_IA32_APICBASE, lo, 0);
keir@17552 856 printk("x2APIC mode enabled.\n");
keir@17552 857 }
keir@17552 858 else
keir@17552 859 printk("x2APIC mode enabled by BIOS.\n");
keir@17552 860
keir@17552 861 x2apic_enabled = 1;
keir@17552 862 }
keir@17552 863
kaf24@1452 864 void __init init_apic_mappings(void)
kaf24@1452 865 {
iap10@4548 866 unsigned long apic_phys;
kaf24@1452 867
keir@17552 868 if ( x2apic_enabled )
keir@17552 869 goto __next;
kaf24@1452 870 /*
iap10@4548 871 * If no local APIC can be found then set up a fake all
iap10@4548 872 * zeroes page to simulate the local APIC and another
iap10@4548 873 * one for the IO-APIC.
kaf24@1452 874 */
kaf24@9582 875 if (!smp_found_config && detect_init_APIC()) {
kaf24@5398 876 apic_phys = __pa(alloc_xenheap_page());
kfraser@15405 877 clear_page(__va(apic_phys));
kaf24@9582 878 } else
kaf24@1452 879 apic_phys = mp_lapic_addr;
kaf24@1452 880
kaf24@1452 881 set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
kaf24@4888 882 apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n", APIC_BASE,
kaf24@4888 883 apic_phys);
kaf24@1452 884
keir@17552 885 __next:
kaf24@1452 886 /*
kaf24@1452 887 * Fetch the APIC ID of the BSP in case we have a
kaf24@1452 888 * default configuration (or the MP table is broken).
kaf24@1452 889 */
kaf24@1452 890 if (boot_cpu_physical_apicid == -1U)
keir@17552 891 boot_cpu_physical_apicid = get_apic_id();
kaf24@1452 892
kaf24@1452 893 #ifdef CONFIG_X86_IO_APIC
kaf24@1452 894 {
iap10@4548 895 unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
kaf24@1452 896 int i;
kaf24@1452 897
kaf24@1452 898 for (i = 0; i < nr_ioapics; i++) {
iap10@4548 899 if (smp_found_config) {
kaf24@1452 900 ioapic_phys = mp_ioapics[i].mpc_apicaddr;
iap10@4548 901 if (!ioapic_phys) {
iap10@4548 902 printk(KERN_ERR
iap10@4548 903 "WARNING: bogus zero IO-APIC "
iap10@4548 904 "address found in MPTABLE, "
iap10@4548 905 "disabling IO/APIC support!\n");
iap10@4548 906 smp_found_config = 0;
iap10@4548 907 skip_ioapic_setup = 1;
iap10@4548 908 goto fake_ioapic_page;
iap10@4548 909 }
iap10@4548 910 } else {
iap10@4548 911 fake_ioapic_page:
kaf24@5398 912 ioapic_phys = __pa(alloc_xenheap_page());
kfraser@15405 913 clear_page(__va(ioapic_phys));
iap10@4548 914 }
kaf24@1452 915 set_fixmap_nocache(idx, ioapic_phys);
kaf24@4888 916 apic_printk(APIC_VERBOSE, "mapped IOAPIC to %08lx (%08lx)\n",
kaf24@4888 917 __fix_to_virt(idx), ioapic_phys);
kaf24@1452 918 idx++;
kaf24@1452 919 }
kaf24@1452 920 }
kaf24@1452 921 #endif
kaf24@1452 922 }
kaf24@1452 923
kaf24@1452 924 /*****************************************************************************
kaf24@1452 925 * APIC calibration
kaf24@1452 926 *
kaf24@1452 927 * The APIC is programmed in bus cycles.
kaf24@1452 928 * Timeout values should specified in real time units.
kaf24@1452 929 * The "cheapest" time source is the cyclecounter.
kaf24@1452 930 *
kaf24@1452 931 * Thus, we need a mappings from: bus cycles <- cycle counter <- system time
kaf24@1452 932 *
kaf24@1452 933 * The calibration is currently a bit shoddy since it requires the external
kaf24@1452 934 * timer chip to generate periodic timer interupts.
kaf24@1452 935 *****************************************************************************/
kaf24@1452 936
kaf24@1452 937 /* used for system time scaling */
kaf24@1672 938 static unsigned long bus_freq; /* KAF: pointer-size avoids compile warns. */
kaf24@1672 939 static u32 bus_cycle; /* length of one bus cycle in pico-seconds */
kaf24@1672 940 static u32 bus_scale; /* scaling factor convert ns to bus cycles */
kaf24@1452 941
kaf24@1452 942 /*
kaf24@1452 943 * The timer chip is already set up at HZ interrupts per second here,
kaf24@1452 944 * but we do not accept timer interrupts yet. We only allow the BP
kaf24@1452 945 * to calibrate.
kaf24@1452 946 */
kaf24@1452 947 static unsigned int __init get_8254_timer_count(void)
kaf24@1452 948 {
kaf24@1452 949 /*extern spinlock_t i8253_lock;*/
kaf24@1452 950 /*unsigned long flags;*/
iap10@4548 951
kaf24@1452 952 unsigned int count;
iap10@4548 953
kaf24@1452 954 /*spin_lock_irqsave(&i8253_lock, flags);*/
iap10@4548 955
iap10@4548 956 outb_p(0x00, PIT_MODE);
iap10@4548 957 count = inb_p(PIT_CH0);
iap10@4548 958 count |= inb_p(PIT_CH0) << 8;
iap10@4548 959
kaf24@1452 960 /*spin_unlock_irqrestore(&i8253_lock, flags);*/
iap10@4548 961
kaf24@1452 962 return count;
kaf24@1452 963 }
kaf24@1452 964
iap10@4548 965 /* next tick in 8254 can be caught by catching timer wraparound */
iap10@4548 966 static void __init wait_8254_wraparound(void)
kaf24@1452 967 {
kaf24@4888 968 unsigned int curr_count, prev_count;
kaf24@4888 969
kaf24@1452 970 curr_count = get_8254_timer_count();
kaf24@1452 971 do {
kaf24@1452 972 prev_count = curr_count;
kaf24@1452 973 curr_count = get_8254_timer_count();
iap10@4548 974
kaf24@4888 975 /* workaround for broken Mercury/Neptune */
kaf24@4888 976 if (prev_count >= curr_count + 0x100)
kaf24@4888 977 curr_count = get_8254_timer_count();
kaf24@4888 978
kaf24@4888 979 } while (prev_count >= curr_count);
kaf24@1452 980 }
kaf24@1452 981
kaf24@1452 982 /*
iap10@4548 983 * Default initialization for 8254 timers. If we use other timers like HPET,
iap10@4548 984 * we override this later
iap10@4548 985 */
kaf24@4888 986 void (*wait_timer_tick)(void) __initdata = wait_8254_wraparound;
iap10@4548 987
iap10@4548 988 /*
kaf24@1452 989 * This function sets up the local APIC timer, with a timeout of
kaf24@1452 990 * 'clocks' APIC bus clock. During calibration we actually call
kaf24@4888 991 * this function twice on the boot CPU, once with a bogus timeout
kaf24@4888 992 * value, second time for real. The other (noncalibrating) CPUs
kaf24@4888 993 * call this function only once, with the real, calibrated value.
kaf24@1452 994 *
kaf24@1452 995 * We do reads before writes even if unnecessary, to get around the
kaf24@1452 996 * P5 APIC double write bug.
kaf24@1452 997 */
iap10@4548 998
kaf24@1452 999 #define APIC_DIVISOR 1
iap10@4548 1000
kaf24@5146 1001 void __setup_APIC_LVTT(unsigned int clocks)
kaf24@1452 1002 {
iap10@4548 1003 unsigned int lvtt_value, tmp_value, ver;
iap10@4548 1004
iap10@4548 1005 ver = GET_APIC_VERSION(apic_read(APIC_LVR));
kaf24@4619 1006 /* NB. Xen uses local APIC timer in one-shot mode. */
kaf24@4619 1007 lvtt_value = /*APIC_LVT_TIMER_PERIODIC |*/ LOCAL_TIMER_VECTOR;
iap10@4548 1008 if (!APIC_INTEGRATED(ver))
iap10@4548 1009 lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
iap10@4548 1010 apic_write_around(APIC_LVTT, lvtt_value);
iap10@4548 1011
kaf24@1452 1012 tmp_value = apic_read(APIC_TDCR);
kaf24@1452 1013 apic_write_around(APIC_TDCR, (tmp_value | APIC_TDR_DIV_1));
iap10@4548 1014
kaf24@1452 1015 apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
kaf24@1452 1016 }
kaf24@1452 1017
kfraser@15586 1018 static void __devinit setup_APIC_timer(unsigned int clocks)
kaf24@1452 1019 {
kaf24@1452 1020 unsigned long flags;
kaf24@5146 1021 local_irq_save(flags);
kaf24@5146 1022 __setup_APIC_LVTT(clocks);
kaf24@5146 1023 local_irq_restore(flags);
kaf24@1452 1024 }
kaf24@1452 1025
kaf24@1452 1026 /*
kaf24@5146 1027 * In this function we calibrate APIC bus clocks to the external
kaf24@5146 1028 * timer. Unfortunately we cannot use jiffies and the timer irq
kaf24@5146 1029 * to calibrate, since some later bootup code depends on getting
kaf24@5146 1030 * the first irq? Ugh.
kaf24@1452 1031 *
kaf24@5146 1032 * We want to do the calibration only once since we
kaf24@5146 1033 * want to have local timer irqs syncron. CPUs connected
kaf24@5146 1034 * by the same APIC bus have the very same bus frequency.
kaf24@5146 1035 * And we want to have irqs off anyways, no accidental
kaf24@5146 1036 * APIC irq that way.
kaf24@1452 1037 */
kaf24@1452 1038
kaf24@1452 1039 int __init calibrate_APIC_clock(void)
kaf24@1452 1040 {
kaf24@1452 1041 unsigned long long t1 = 0, t2 = 0;
kaf24@1452 1042 long tt1, tt2;
kaf24@1452 1043 long result;
kaf24@1452 1044 int i;
kaf24@1452 1045 const int LOOPS = HZ/10;
kaf24@1452 1046
kaf24@4888 1047 apic_printk(APIC_VERBOSE, "calibrating APIC timer ...\n");
kaf24@1452 1048
iap10@4548 1049 /*
iap10@4548 1050 * Put whatever arbitrary (but long enough) timeout
kaf24@1452 1051 * value into the APIC clock, we just want to get the
iap10@4548 1052 * counter running for calibration.
iap10@4548 1053 */
kaf24@1452 1054 __setup_APIC_LVTT(1000000000);
kaf24@1452 1055
iap10@4548 1056 /*
iap10@4548 1057 * The timer chip counts down to zero. Let's wait
kaf24@1452 1058 * for a wraparound to start exact measurement:
iap10@4548 1059 * (the current tick might have been already half done)
iap10@4548 1060 */
iap10@4548 1061 wait_timer_tick();
iap10@4548 1062
iap10@4548 1063 /*
iap10@4548 1064 * We wrapped around just now. Let's start:
iap10@4548 1065 */
iap10@4548 1066 if (cpu_has_tsc)
kaf24@4619 1067 rdtscll(t1);
kaf24@1452 1068 tt1 = apic_read(APIC_TMCCT);
kaf24@1452 1069
iap10@4548 1070 /*
iap10@4548 1071 * Let's wait LOOPS wraprounds:
iap10@4548 1072 */
kaf24@1452 1073 for (i = 0; i < LOOPS; i++)
iap10@4548 1074 wait_timer_tick();
kaf24@1452 1075
kaf24@1452 1076 tt2 = apic_read(APIC_TMCCT);
iap10@4548 1077 if (cpu_has_tsc)
kaf24@4619 1078 rdtscll(t2);
kaf24@1452 1079
iap10@4548 1080 /*
iap10@4548 1081 * The APIC bus clock counter is 32 bits only, it
kaf24@1452 1082 * might have overflown, but note that we use signed
kaf24@1452 1083 * longs, thus no extra care needed.
kaf24@4888 1084 *
kaf24@4888 1085 * underflown to be exact, as the timer counts down ;)
iap10@4548 1086 */
iap10@4548 1087
kaf24@1452 1088 result = (tt1-tt2)*APIC_DIVISOR/LOOPS;
kaf24@1452 1089
iap10@4548 1090 if (cpu_has_tsc)
kaf24@4888 1091 apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
kaf24@4888 1092 "%ld.%04ld MHz.\n",
kaf24@4888 1093 ((long)(t2-t1)/LOOPS)/(1000000/HZ),
kaf24@4888 1094 ((long)(t2-t1)/LOOPS)%(1000000/HZ));
kaf24@1452 1095
kaf24@4888 1096 apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
kfraser@11204 1097 "%ld.%04ld MHz.\n",
kfraser@11204 1098 result/(1000000/HZ),
kfraser@11204 1099 result%(1000000/HZ));
kaf24@1452 1100
kaf24@1452 1101 /* set up multipliers for accurate timer code */
kaf24@1452 1102 bus_freq = result*HZ;
kaf24@1452 1103 bus_cycle = (u32) (1000000000000LL/bus_freq); /* in pico seconds */
kaf24@1452 1104 bus_scale = (1000*262144)/bus_cycle;
kaf24@1452 1105
kaf24@4888 1106 apic_printk(APIC_VERBOSE, "..... bus_scale = 0x%08X\n", bus_scale);
kaf24@1452 1107 /* reset APIC to zero timeout value */
kaf24@1452 1108 __setup_APIC_LVTT(0);
iap10@4548 1109
kaf24@1452 1110 return result;
kaf24@1452 1111 }
kaf24@1452 1112
kaf24@9184 1113 u32 get_apic_bus_cycle(void)
kaf24@7546 1114 {
kaf24@9184 1115 return bus_cycle;
kaf24@7546 1116 }
kaf24@5146 1117
kaf24@5146 1118 static unsigned int calibration_result;
kaf24@5146 1119
kaf24@5146 1120 void __init setup_boot_APIC_clock(void)
kaf24@1452 1121 {
kaf24@8847 1122 unsigned long flags;
kaf24@5146 1123 apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n");
kaf24@1452 1124 using_apic_timer = 1;
kaf24@5146 1125
kaf24@8847 1126 local_irq_save(flags);
kaf24@8847 1127
kaf24@5146 1128 calibration_result = calibrate_APIC_clock();
kaf24@5146 1129 /*
kaf24@5146 1130 * Now set up the timer for real.
kaf24@5146 1131 */
kaf24@5146 1132 setup_APIC_timer(calibration_result);
kaf24@5146 1133
kaf24@8847 1134 local_irq_restore(flags);
kaf24@5146 1135 }
kaf24@5146 1136
kaf24@8847 1137 void __devinit setup_secondary_APIC_clock(void)
kaf24@5146 1138 {
kaf24@5146 1139 setup_APIC_timer(calibration_result);
kaf24@5146 1140 }
kaf24@5146 1141
kaf24@8847 1142 void disable_APIC_timer(void)
kaf24@5146 1143 {
kaf24@5146 1144 if (using_apic_timer) {
kaf24@5146 1145 unsigned long v;
kaf24@5146 1146
kaf24@5146 1147 v = apic_read(APIC_LVTT);
kaf24@5146 1148 apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED);
kaf24@5146 1149 }
kaf24@5146 1150 }
kaf24@5146 1151
kaf24@5146 1152 void enable_APIC_timer(void)
kaf24@5146 1153 {
kaf24@5146 1154 if (using_apic_timer) {
kaf24@5146 1155 unsigned long v;
kaf24@5146 1156
kaf24@5146 1157 v = apic_read(APIC_LVTT);
kaf24@5146 1158 apic_write_around(APIC_LVTT, v & ~APIC_LVT_MASKED);
kaf24@5146 1159 }
kaf24@1452 1160 }
kaf24@1452 1161
kaf24@1452 1162 #undef APIC_DIVISOR
kaf24@1452 1163
kaf24@1452 1164 /*
kaf24@1452 1165 * reprogram the APIC timer. Timeoutvalue is in ns from start of boot
kaf24@1452 1166 * returns 1 on success
kaf24@1452 1167 * returns 0 if the timeout value is too small or in the past.
kaf24@1452 1168 */
kaf24@8586 1169 int reprogram_timer(s_time_t timeout)
kaf24@1452 1170 {
kaf24@1452 1171 s_time_t now;
kaf24@1452 1172 s_time_t expire;
kaf24@1452 1173 u64 apic_tmict;
kaf24@1452 1174
kaf24@1452 1175 /*
kfraser@14340 1176 * If we don't have local APIC then we just poll the timer list off the
kfraser@14340 1177 * PIT interrupt.
kfraser@14340 1178 */
kfraser@14340 1179 if ( !cpu_has_apic )
kfraser@14340 1180 return 1;
kfraser@14340 1181
kfraser@14340 1182 /*
kaf24@1452 1183 * We use this value because we don't trust zero (we think it may just
kaf24@1452 1184 * cause an immediate interrupt). At least this is guaranteed to hold it
kaf24@1452 1185 * off for ages (esp. since the clock ticks on bus clock, not cpu clock!).
kaf24@1452 1186 */
kaf24@1452 1187 if ( timeout == 0 )
kaf24@1452 1188 {
kaf24@1452 1189 apic_tmict = 0xffffffff;
kaf24@1452 1190 goto reprogram;
kaf24@1452 1191 }
kaf24@1452 1192
kaf24@1452 1193 now = NOW();
kaf24@1452 1194 expire = timeout - now; /* value from now */
kaf24@1452 1195
kaf24@1452 1196 if ( expire <= 0 )
kaf24@1452 1197 {
kaf24@1452 1198 Dprintk("APICT[%02d] Timeout in the past 0x%08X%08X > 0x%08X%08X\n",
kaf24@1452 1199 smp_processor_id(), (u32)(now>>32),
kaf24@1452 1200 (u32)now, (u32)(timeout>>32),(u32)timeout);
kaf24@1452 1201 return 0;
kaf24@1452 1202 }
kaf24@1452 1203
kaf24@1452 1204 /* conversion to bus units */
kaf24@1452 1205 apic_tmict = (((u64)bus_scale) * expire)>>18;
kaf24@1452 1206
kaf24@1452 1207 if ( apic_tmict >= 0xffffffff )
kaf24@1452 1208 {
kaf24@1452 1209 Dprintk("APICT[%02d] Timeout value too large\n", smp_processor_id());
kaf24@1452 1210 apic_tmict = 0xffffffff;
kaf24@1452 1211 }
kaf24@1452 1212
kaf24@1452 1213 if ( apic_tmict == 0 )
kaf24@1452 1214 {
kaf24@1452 1215 Dprintk("APICT[%02d] timeout value too small\n", smp_processor_id());
kaf24@1452 1216 return 0;
kaf24@1452 1217 }
kaf24@1452 1218
kaf24@1452 1219 reprogram:
kaf24@1452 1220 /* Program the timer. */
kaf24@1452 1221 apic_write(APIC_TMICT, (unsigned long)apic_tmict);
kaf24@1452 1222
kaf24@1452 1223 return 1;
kaf24@1452 1224 }
kaf24@1452 1225
kaf24@8846 1226 fastcall void smp_apic_timer_interrupt(struct cpu_user_regs * regs)
kaf24@1452 1227 {
kaf24@1452 1228 ack_APIC_irq();
kfraser@14595 1229 perfc_incr(apic_timer);
kaf24@8586 1230 raise_softirq(TIMER_SOFTIRQ);
kaf24@1452 1231 }
kaf24@1452 1232
kaf24@1452 1233 /*
kaf24@1452 1234 * This interrupt should _never_ happen with our APIC/SMP architecture
kaf24@1452 1235 */
kaf24@8846 1236 fastcall void smp_spurious_interrupt(struct cpu_user_regs *regs)
kaf24@1452 1237 {
kaf24@1452 1238 unsigned long v;
kaf24@1452 1239
kaf24@8847 1240 irq_enter();
kaf24@1452 1241 /*
kaf24@1452 1242 * Check if this really is a spurious interrupt and ACK it
kaf24@1452 1243 * if it is a vectored one. Just in case...
kaf24@1452 1244 * Spurious interrupts should not be ACKed.
kaf24@1452 1245 */
kaf24@1452 1246 v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1));
kaf24@1452 1247 if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
kaf24@1452 1248 ack_APIC_irq();
kaf24@1452 1249
kaf24@1452 1250 /* see sw-dev-man vol 3, chapter 7.4.13.5 */
kaf24@5146 1251 printk(KERN_INFO "spurious APIC interrupt on CPU#%d, should never happen.\n",
kaf24@1452 1252 smp_processor_id());
kaf24@8847 1253 irq_exit();
kaf24@1452 1254 }
kaf24@1452 1255
kaf24@1452 1256 /*
kaf24@1452 1257 * This interrupt should never happen with our APIC/SMP architecture
kaf24@1452 1258 */
kaf24@1452 1259
kaf24@8846 1260 fastcall void smp_error_interrupt(struct cpu_user_regs *regs)
kaf24@1452 1261 {
kaf24@1452 1262 unsigned long v, v1;
kaf24@1452 1263
kaf24@8847 1264 irq_enter();
kaf24@1452 1265 /* First tickle the hardware, only then report what went on. -- REW */
kaf24@1452 1266 v = apic_read(APIC_ESR);
kaf24@1452 1267 apic_write(APIC_ESR, 0);
kaf24@1452 1268 v1 = apic_read(APIC_ESR);
kaf24@1452 1269 ack_APIC_irq();
kaf24@1452 1270 atomic_inc(&irq_err_count);
kaf24@1452 1271
kaf24@1452 1272 /* Here is what the APIC error bits mean:
kaf24@1452 1273 0: Send CS error
kaf24@1452 1274 1: Receive CS error
kaf24@1452 1275 2: Send accept error
kaf24@1452 1276 3: Receive accept error
kaf24@1452 1277 4: Reserved
kaf24@1452 1278 5: Send illegal vector
kaf24@1452 1279 6: Received illegal vector
kaf24@1452 1280 7: Illegal register address
kaf24@1452 1281 */
kaf24@5146 1282 printk (KERN_DEBUG "APIC error on CPU%d: %02lx(%02lx)\n",
kaf24@5146 1283 smp_processor_id(), v , v1);
kaf24@8847 1284 irq_exit();
kaf24@1452 1285 }
kaf24@1452 1286
kaf24@1452 1287 /*
keir@16940 1288 * This interrupt handles performance counters interrupt
keir@16940 1289 */
keir@16940 1290
keir@16940 1291 fastcall void smp_pmu_apic_interrupt(struct cpu_user_regs *regs)
keir@16940 1292 {
keir@16940 1293 ack_APIC_irq();
keir@16940 1294 hvm_do_pmu_interrupt(regs);
keir@16940 1295 }
keir@16940 1296
keir@16940 1297 /*
kaf24@1452 1298 * This initializes the IO-APIC and APIC hardware if this is
kaf24@1452 1299 * a UP kernel.
kaf24@1452 1300 */
kaf24@1452 1301 int __init APIC_init_uniprocessor (void)
kaf24@1452 1302 {
kaf24@5211 1303 if (enable_local_apic < 0)
kaf24@5211 1304 clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
kaf24@5211 1305
keir@19501 1306 if (!smp_found_config && !cpu_has_apic) {
keir@19501 1307 skip_ioapic_setup = 1;
kaf24@1452 1308 return -1;
keir@19501 1309 }
kaf24@1452 1310
kaf24@1452 1311 /*
kaf24@1452 1312 * Complain if the BIOS pretends there is one.
kaf24@1452 1313 */
iap10@4548 1314 if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
kaf24@4888 1315 printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
kaf24@1452 1316 boot_cpu_physical_apicid);
kfraser@11541 1317 clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
keir@19501 1318 skip_ioapic_setup = 1;
kaf24@1452 1319 return -1;
kaf24@1452 1320 }
kaf24@1452 1321
kaf24@1452 1322 verify_local_APIC();
kaf24@1452 1323
kaf24@1452 1324 connect_bsp_APIC();
kaf24@1452 1325
kfraser@11541 1326 /*
kfraser@11541 1327 * Hack: In case of kdump, after a crash, kernel might be booting
kfraser@11541 1328 * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid
kfraser@11541 1329 * might be zero if read from MP tables. Get it from LAPIC.
kfraser@11541 1330 */
kfraser@11541 1331 #ifdef CONFIG_CRASH_DUMP
keir@17552 1332 boot_cpu_physical_apicid = get_apic_id();
kfraser@11541 1333 #endif
kaf24@4804 1334 phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
kaf24@1452 1335
kaf24@1452 1336 setup_local_APIC();
kaf24@1452 1337
kaf24@5146 1338 if (nmi_watchdog == NMI_LOCAL_APIC)
kaf24@5146 1339 check_nmi_watchdog();
kaf24@1452 1340 #ifdef CONFIG_X86_IO_APIC
iap10@4548 1341 if (smp_found_config)
iap10@4548 1342 if (!skip_ioapic_setup && nr_ioapics)
kaf24@4619 1343 setup_IO_APIC();
iap10@4548 1344 #endif
kaf24@5146 1345 setup_boot_APIC_clock();
kaf24@1452 1346
kaf24@1452 1347 return 0;
kaf24@1452 1348 }