ia64/xen-unstable

annotate xen/arch/x86/apic.c @ 4548:8ce73ebd1311

bitkeeper revision 1.1308 (4260510bQdQyEJ4w-XdZSU5iSTB_Pg)

The attached patch apic.patch updates xen/arch/x86/apic.c so that it is based on linux 2.6.10 code. A few changes made to linux required reworking functions in other files as well so I held off on those changes. For example, setup_APIC_timer(void *) changed to setup_APIC_timer(unsigned int). The change has no real bearing on the Xen code -- it's just a question of how close to linux one wants to be. However, that change goes with a change to smp_call_function which would affect quite a few other files/functions so I left it as is. Most of the other changes are trivial.
xen/ac_timer.h was included but not needed by apic.c so I removed it from the list of #includes.

The new apic.c includes two new files: asm/io_ports.h and asm/mach_apic.h. Patches to create those files are included as well.
author iap10@freefall.cl.cam.ac.uk
date Fri Apr 15 23:40:59 2005 +0000 (2005-04-15)
parents a01199a95070
children 67c40314aa6e
rev   line source
kaf24@1452 1 /*
iap10@4548 2 * based on linux-2.6.10/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.
kaf24@1452 13 * Maciej W. Rozycki : Various updates and fixes.
kaf24@1452 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>
iap10@4548 37 #include <asm/mach_apic.h>
iap10@4548 38 #include <asm/io_ports.h>
kaf24@1452 39
kaf24@1452 40 /* Using APIC to generate smp_local_timer_interrupt? */
kaf24@1452 41 int using_apic_timer = 0;
kaf24@1452 42
kaf24@1452 43 static int enabled_via_apicbase;
kaf24@1452 44
kaf24@1452 45 int get_maxlvt(void)
kaf24@1452 46 {
kaf24@1452 47 unsigned int v, ver, maxlvt;
kaf24@1452 48
kaf24@1452 49 v = apic_read(APIC_LVR);
kaf24@1452 50 ver = GET_APIC_VERSION(v);
kaf24@1452 51 /* 82489DXs do not report # of LVT entries. */
kaf24@1452 52 maxlvt = APIC_INTEGRATED(ver) ? GET_APIC_MAXLVT(v) : 2;
kaf24@1452 53 return maxlvt;
kaf24@1452 54 }
kaf24@1452 55
kaf24@1452 56 void clear_local_APIC(void)
kaf24@1452 57 {
kaf24@1452 58 int maxlvt;
kaf24@1452 59 unsigned long v;
kaf24@1452 60
kaf24@1452 61 maxlvt = get_maxlvt();
kaf24@1452 62
kaf24@1452 63 /*
kaf24@1452 64 * Masking an LVT entry on a P6 can trigger a local APIC error
kaf24@1452 65 * if the vector is zero. Mask LVTERR first to prevent this.
kaf24@1452 66 */
kaf24@1452 67 if (maxlvt >= 3) {
kaf24@1452 68 v = ERROR_APIC_VECTOR; /* any non-zero vector will do */
kaf24@1452 69 apic_write_around(APIC_LVTERR, v | APIC_LVT_MASKED);
kaf24@1452 70 }
kaf24@1452 71 /*
kaf24@1452 72 * Careful: we have to set masks only first to deassert
kaf24@1452 73 * any level-triggered sources.
kaf24@1452 74 */
kaf24@1452 75 v = apic_read(APIC_LVTT);
kaf24@1452 76 apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED);
kaf24@1452 77 v = apic_read(APIC_LVT0);
kaf24@1452 78 apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED);
kaf24@1452 79 v = apic_read(APIC_LVT1);
kaf24@1452 80 apic_write_around(APIC_LVT1, v | APIC_LVT_MASKED);
kaf24@1452 81 if (maxlvt >= 4) {
kaf24@1452 82 v = apic_read(APIC_LVTPC);
kaf24@1452 83 apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED);
kaf24@1452 84 }
kaf24@1452 85
iap10@4548 86 #if 0
iap10@4548 87 /* lets not touch this if we didn't frob it */
iap10@4548 88 #ifdef CONFIG_X86_MCE_P4THERMAL
iap10@4548 89 if (maxlvt >= 5) {
iap10@4548 90 v = apic_read(APIC_LVTTHMR);
iap10@4548 91 apic_write_around(APIC_LVTTHMR, v | APIC_LVT_MASKED);
iap10@4548 92 }
iap10@4548 93 #endif
iap10@4548 94 #endif
iap10@4548 95
kaf24@1452 96 /*
kaf24@1452 97 * Clean APIC state for other OSs:
kaf24@1452 98 */
kaf24@1452 99 apic_write_around(APIC_LVTT, APIC_LVT_MASKED);
kaf24@1452 100 apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
kaf24@1452 101 apic_write_around(APIC_LVT1, APIC_LVT_MASKED);
kaf24@1452 102 if (maxlvt >= 3)
kaf24@1452 103 apic_write_around(APIC_LVTERR, APIC_LVT_MASKED);
kaf24@1452 104 if (maxlvt >= 4)
kaf24@1452 105 apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
iap10@4548 106
iap10@4548 107 #if 0
iap10@4548 108 #ifdef CONFIG_X86_MCE_P4THERMAL
iap10@4548 109 if (maxlvt >= 5)
iap10@4548 110 apic_write_around(APIC_LVTTHMR, APIC_LVT_MASKED);
iap10@4548 111 #endif
iap10@4548 112 #endif
iap10@4548 113
kaf24@1452 114 v = GET_APIC_VERSION(apic_read(APIC_LVR));
kaf24@1452 115 if (APIC_INTEGRATED(v)) { /* !82489DX */
iap10@4548 116 if (maxlvt > 3) /* Due to Pentium errata 3AP and 11AP. */
kaf24@1452 117 apic_write(APIC_ESR, 0);
kaf24@1452 118 apic_read(APIC_ESR);
kaf24@1452 119 }
kaf24@1452 120 }
kaf24@1452 121
kaf24@1452 122 void __init connect_bsp_APIC(void)
kaf24@1452 123 {
kaf24@1452 124 if (pic_mode) {
kaf24@1452 125 /*
kaf24@1452 126 * Do not trust the local APIC being empty at bootup.
kaf24@1452 127 */
kaf24@1452 128 clear_local_APIC();
kaf24@1452 129 /*
kaf24@1452 130 * PIC mode, enable APIC mode in the IMCR, i.e.
kaf24@1452 131 * connect BSP's local APIC to INT and NMI lines.
kaf24@1452 132 */
kaf24@1452 133 printk("leaving PIC mode, enabling APIC mode.\n");
kaf24@1452 134 outb(0x70, 0x22);
kaf24@1452 135 outb(0x01, 0x23);
kaf24@1452 136 }
iap10@4548 137 #if 0
iap10@4548 138 enable_apic_mode();
iap10@4548 139 #endif
kaf24@1452 140 }
kaf24@1452 141
kaf24@1452 142 void disconnect_bsp_APIC(void)
kaf24@1452 143 {
kaf24@1452 144 if (pic_mode) {
kaf24@1452 145 /*
kaf24@1452 146 * Put the board back into PIC mode (has an effect
kaf24@1452 147 * only on certain older boards). Note that APIC
kaf24@1452 148 * interrupts, including IPIs, won't work beyond
kaf24@1452 149 * this point! The only exception are INIT IPIs.
kaf24@1452 150 */
kaf24@1452 151 printk("disabling APIC mode, entering PIC mode.\n");
kaf24@1452 152 outb(0x70, 0x22);
kaf24@1452 153 outb(0x00, 0x23);
kaf24@1452 154 }
kaf24@1452 155 }
kaf24@1452 156
kaf24@1452 157 void disable_local_APIC(void)
kaf24@1452 158 {
kaf24@1452 159 unsigned long value;
kaf24@1452 160
kaf24@1452 161 clear_local_APIC();
kaf24@1452 162
kaf24@1452 163 /*
kaf24@1452 164 * Disable APIC (implies clearing of registers
kaf24@1452 165 * for 82489DX!).
kaf24@1452 166 */
kaf24@1452 167 value = apic_read(APIC_SPIV);
kaf24@1452 168 value &= ~APIC_SPIV_APIC_ENABLED;
kaf24@1452 169 apic_write_around(APIC_SPIV, value);
kaf24@1452 170
kaf24@1452 171 if (enabled_via_apicbase) {
kaf24@1452 172 unsigned int l, h;
kaf24@1452 173 rdmsr(MSR_IA32_APICBASE, l, h);
kaf24@1452 174 l &= ~MSR_IA32_APICBASE_ENABLE;
kaf24@1452 175 wrmsr(MSR_IA32_APICBASE, l, h);
kaf24@1452 176 }
kaf24@1452 177 }
kaf24@1452 178
kaf24@1452 179 /*
kaf24@1452 180 * This is to verify that we're looking at a real local APIC.
kaf24@1452 181 * Check these against your board if the CPUs aren't getting
kaf24@1452 182 * started for no apparent reason.
kaf24@1452 183 */
kaf24@1452 184 int __init verify_local_APIC(void)
kaf24@1452 185 {
kaf24@1452 186 unsigned int reg0, reg1;
kaf24@1452 187
kaf24@1452 188 /*
kaf24@1452 189 * The version register is read-only in a real APIC.
kaf24@1452 190 */
kaf24@1452 191 reg0 = apic_read(APIC_LVR);
kaf24@1452 192 Dprintk("Getting VERSION: %x\n", reg0);
kaf24@1452 193 apic_write(APIC_LVR, reg0 ^ APIC_LVR_MASK);
kaf24@1452 194 reg1 = apic_read(APIC_LVR);
kaf24@1452 195 Dprintk("Getting VERSION: %x\n", reg1);
kaf24@1452 196
kaf24@1452 197 /*
kaf24@1452 198 * The two version reads above should print the same
kaf24@1452 199 * numbers. If the second one is different, then we
kaf24@1452 200 * poke at a non-APIC.
kaf24@1452 201 */
kaf24@1452 202 if (reg1 != reg0)
kaf24@1452 203 return 0;
kaf24@1452 204
kaf24@1452 205 /*
kaf24@1452 206 * Check if the version looks reasonably.
kaf24@1452 207 */
kaf24@1452 208 reg1 = GET_APIC_VERSION(reg0);
kaf24@1452 209 if (reg1 == 0x00 || reg1 == 0xff)
kaf24@1452 210 return 0;
kaf24@1452 211 reg1 = get_maxlvt();
kaf24@1452 212 if (reg1 < 0x02 || reg1 == 0xff)
kaf24@1452 213 return 0;
kaf24@1452 214
kaf24@1452 215 /*
kaf24@1452 216 * The ID register is read/write in a real APIC.
kaf24@1452 217 */
kaf24@1452 218 reg0 = apic_read(APIC_ID);
kaf24@1452 219 Dprintk("Getting ID: %x\n", reg0);
kaf24@1452 220
kaf24@1452 221 /*
kaf24@1452 222 * The next two are just to see if we have sane values.
kaf24@1452 223 * They're only really relevant if we're in Virtual Wire
kaf24@1452 224 * compatibility mode, but most boxes are anymore.
kaf24@1452 225 */
kaf24@1452 226 reg0 = apic_read(APIC_LVT0);
kaf24@1452 227 Dprintk("Getting LVT0: %x\n", reg0);
kaf24@1452 228 reg1 = apic_read(APIC_LVT1);
kaf24@1452 229 Dprintk("Getting LVT1: %x\n", reg1);
kaf24@1452 230
kaf24@1452 231 return 1;
kaf24@1452 232 }
kaf24@1452 233
kaf24@1452 234 void __init sync_Arb_IDs(void)
kaf24@1452 235 {
iap10@4548 236 /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */
iap10@4548 237 unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
iap10@4548 238 if (ver >= 0x14) /* P4 or higher */
iap10@4548 239 return;
kaf24@1452 240 /*
kaf24@1452 241 * Wait for idle.
kaf24@1452 242 */
kaf24@1452 243 apic_wait_icr_idle();
kaf24@1452 244
kaf24@1452 245 Dprintk("Synchronizing Arb IDs.\n");
kaf24@1452 246 apic_write_around(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG
kaf24@1452 247 | APIC_DM_INIT);
kaf24@1452 248 }
kaf24@1452 249
kaf24@1452 250 extern void __error_in_apic_c (void);
kaf24@1452 251
kaf24@1452 252 /*
kaf24@1452 253 * WAS: An initial setup of the virtual wire mode.
kaf24@1452 254 * NOW: We don't bother doing anything. All we need at this point
kaf24@1452 255 * is to receive timer ticks, so that 'jiffies' is incremented.
kaf24@1452 256 * If we're SMP, then we can assume BIOS did setup for us.
kaf24@1452 257 * If we're UP, then the APIC should be disabled (it is at reset).
kaf24@1452 258 * If we're UP and APIC is enabled, then BIOS is clever and has
kaf24@1452 259 * probably done initial interrupt routing for us.
kaf24@1452 260 */
kaf24@1452 261 void __init init_bsp_APIC(void)
kaf24@1452 262 {
kaf24@1452 263 }
kaf24@1452 264
kaf24@1452 265 void __init setup_local_APIC (void)
kaf24@1452 266 {
iap10@4548 267 unsigned long oldvalue, value, ver, maxlvt;
iap10@4548 268
iap10@4548 269 /* Pound the ESR really hard over the head with a big hammer - mbligh */
iap10@4548 270 if (esr_disable) {
iap10@4548 271 apic_write(APIC_ESR, 0);
iap10@4548 272 apic_write(APIC_ESR, 0);
iap10@4548 273 apic_write(APIC_ESR, 0);
iap10@4548 274 apic_write(APIC_ESR, 0);
iap10@4548 275 }
kaf24@1452 276
kaf24@1452 277 value = apic_read(APIC_LVR);
kaf24@1452 278 ver = GET_APIC_VERSION(value);
kaf24@1452 279
kaf24@1452 280 if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f)
kaf24@1452 281 __error_in_apic_c();
kaf24@1452 282
iap10@4548 283 /*
iap10@4548 284 * Double-check whether this APIC is really registered.
iap10@4548 285 */
iap10@4548 286 if (!apic_id_registered())
kaf24@1452 287 BUG();
kaf24@1452 288
kaf24@1452 289 /*
kaf24@1452 290 * Intel recommends to set DFR, LDR and TPR before enabling
kaf24@1452 291 * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
kaf24@1452 292 * document number 292116). So here it goes...
kaf24@1452 293 */
iap10@4548 294 init_apic_ldr();
kaf24@1452 295
kaf24@1452 296 /*
kaf24@1452 297 * Set Task Priority to 'accept all'. We never change this
kaf24@1452 298 * later on.
kaf24@1452 299 */
kaf24@1452 300 value = apic_read(APIC_TASKPRI);
kaf24@1452 301 value &= ~APIC_TPRI_MASK;
kaf24@1452 302 apic_write_around(APIC_TASKPRI, value);
kaf24@1452 303
kaf24@1452 304 /*
kaf24@1452 305 * Now that we are all set up, enable the APIC
kaf24@1452 306 */
kaf24@1452 307 value = apic_read(APIC_SPIV);
kaf24@1452 308 value &= ~APIC_VECTOR_MASK;
kaf24@1452 309 /*
kaf24@1452 310 * Enable APIC
kaf24@1452 311 */
kaf24@1452 312 value |= APIC_SPIV_APIC_ENABLED;
kaf24@1452 313
iap10@4548 314 /*
iap10@4548 315 * Some unknown Intel IO/APIC (or APIC) errata is biting us with
iap10@4548 316 * certain networking cards. If high frequency interrupts are
iap10@4548 317 * happening on a particular IOAPIC pin, plus the IOAPIC routing
iap10@4548 318 * entry is masked/unmasked at a high rate as well then sooner or
iap10@4548 319 * later IOAPIC line gets 'stuck', no more interrupts are received
iap10@4548 320 * from the device. If focus CPU is disabled then the hang goes
iap10@4548 321 * away, oh well :-(
iap10@4548 322 *
iap10@4548 323 * [ This bug can be reproduced easily with a level-triggered
iap10@4548 324 * PCI Ne2000 networking cards and PII/PIII processors, dual
iap10@4548 325 * BX chipset. ]
iap10@4548 326 */
iap10@4548 327 /*
iap10@4548 328 * Actually disabling the focus CPU check just makes the hang less
iap10@4548 329 * frequent as it makes the interrupt distributon model be more
iap10@4548 330 * like LRU than MRU (the short-term load is more even across CPUs).
iap10@4548 331 * See also the comment in end_level_ioapic_irq(). --macro
iap10@4548 332 */
iap10@4548 333 #if 1
kaf24@1452 334 /* Enable focus processor (bit==0) */
kaf24@1452 335 value &= ~APIC_SPIV_FOCUS_DISABLED;
iap10@4548 336 #else
iap10@4548 337 /* Disable focus processor (bit==1) */
iap10@4548 338 value |= APIC_SPIV_FOCUS_DISABLED;
iap10@4548 339 #endif
iap10@4548 340 /*
iap10@4548 341 * Set spurious IRQ vector
iap10@4548 342 */
kaf24@1452 343 value |= SPURIOUS_APIC_VECTOR;
kaf24@1452 344 apic_write_around(APIC_SPIV, value);
kaf24@1452 345
kaf24@1452 346 /*
kaf24@1452 347 * Set up LVT0, LVT1:
kaf24@1452 348 *
kaf24@1452 349 * set up through-local-APIC on the BP's LINT0. This is not
kaf24@1452 350 * strictly necessery in pure symmetric-IO mode, but sometimes
kaf24@1452 351 * we delegate interrupts to the 8259A.
kaf24@1452 352 */
kaf24@1452 353 /*
kaf24@1452 354 * TODO: set up through-local-APIC from through-I/O-APIC? --macro
kaf24@1452 355 */
kaf24@1452 356 value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
iap10@4548 357 if (!smp_processor_id() && (pic_mode || !value)) {
kaf24@1452 358 value = APIC_DM_EXTINT;
kaf24@1452 359 printk("enabled ExtINT on CPU#%d\n", smp_processor_id());
kaf24@1452 360 } else {
kaf24@1452 361 value = APIC_DM_EXTINT | APIC_LVT_MASKED;
kaf24@1452 362 printk("masked ExtINT on CPU#%d\n", smp_processor_id());
kaf24@1452 363 }
kaf24@1452 364 apic_write_around(APIC_LVT0, value);
kaf24@1452 365
kaf24@1452 366 /*
kaf24@1452 367 * only the BP should see the LINT1 NMI signal, obviously.
kaf24@1452 368 */
kaf24@1452 369 if (!smp_processor_id())
kaf24@1452 370 value = APIC_DM_NMI;
kaf24@1452 371 else
kaf24@1452 372 value = APIC_DM_NMI | APIC_LVT_MASKED;
kaf24@1452 373 if (!APIC_INTEGRATED(ver)) /* 82489DX */
kaf24@1452 374 value |= APIC_LVT_LEVEL_TRIGGER;
kaf24@1452 375 apic_write_around(APIC_LVT1, value);
kaf24@1452 376
iap10@4548 377 if (APIC_INTEGRATED(ver) && !esr_disable) { /* !82489DX */
kaf24@1452 378 maxlvt = get_maxlvt();
kaf24@1452 379 if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
kaf24@1452 380 apic_write(APIC_ESR, 0);
iap10@4548 381 oldvalue = apic_read(APIC_ESR);
kaf24@1452 382
iap10@4548 383 value = ERROR_APIC_VECTOR; // enables sending errors
kaf24@1452 384 apic_write_around(APIC_LVTERR, value);
iap10@4548 385 /*
iap10@4548 386 * spec says clear errors after enabling vector.
iap10@4548 387 */
kaf24@1452 388 if (maxlvt > 3)
kaf24@1452 389 apic_write(APIC_ESR, 0);
kaf24@1452 390 value = apic_read(APIC_ESR);
iap10@4548 391 if (value != oldvalue)
iap10@4548 392 printk("ESR value before enabling vector: 0x%08lx "
iap10@4548 393 "after: 0x%08lx\n", oldvalue, value);
kaf24@1452 394 } else {
iap10@4548 395 if (esr_disable)
iap10@4548 396 /*
iap10@4548 397 * Something untraceble is creating bad interrupts on
iap10@4548 398 * secondary quads ... for the moment, just leave the
iap10@4548 399 * ESR disabled - we can't do anything useful with the
iap10@4548 400 * errors anyway - mbligh
iap10@4548 401 */
iap10@4548 402 printk("Leaving ESR disabled.\n");
iap10@4548 403 else
kaf24@1452 404 printk("No ESR for 82489DX.\n");
kaf24@1452 405 }
kaf24@1452 406
iap10@4548 407 if (nmi_watchdog == NMI_LOCAL_APIC)
kaf24@1452 408 setup_apic_nmi_watchdog();
iap10@4548 409 #if 0
iap10@4548 410 apic_pm_activate();
iap10@4548 411 #endif
kaf24@1452 412 }
kaf24@1452 413
kaf24@1452 414 /*
kaf24@1452 415 * Detect and enable local APICs on non-SMP boards.
kaf24@1452 416 * Original code written by Keir Fraser.
kaf24@1452 417 */
kaf24@1452 418
kaf24@1452 419 static int __init detect_init_APIC (void)
kaf24@1452 420 {
kaf24@1452 421 u32 h, l, features;
kaf24@1452 422 extern void get_cpu_vendor(struct cpuinfo_x86*);
kaf24@1452 423
iap10@4548 424 #if 0
iap10@4548 425 /* Disabled by kernel option? */
iap10@4548 426 if (enable_local_apic < 0)
iap10@4548 427 return -1;
iap10@4548 428 #endif
iap10@4548 429
kaf24@1452 430 /* Workaround for us being called before identify_cpu(). */
kaf24@1452 431 get_cpu_vendor(&boot_cpu_data);
kaf24@1452 432
kaf24@1452 433 switch (boot_cpu_data.x86_vendor) {
kaf24@1452 434 case X86_VENDOR_AMD:
iap10@4548 435 if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||
iap10@4548 436 (boot_cpu_data.x86 == 15))
kaf24@1452 437 break;
kaf24@1452 438 goto no_apic;
kaf24@1452 439 case X86_VENDOR_INTEL:
iap10@4548 440 if (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15 ||
kaf24@1452 441 (boot_cpu_data.x86 == 5 && cpu_has_apic))
kaf24@1452 442 break;
kaf24@1452 443 goto no_apic;
kaf24@1452 444 default:
kaf24@1452 445 goto no_apic;
kaf24@1452 446 }
kaf24@1452 447
kaf24@1452 448 if (!cpu_has_apic) {
kaf24@1452 449 /*
iap10@4548 450 * Over-ride BIOS and try to enable the local
iap10@4548 451 * APIC only if "lapic" specified.
iap10@4548 452 */
iap10@4548 453 #if 0
iap10@4548 454 if (enable_local_apic <= 0) {
iap10@4548 455 printk("Local APIC disabled by BIOS -- "
iap10@4548 456 "you can enable it with \"lapic\"\n");
iap10@4548 457 return -1;
iap10@4548 458 }
iap10@4548 459 #endif
iap10@4548 460 /*
kaf24@1452 461 * Some BIOSes disable the local APIC in the
kaf24@1452 462 * APIC_BASE MSR. This can only be done in
iap10@4548 463 * software for Intel P6 or later and AMD K7
iap10@4548 464 * (Model > 1) or later.
kaf24@1452 465 */
kaf24@1452 466 rdmsr(MSR_IA32_APICBASE, l, h);
kaf24@1452 467 if (!(l & MSR_IA32_APICBASE_ENABLE)) {
kaf24@1452 468 printk("Local APIC disabled by BIOS -- reenabling.\n");
kaf24@1452 469 l &= ~MSR_IA32_APICBASE_BASE;
kaf24@1452 470 l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
kaf24@1452 471 wrmsr(MSR_IA32_APICBASE, l, h);
kaf24@1452 472 enabled_via_apicbase = 1;
kaf24@1452 473 }
kaf24@1452 474 }
iap10@4548 475 /*
iap10@4548 476 * The APIC feature bit should now be enabled
iap10@4548 477 * in `cpuid'
iap10@4548 478 */
kaf24@1452 479 features = cpuid_edx(1);
kaf24@1452 480 if (!(features & (1 << X86_FEATURE_APIC))) {
kaf24@1452 481 printk("Could not enable APIC!\n");
kaf24@1452 482 return -1;
kaf24@1452 483 }
iap10@4548 484 set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
kaf24@1452 485 mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
kaf24@1452 486
kaf24@1452 487 /* The BIOS may have set up the APIC at some other address */
kaf24@1452 488 rdmsr(MSR_IA32_APICBASE, l, h);
kaf24@1452 489 if (l & MSR_IA32_APICBASE_ENABLE)
kaf24@1452 490 mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
kaf24@1452 491
kaf24@1452 492 if (nmi_watchdog != NMI_NONE)
kaf24@1452 493 nmi_watchdog = NMI_LOCAL_APIC;
kaf24@1452 494
kaf24@1452 495 printk("Found and enabled local APIC!\n");
iap10@4548 496
iap10@4548 497 #if 0
iap10@4548 498 apic_pm_activate();
iap10@4548 499 #endif
iap10@4548 500
kaf24@1452 501 return 0;
kaf24@1452 502
iap10@4548 503 no_apic:
kaf24@1452 504 printk("No local APIC present or hardware disabled\n");
kaf24@1452 505 return -1;
kaf24@1452 506 }
kaf24@1452 507
kaf24@1452 508 void __init init_apic_mappings(void)
kaf24@1452 509 {
iap10@4548 510 unsigned long apic_phys;
kaf24@1452 511
kaf24@1452 512 /*
iap10@4548 513 * If no local APIC can be found then set up a fake all
iap10@4548 514 * zeroes page to simulate the local APIC and another
iap10@4548 515 * one for the IO-APIC.
kaf24@1452 516 */
kaf24@1452 517 if (!smp_found_config && detect_init_APIC()) {
kaf24@1920 518 apic_phys = alloc_xenheap_page();
kaf24@1452 519 apic_phys = __pa(apic_phys);
kaf24@1452 520 } else
kaf24@1452 521 apic_phys = mp_lapic_addr;
kaf24@1452 522
kaf24@1452 523 set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
kaf24@1452 524 Dprintk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys);
kaf24@1452 525
kaf24@1452 526 /*
kaf24@1452 527 * Fetch the APIC ID of the BSP in case we have a
kaf24@1452 528 * default configuration (or the MP table is broken).
kaf24@1452 529 */
kaf24@1452 530 if (boot_cpu_physical_apicid == -1U)
kaf24@1452 531 boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
kaf24@1452 532
kaf24@1452 533 #ifdef CONFIG_X86_IO_APIC
kaf24@1452 534 {
iap10@4548 535 unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
kaf24@1452 536 int i;
kaf24@1452 537
kaf24@1452 538 for (i = 0; i < nr_ioapics; i++) {
iap10@4548 539 if (smp_found_config) {
kaf24@1452 540 ioapic_phys = mp_ioapics[i].mpc_apicaddr;
iap10@4548 541 if (!ioapic_phys) {
iap10@4548 542 printk(KERN_ERR
iap10@4548 543 "WARNING: bogus zero IO-APIC "
iap10@4548 544 "address found in MPTABLE, "
iap10@4548 545 "disabling IO/APIC support!\n");
iap10@4548 546 smp_found_config = 0;
iap10@4548 547 skip_ioapic_setup = 1;
iap10@4548 548 goto fake_ioapic_page;
iap10@4548 549 }
iap10@4548 550 } else {
iap10@4548 551 fake_ioapic_page:
iap10@4548 552 ioapic_phys = alloc_xenheap_page();
iap10@4548 553 ioapic_phys = __pa(ioapic_phys);
iap10@4548 554 }
kaf24@1452 555 set_fixmap_nocache(idx, ioapic_phys);
kaf24@1452 556 Dprintk("mapped IOAPIC to %08lx (%08lx)\n",
kaf24@1508 557 fix_to_virt(idx), ioapic_phys);
kaf24@1452 558 idx++;
kaf24@1452 559 }
kaf24@1452 560 }
kaf24@1452 561 #endif
kaf24@1452 562 }
kaf24@1452 563
kaf24@1452 564 /*****************************************************************************
kaf24@1452 565 * APIC calibration
kaf24@1452 566 *
kaf24@1452 567 * The APIC is programmed in bus cycles.
kaf24@1452 568 * Timeout values should specified in real time units.
kaf24@1452 569 * The "cheapest" time source is the cyclecounter.
kaf24@1452 570 *
kaf24@1452 571 * Thus, we need a mappings from: bus cycles <- cycle counter <- system time
kaf24@1452 572 *
kaf24@1452 573 * The calibration is currently a bit shoddy since it requires the external
kaf24@1452 574 * timer chip to generate periodic timer interupts.
kaf24@1452 575 *****************************************************************************/
kaf24@1452 576
kaf24@1452 577 /* used for system time scaling */
kaf24@1672 578 static unsigned long bus_freq; /* KAF: pointer-size avoids compile warns. */
kaf24@1672 579 static u32 bus_cycle; /* length of one bus cycle in pico-seconds */
kaf24@1672 580 static u32 bus_scale; /* scaling factor convert ns to bus cycles */
kaf24@1452 581
kaf24@1452 582 /*
kaf24@1452 583 * The timer chip is already set up at HZ interrupts per second here,
kaf24@1452 584 * but we do not accept timer interrupts yet. We only allow the BP
kaf24@1452 585 * to calibrate.
kaf24@1452 586 */
kaf24@1452 587 static unsigned int __init get_8254_timer_count(void)
kaf24@1452 588 {
kaf24@1452 589 /*extern spinlock_t i8253_lock;*/
kaf24@1452 590 /*unsigned long flags;*/
iap10@4548 591
kaf24@1452 592 unsigned int count;
iap10@4548 593
kaf24@1452 594 /*spin_lock_irqsave(&i8253_lock, flags);*/
iap10@4548 595
iap10@4548 596 outb_p(0x00, PIT_MODE);
iap10@4548 597 count = inb_p(PIT_CH0);
iap10@4548 598 count |= inb_p(PIT_CH0) << 8;
iap10@4548 599
kaf24@1452 600 /*spin_unlock_irqrestore(&i8253_lock, flags);*/
iap10@4548 601
kaf24@1452 602 return count;
kaf24@1452 603 }
kaf24@1452 604
iap10@4548 605 /* next tick in 8254 can be caught by catching timer wraparound */
iap10@4548 606 static void __init wait_8254_wraparound(void)
kaf24@1452 607 {
kaf24@1452 608 unsigned int curr_count, prev_count=~0;
kaf24@1452 609 int delta;
iap10@4548 610
kaf24@1452 611 curr_count = get_8254_timer_count();
iap10@4548 612
kaf24@1452 613 do {
kaf24@1452 614 prev_count = curr_count;
kaf24@1452 615 curr_count = get_8254_timer_count();
kaf24@1452 616 delta = curr_count-prev_count;
iap10@4548 617
kaf24@1452 618 /*
iap10@4548 619 * This limit for delta seems arbitrary, but it isn't, it's
iap10@4548 620 * slightly above the level of error a buggy Mercury/Neptune
iap10@4548 621 * chipset timer can cause.
kaf24@1452 622 */
iap10@4548 623
kaf24@1452 624 } while (delta < 300);
kaf24@1452 625 }
kaf24@1452 626
kaf24@1452 627 /*
iap10@4548 628 * Default initialization for 8254 timers. If we use other timers like HPET,
iap10@4548 629 * we override this later
iap10@4548 630 */
iap10@4548 631 void (*wait_timer_tick)(void) = wait_8254_wraparound;
iap10@4548 632
iap10@4548 633 /*
kaf24@1452 634 * This function sets up the local APIC timer, with a timeout of
kaf24@1452 635 * 'clocks' APIC bus clock. During calibration we actually call
kaf24@1452 636 * this function with a very large value and read the current time after
kaf24@1452 637 * a well defined period of time as expired.
kaf24@1452 638 *
kaf24@1452 639 * Calibration is only performed once, for CPU0!
kaf24@1452 640 *
kaf24@1452 641 * We do reads before writes even if unnecessary, to get around the
kaf24@1452 642 * P5 APIC double write bug.
kaf24@1452 643 */
iap10@4548 644
kaf24@1452 645 #define APIC_DIVISOR 1
iap10@4548 646
kaf24@1452 647 static void __setup_APIC_LVTT(unsigned int clocks)
kaf24@1452 648 {
iap10@4548 649 unsigned int lvtt_value, tmp_value, ver;
iap10@4548 650
iap10@4548 651 ver = GET_APIC_VERSION(apic_read(APIC_LVR));
iap10@4548 652 lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
iap10@4548 653 if (!APIC_INTEGRATED(ver))
iap10@4548 654 lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
iap10@4548 655 apic_write_around(APIC_LVTT, lvtt_value);
iap10@4548 656
iap10@4548 657 #if 0
iap10@4548 658 /*
iap10@4548 659 * Divide PICLK by 16
iap10@4548 660 */
iap10@4548 661 tmp_value = apic_read(APIC_TDCR);
iap10@4548 662 apic_write_around(APIC_TDCR, (tmp_value
iap10@4548 663 & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
iap10@4548 664 | APIC_TDR_DIV_16);
iap10@4548 665 #endif
iap10@4548 666
kaf24@1452 667 tmp_value = apic_read(APIC_TDCR);
kaf24@1452 668 apic_write_around(APIC_TDCR, (tmp_value | APIC_TDR_DIV_1));
iap10@4548 669
kaf24@1452 670 apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
kaf24@1452 671 }
kaf24@1452 672
kaf24@1452 673 /*
kaf24@1452 674 * this is done for every CPU from setup_APIC_clocks() below.
kaf24@1452 675 * We setup each local APIC with a zero timeout value for now.
kaf24@1452 676 * Unlike Linux, we don't have to wait for slices etc.
kaf24@1452 677 */
kaf24@1452 678 void setup_APIC_timer(void * data)
kaf24@1452 679 {
kaf24@1452 680 unsigned long flags;
kaf24@1452 681 __save_flags(flags);
kaf24@1452 682 __sti();
kaf24@1452 683 __setup_APIC_LVTT(0);
kaf24@1452 684 __restore_flags(flags);
kaf24@1452 685 }
kaf24@1452 686
kaf24@1452 687 /*
kaf24@1452 688 * In this function we calibrate APIC bus clocks to the external timer.
kaf24@1452 689 *
iap10@4548 690 * As a result we have the Bus Speed and CPU speed in Hz.
kaf24@1452 691 *
kaf24@1452 692 * We want to do the calibration only once (for CPU0). CPUs connected by the
kaf24@1452 693 * same APIC bus have the very same bus frequency.
kaf24@1452 694 *
kaf24@1452 695 * This bit is a bit shoddy since we use the very same periodic timer interrupt
kaf24@1452 696 * we try to eliminate to calibrate the APIC.
kaf24@1452 697 */
kaf24@1452 698
kaf24@1452 699 int __init calibrate_APIC_clock(void)
kaf24@1452 700 {
kaf24@1452 701 unsigned long long t1 = 0, t2 = 0;
kaf24@1452 702 long tt1, tt2;
kaf24@1452 703 long result;
kaf24@1452 704 int i;
kaf24@1452 705 const int LOOPS = HZ/10;
kaf24@1452 706
iap10@4548 707 #if 0
iap10@4548 708 apic_printk(APIC_VERBOSE, "calibrating APIC timer ...\n");
iap10@4548 709 #endif
kaf24@1452 710 printk("Calibrating APIC timer for CPU%d...\n", smp_processor_id());
kaf24@1452 711
iap10@4548 712 /*
iap10@4548 713 * Put whatever arbitrary (but long enough) timeout
kaf24@1452 714 * value into the APIC clock, we just want to get the
iap10@4548 715 * counter running for calibration.
iap10@4548 716 */
kaf24@1452 717 __setup_APIC_LVTT(1000000000);
kaf24@1452 718
iap10@4548 719 /*
iap10@4548 720 * The timer chip counts down to zero. Let's wait
kaf24@1452 721 * for a wraparound to start exact measurement:
iap10@4548 722 * (the current tick might have been already half done)
iap10@4548 723 */
kaf24@1452 724
iap10@4548 725 wait_timer_tick();
iap10@4548 726
iap10@4548 727 /*
iap10@4548 728 * We wrapped around just now. Let's start:
iap10@4548 729 */
iap10@4548 730 if (cpu_has_tsc)
kaf24@1452 731 rdtscll(t1);
kaf24@1452 732 tt1 = apic_read(APIC_TMCCT);
kaf24@1452 733
iap10@4548 734 /*
iap10@4548 735 * Let's wait LOOPS wraprounds:
iap10@4548 736 */
kaf24@1452 737 for (i = 0; i < LOOPS; i++)
iap10@4548 738 wait_timer_tick();
kaf24@1452 739
kaf24@1452 740 tt2 = apic_read(APIC_TMCCT);
iap10@4548 741 if (cpu_has_tsc)
kaf24@1452 742 rdtscll(t2);
kaf24@1452 743
iap10@4548 744 /*
iap10@4548 745 * The APIC bus clock counter is 32 bits only, it
kaf24@1452 746 * might have overflown, but note that we use signed
kaf24@1452 747 * longs, thus no extra care needed.
iap10@4548 748 *
iap10@4548 749 * underflown to be exact, as the timer counts down ;)
iap10@4548 750 */
iap10@4548 751
kaf24@1452 752 result = (tt1-tt2)*APIC_DIVISOR/LOOPS;
kaf24@1452 753
iap10@4548 754 if (cpu_has_tsc)
iap10@4548 755 printk("..... CPU clock speed is %ld.%04ld MHz.\n",
iap10@4548 756 ((long)(t2-t1)/LOOPS)/(1000000/HZ),
iap10@4548 757 ((long)(t2-t1)/LOOPS)%(1000000/HZ));
kaf24@1452 758
iap10@4548 759 printk("..... host bus clock speed is %ld.%04ld MHz.\n",
iap10@4548 760 result/(1000000/HZ),
iap10@4548 761 result%(1000000/HZ));
kaf24@1452 762
kaf24@1452 763 /* set up multipliers for accurate timer code */
kaf24@1452 764 bus_freq = result*HZ;
kaf24@1452 765 bus_cycle = (u32) (1000000000000LL/bus_freq); /* in pico seconds */
kaf24@1452 766 bus_scale = (1000*262144)/bus_cycle;
kaf24@1452 767
kaf24@1452 768 printk("..... bus_scale = 0x%08X\n", bus_scale);
kaf24@1452 769 /* reset APIC to zero timeout value */
kaf24@1452 770 __setup_APIC_LVTT(0);
iap10@4548 771
kaf24@1452 772 return result;
kaf24@1452 773 }
kaf24@1452 774
kaf24@1452 775 /*
kaf24@1452 776 * initialise the APIC timers for all CPUs
kaf24@1452 777 * we start with the first and find out processor frequency and bus speed
kaf24@1452 778 */
kaf24@1452 779 void __init setup_APIC_clocks (void)
kaf24@1452 780 {
kaf24@1452 781 printk("Using local APIC timer interrupts.\n");
kaf24@1452 782 using_apic_timer = 1;
kaf24@1452 783 __cli();
kaf24@1452 784 /* calibrate CPU0 for CPU speed and BUS speed */
kaf24@1452 785 bus_freq = calibrate_APIC_clock();
kaf24@1452 786 /* Now set up the timer for real. */
kaf24@1452 787 setup_APIC_timer((void *)bus_freq);
kaf24@1452 788 __sti();
kaf24@1452 789 /* and update all other cpus */
kaf24@1452 790 smp_call_function(setup_APIC_timer, (void *)bus_freq, 1, 1);
kaf24@1452 791 }
kaf24@1452 792
kaf24@1452 793 #undef APIC_DIVISOR
kaf24@1452 794
kaf24@1452 795 /*
kaf24@1452 796 * reprogram the APIC timer. Timeoutvalue is in ns from start of boot
kaf24@1452 797 * returns 1 on success
kaf24@1452 798 * returns 0 if the timeout value is too small or in the past.
kaf24@1452 799 */
kaf24@1452 800 int reprogram_ac_timer(s_time_t timeout)
kaf24@1452 801 {
kaf24@1452 802 s_time_t now;
kaf24@1452 803 s_time_t expire;
kaf24@1452 804 u64 apic_tmict;
kaf24@1452 805
kaf24@1452 806 /*
kaf24@1452 807 * We use this value because we don't trust zero (we think it may just
kaf24@1452 808 * cause an immediate interrupt). At least this is guaranteed to hold it
kaf24@1452 809 * off for ages (esp. since the clock ticks on bus clock, not cpu clock!).
kaf24@1452 810 */
kaf24@1452 811 if ( timeout == 0 )
kaf24@1452 812 {
kaf24@1452 813 apic_tmict = 0xffffffff;
kaf24@1452 814 goto reprogram;
kaf24@1452 815 }
kaf24@1452 816
kaf24@1452 817 now = NOW();
kaf24@1452 818 expire = timeout - now; /* value from now */
kaf24@1452 819
kaf24@1452 820 if ( expire <= 0 )
kaf24@1452 821 {
kaf24@1452 822 Dprintk("APICT[%02d] Timeout in the past 0x%08X%08X > 0x%08X%08X\n",
kaf24@1452 823 smp_processor_id(), (u32)(now>>32),
kaf24@1452 824 (u32)now, (u32)(timeout>>32),(u32)timeout);
kaf24@1452 825 return 0;
kaf24@1452 826 }
kaf24@1452 827
kaf24@1452 828 /*
kaf24@1452 829 * If we don't have local APIC then we just poll the timer list off the
kaf24@1452 830 * PIT interrupt. Cheesy but good enough to work on eg. VMware :-)
kaf24@1452 831 */
kaf24@1452 832 if ( !cpu_has_apic )
kaf24@1452 833 return 1;
kaf24@1452 834
kaf24@1452 835 /* conversion to bus units */
kaf24@1452 836 apic_tmict = (((u64)bus_scale) * expire)>>18;
kaf24@1452 837
kaf24@1452 838 if ( apic_tmict >= 0xffffffff )
kaf24@1452 839 {
kaf24@1452 840 Dprintk("APICT[%02d] Timeout value too large\n", smp_processor_id());
kaf24@1452 841 apic_tmict = 0xffffffff;
kaf24@1452 842 }
kaf24@1452 843
kaf24@1452 844 if ( apic_tmict == 0 )
kaf24@1452 845 {
kaf24@1452 846 Dprintk("APICT[%02d] timeout value too small\n", smp_processor_id());
kaf24@1452 847 return 0;
kaf24@1452 848 }
kaf24@1452 849
kaf24@1452 850 reprogram:
kaf24@1452 851 /* Program the timer. */
kaf24@1452 852 apic_write(APIC_TMICT, (unsigned long)apic_tmict);
kaf24@1452 853
kaf24@1452 854 return 1;
kaf24@1452 855 }
kaf24@1452 856
ach61@2805 857 void smp_apic_timer_interrupt(struct xen_regs * regs)
kaf24@1452 858 {
kaf24@1452 859 ack_APIC_irq();
kaf24@1452 860 perfc_incrc(apic_timer);
kaf24@1506 861 raise_softirq(AC_TIMER_SOFTIRQ);
kaf24@1452 862 }
kaf24@1452 863
iap10@4548 864
kaf24@1452 865 /*
kaf24@1452 866 * This interrupt should _never_ happen with our APIC/SMP architecture
kaf24@1452 867 */
iap10@4548 868 asmlinkage void smp_spurious_interrupt(struct xen_regs *regs)
kaf24@1452 869 {
kaf24@1452 870 unsigned long v;
kaf24@1452 871
iap10@4548 872 #if 0
iap10@4548 873 irq_enter();
iap10@4548 874 #endif
kaf24@1452 875 /*
kaf24@1452 876 * Check if this really is a spurious interrupt and ACK it
kaf24@1452 877 * if it is a vectored one. Just in case...
kaf24@1452 878 * Spurious interrupts should not be ACKed.
kaf24@1452 879 */
kaf24@1452 880 v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1));
kaf24@1452 881 if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
kaf24@1452 882 ack_APIC_irq();
kaf24@1452 883
kaf24@1452 884 /* see sw-dev-man vol 3, chapter 7.4.13.5 */
kaf24@1452 885 printk("spurious APIC interrupt on CPU#%d, should never happen.\n",
kaf24@1452 886 smp_processor_id());
iap10@4548 887 #if 0
iap10@4548 888 irq_exit();
iap10@4548 889 #endif
kaf24@1452 890 }
kaf24@1452 891
kaf24@1452 892 /*
kaf24@1452 893 * This interrupt should never happen with our APIC/SMP architecture
kaf24@1452 894 */
kaf24@1452 895
iap10@4548 896 asmlinkage void smp_error_interrupt(struct xen_regs *regs)
kaf24@1452 897 {
kaf24@1452 898 unsigned long v, v1;
kaf24@1452 899
iap10@4548 900 #if 0
iap10@4548 901 irq_enter();
iap10@4548 902 #endif
kaf24@1452 903 /* First tickle the hardware, only then report what went on. -- REW */
kaf24@1452 904 v = apic_read(APIC_ESR);
kaf24@1452 905 apic_write(APIC_ESR, 0);
kaf24@1452 906 v1 = apic_read(APIC_ESR);
kaf24@1452 907 ack_APIC_irq();
kaf24@1452 908 atomic_inc(&irq_err_count);
kaf24@1452 909
kaf24@1452 910 /* Here is what the APIC error bits mean:
kaf24@1452 911 0: Send CS error
kaf24@1452 912 1: Receive CS error
kaf24@1452 913 2: Send accept error
kaf24@1452 914 3: Receive accept error
kaf24@1452 915 4: Reserved
kaf24@1452 916 5: Send illegal vector
kaf24@1452 917 6: Received illegal vector
kaf24@1452 918 7: Illegal register address
kaf24@1452 919 */
iap10@4548 920 Dprintk("APIC error on CPU%d: %02lx(%02lx)\n",
kaf24@1452 921 smp_processor_id(), v , v1);
iap10@4548 922 #if 0
iap10@4548 923 irq_exit();
iap10@4548 924 #endif
kaf24@1452 925 }
kaf24@1452 926
kaf24@1452 927 /*
kaf24@1452 928 * This initializes the IO-APIC and APIC hardware if this is
kaf24@1452 929 * a UP kernel.
kaf24@1452 930 */
kaf24@1452 931 int __init APIC_init_uniprocessor (void)
kaf24@1452 932 {
iap10@4548 933 #if 0
iap10@4548 934 if (enable_local_apic < 0)
iap10@4548 935 clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
iap10@4548 936 #endif
iap10@4548 937
kaf24@1452 938 if (!smp_found_config && !cpu_has_apic)
kaf24@1452 939 return -1;
kaf24@1452 940
kaf24@1452 941 /*
kaf24@1452 942 * Complain if the BIOS pretends there is one.
kaf24@1452 943 */
iap10@4548 944 if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
kaf24@1452 945 printk("BIOS bug, local APIC #%d not detected!...\n",
kaf24@1452 946 boot_cpu_physical_apicid);
kaf24@1452 947 return -1;
kaf24@1452 948 }
kaf24@1452 949
kaf24@1452 950 verify_local_APIC();
kaf24@1452 951
kaf24@1452 952 connect_bsp_APIC();
kaf24@1452 953
kaf24@1452 954 #ifdef CONFIG_SMP
kaf24@1452 955 cpu_online_map = 1;
kaf24@1452 956 #endif
iap10@4548 957 #if 0
iap10@4548 958 phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
iap10@4548 959 #endif
kaf24@1452 960 phys_cpu_present_map = 1;
kaf24@1452 961 apic_write_around(APIC_ID, boot_cpu_physical_apicid);
kaf24@1452 962
kaf24@1452 963 setup_local_APIC();
kaf24@1452 964
iap10@4548 965 #if 0
iap10@4548 966 if (nmi_watchdog == NMI_LOCAL_APIC)
iap10@4548 967 check_nmi_watchdog();
iap10@4548 968 #endif
kaf24@1452 969 #ifdef CONFIG_X86_IO_APIC
iap10@4548 970 if (smp_found_config)
iap10@4548 971 if (!skip_ioapic_setup && nr_ioapics)
kaf24@1452 972 setup_IO_APIC();
kaf24@1452 973 #endif
iap10@4548 974 #if 0
iap10@4548 975 setup_boot_APIC_clock();
iap10@4548 976 #endif
kaf24@1452 977 setup_APIC_clocks();
kaf24@1452 978
kaf24@1452 979 return 0;
kaf24@1452 980 }