diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2010-12-29 14:36:26 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2010-12-29 14:36:26 -0500 |
commit | d50e8fc7e38d88909448a723cb1f825bb3af30e2 (patch) | |
tree | 099e969b273c3d180c89aa64b1e359ef66a9fc5d /arch/x86/kernel/apic/apic.c | |
parent | a387e95a49743cf9835c5299ca549232618d8249 (diff) | |
parent | 0aa002fe602939370e9476e5ec32b562000a0425 (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.c | 151 |
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 | */ |
1202 | void __cpuinit setup_local_APIC(void) | 1204 | void __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 | |||
1531 | static 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 | |||
1556 | int 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 | */ |
1536 | static int __init detect_init_APIC(void) | 1582 | static 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 | ||
1613 | void __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 | ||
1677 | void __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. |