aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic/apic.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2010-12-29 14:36:26 -0500
committerH. Peter Anvin <hpa@linux.intel.com>2010-12-29 14:36:26 -0500
commitd50e8fc7e38d88909448a723cb1f825bb3af30e2 (patch)
tree099e969b273c3d180c89aa64b1e359ef66a9fc5d /arch/x86/kernel/apic/apic.c
parenta387e95a49743cf9835c5299ca549232618d8249 (diff)
parent0aa002fe602939370e9476e5ec32b562000a0425 (diff)
Merge branch 'x86/apic-cleanups' into x86/numa
Diffstat (limited to 'arch/x86/kernel/apic/apic.c')
-rw-r--r--arch/x86/kernel/apic/apic.c151
1 files changed, 80 insertions, 71 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 3f838d537392..c0f6426cd337 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1195,12 +1195,15 @@ static void __cpuinit lapic_setup_esr(void)
1195 oldvalue, value); 1195 oldvalue, value);
1196} 1196}
1197 1197
1198
1199/** 1198/**
1200 * setup_local_APIC - setup the local APIC 1199 * setup_local_APIC - setup the local APIC
1200 *
1201 * Used to setup local APIC while initializing BSP or bringin up APs.
1202 * Always called with preemption disabled.
1201 */ 1203 */
1202void __cpuinit setup_local_APIC(void) 1204void __cpuinit setup_local_APIC(void)
1203{ 1205{
1206 int cpu = smp_processor_id();
1204 unsigned int value, queued; 1207 unsigned int value, queued;
1205 int i, j, acked = 0; 1208 int i, j, acked = 0;
1206 unsigned long long tsc = 0, ntsc; 1209 unsigned long long tsc = 0, ntsc;
@@ -1225,8 +1228,6 @@ void __cpuinit setup_local_APIC(void)
1225#endif 1228#endif
1226 perf_events_lapic_init(); 1229 perf_events_lapic_init();
1227 1230
1228 preempt_disable();
1229
1230 /* 1231 /*
1231 * Double-check whether this APIC is really registered. 1232 * Double-check whether this APIC is really registered.
1232 * This is meaningless in clustered apic mode, so we skip it. 1233 * This is meaningless in clustered apic mode, so we skip it.
@@ -1342,21 +1343,19 @@ void __cpuinit setup_local_APIC(void)
1342 * TODO: set up through-local-APIC from through-I/O-APIC? --macro 1343 * TODO: set up through-local-APIC from through-I/O-APIC? --macro
1343 */ 1344 */
1344 value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; 1345 value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
1345 if (!smp_processor_id() && (pic_mode || !value)) { 1346 if (!cpu && (pic_mode || !value)) {
1346 value = APIC_DM_EXTINT; 1347 value = APIC_DM_EXTINT;
1347 apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", 1348 apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", cpu);
1348 smp_processor_id());
1349 } else { 1349 } else {
1350 value = APIC_DM_EXTINT | APIC_LVT_MASKED; 1350 value = APIC_DM_EXTINT | APIC_LVT_MASKED;
1351 apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", 1351 apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", cpu);
1352 smp_processor_id());
1353 } 1352 }
1354 apic_write(APIC_LVT0, value); 1353 apic_write(APIC_LVT0, value);
1355 1354
1356 /* 1355 /*
1357 * only the BP should see the LINT1 NMI signal, obviously. 1356 * only the BP should see the LINT1 NMI signal, obviously.
1358 */ 1357 */
1359 if (!smp_processor_id()) 1358 if (!cpu)
1360 value = APIC_DM_NMI; 1359 value = APIC_DM_NMI;
1361 else 1360 else
1362 value = APIC_DM_NMI | APIC_LVT_MASKED; 1361 value = APIC_DM_NMI | APIC_LVT_MASKED;
@@ -1364,11 +1363,9 @@ void __cpuinit setup_local_APIC(void)
1364 value |= APIC_LVT_LEVEL_TRIGGER; 1363 value |= APIC_LVT_LEVEL_TRIGGER;
1365 apic_write(APIC_LVT1, value); 1364 apic_write(APIC_LVT1, value);
1366 1365
1367 preempt_enable();
1368
1369#ifdef CONFIG_X86_MCE_INTEL 1366#ifdef CONFIG_X86_MCE_INTEL
1370 /* Recheck CMCI information after local APIC is up on CPU #0 */ 1367 /* Recheck CMCI information after local APIC is up on CPU #0 */
1371 if (smp_processor_id() == 0) 1368 if (!cpu)
1372 cmci_recheck(); 1369 cmci_recheck();
1373#endif 1370#endif
1374} 1371}
@@ -1530,13 +1527,60 @@ static int __init detect_init_APIC(void)
1530 return 0; 1527 return 0;
1531} 1528}
1532#else 1529#else
1530
1531static int apic_verify(void)
1532{
1533 u32 features, h, l;
1534
1535 /*
1536 * The APIC feature bit should now be enabled
1537 * in `cpuid'
1538 */
1539 features = cpuid_edx(1);
1540 if (!(features & (1 << X86_FEATURE_APIC))) {
1541 pr_warning("Could not enable APIC!\n");
1542 return -1;
1543 }
1544 set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
1545 mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
1546
1547 /* The BIOS may have set up the APIC at some other address */
1548 rdmsr(MSR_IA32_APICBASE, l, h);
1549 if (l & MSR_IA32_APICBASE_ENABLE)
1550 mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
1551
1552 pr_info("Found and enabled local APIC!\n");
1553 return 0;
1554}
1555
1556int apic_force_enable(void)
1557{
1558 u32 h, l;
1559
1560 if (disable_apic)
1561 return -1;
1562
1563 /*
1564 * Some BIOSes disable the local APIC in the APIC_BASE
1565 * MSR. This can only be done in software for Intel P6 or later
1566 * and AMD K7 (Model > 1) or later.
1567 */
1568 rdmsr(MSR_IA32_APICBASE, l, h);
1569 if (!(l & MSR_IA32_APICBASE_ENABLE)) {
1570 pr_info("Local APIC disabled by BIOS -- reenabling.\n");
1571 l &= ~MSR_IA32_APICBASE_BASE;
1572 l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
1573 wrmsr(MSR_IA32_APICBASE, l, h);
1574 enabled_via_apicbase = 1;
1575 }
1576 return apic_verify();
1577}
1578
1533/* 1579/*
1534 * Detect and initialize APIC 1580 * Detect and initialize APIC
1535 */ 1581 */
1536static int __init detect_init_APIC(void) 1582static int __init detect_init_APIC(void)
1537{ 1583{
1538 u32 h, l, features;
1539
1540 /* Disabled by kernel option? */ 1584 /* Disabled by kernel option? */
1541 if (disable_apic) 1585 if (disable_apic)
1542 return -1; 1586 return -1;
@@ -1566,38 +1610,12 @@ static int __init detect_init_APIC(void)
1566 "you can enable it with \"lapic\"\n"); 1610 "you can enable it with \"lapic\"\n");
1567 return -1; 1611 return -1;
1568 } 1612 }
1569 /* 1613 if (apic_force_enable())
1570 * Some BIOSes disable the local APIC in the APIC_BASE 1614 return -1;
1571 * MSR. This can only be done in software for Intel P6 or later 1615 } else {
1572 * and AMD K7 (Model > 1) or later. 1616 if (apic_verify())
1573 */ 1617 return -1;
1574 rdmsr(MSR_IA32_APICBASE, l, h);
1575 if (!(l & MSR_IA32_APICBASE_ENABLE)) {
1576 pr_info("Local APIC disabled by BIOS -- reenabling.\n");
1577 l &= ~MSR_IA32_APICBASE_BASE;
1578 l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
1579 wrmsr(MSR_IA32_APICBASE, l, h);
1580 enabled_via_apicbase = 1;
1581 }
1582 }
1583 /*
1584 * The APIC feature bit should now be enabled
1585 * in `cpuid'
1586 */
1587 features = cpuid_edx(1);
1588 if (!(features & (1 << X86_FEATURE_APIC))) {
1589 pr_warning("Could not enable APIC!\n");
1590 return -1;
1591 } 1618 }
1592 set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
1593 mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
1594
1595 /* The BIOS may have set up the APIC at some other address */
1596 rdmsr(MSR_IA32_APICBASE, l, h);
1597 if (l & MSR_IA32_APICBASE_ENABLE)
1598 mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
1599
1600 pr_info("Found and enabled local APIC!\n");
1601 1619
1602 apic_pm_activate(); 1620 apic_pm_activate();
1603 1621
@@ -1609,28 +1627,6 @@ no_apic:
1609} 1627}
1610#endif 1628#endif
1611 1629
1612#ifdef CONFIG_X86_64
1613void __init early_init_lapic_mapping(void)
1614{
1615 /*
1616 * If no local APIC can be found then go out
1617 * : it means there is no mpatable and MADT
1618 */
1619 if (!smp_found_config)
1620 return;
1621
1622 set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
1623 apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
1624 APIC_BASE, mp_lapic_addr);
1625
1626 /*
1627 * Fetch the APIC ID of the BSP in case we have a
1628 * default configuration (or the MP table is broken).
1629 */
1630 boot_cpu_physical_apicid = read_apic_id();
1631}
1632#endif
1633
1634/** 1630/**
1635 * init_apic_mappings - initialize APIC mappings 1631 * init_apic_mappings - initialize APIC mappings
1636 */ 1632 */
@@ -1656,10 +1652,7 @@ void __init init_apic_mappings(void)
1656 * acpi_register_lapic_address() 1652 * acpi_register_lapic_address()
1657 */ 1653 */
1658 if (!acpi_lapic && !smp_found_config) 1654 if (!acpi_lapic && !smp_found_config)
1659 set_fixmap_nocache(FIX_APIC_BASE, apic_phys); 1655 register_lapic_address(apic_phys);
1660
1661 apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n",
1662 APIC_BASE, apic_phys);
1663 } 1656 }
1664 1657
1665 /* 1658 /*
@@ -1681,6 +1674,22 @@ void __init init_apic_mappings(void)
1681 } 1674 }
1682} 1675}
1683 1676
1677void __init register_lapic_address(unsigned long address)
1678{
1679 mp_lapic_addr = address;
1680
1681 if (!x2apic_mode) {
1682 set_fixmap_nocache(FIX_APIC_BASE, address);
1683 apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
1684 APIC_BASE, mp_lapic_addr);
1685 }
1686 if (boot_cpu_physical_apicid == -1U) {
1687 boot_cpu_physical_apicid = read_apic_id();
1688 apic_version[boot_cpu_physical_apicid] =
1689 GET_APIC_VERSION(apic_read(APIC_LVR));
1690 }
1691}
1692
1684/* 1693/*
1685 * This initializes the IO-APIC and APIC hardware if this is 1694 * This initializes the IO-APIC and APIC hardware if this is
1686 * a UP kernel. 1695 * a UP kernel.