diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-09 19:57:56 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-09 19:57:56 -0500 |
commit | 9d43bade347143b96671b38a7f81c39a81206675 (patch) | |
tree | 9c2126fa29fdbc6274f83be653de5f014e999f32 /arch/x86/kernel | |
parent | 0ba97bc4b4b054b71cd348dab838a7545a27b893 (diff) | |
parent | ba360f887a4130b06c55eb93bcb4ae373b262a1c (diff) |
Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 APIC updates from Ingo Molnar:
"Continued fallout of the conversion of the x86 IRQ code to the
hierarchical irqdomain framework: more cleanups, simplifications,
memory allocation behavior enhancements, mainly in the interrupt
remapping and APIC code"
* 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (44 commits)
x86, init: Fix UP boot regression on x86_64
iommu/amd: Fix irq remapping detection logic
x86/acpi: Make acpi_[un]register_gsi_ioapic() depend on CONFIG_X86_LOCAL_APIC
x86: Consolidate boot cpu timer setup
x86/apic: Reuse apic_bsp_setup() for UP APIC setup
x86/smpboot: Sanitize uniprocessor init
x86/smpboot: Move apic init code to apic.c
init: Get rid of x86isms
x86/apic: Move apic_init_uniprocessor code
x86/smpboot: Cleanup ioapic handling
x86/apic: Sanitize ioapic handling
x86/ioapic: Add proper checks to setp/enable_IO_APIC()
x86/ioapic: Provide stub functions for IOAPIC%3Dn
x86/smpboot: Move smpboot inlines to code
x86/x2apic: Use state information for disable
x86/x2apic: Split enable and setup function
x86/x2apic: Disable x2apic from nox2apic setup
x86/x2apic: Add proper state tracking
x86/x2apic: Clarify remapping mode for x2apic enablement
x86/x2apic: Move code in conditional region
...
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 456 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 13 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/smpboot.c | 113 |
5 files changed, 317 insertions, 269 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index b9e30daa0881..a18fff361c7f 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -653,6 +653,7 @@ static int acpi_register_gsi_pic(struct device *dev, u32 gsi, | |||
653 | return gsi; | 653 | return gsi; |
654 | } | 654 | } |
655 | 655 | ||
656 | #ifdef CONFIG_X86_LOCAL_APIC | ||
656 | static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi, | 657 | static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi, |
657 | int trigger, int polarity) | 658 | int trigger, int polarity) |
658 | { | 659 | { |
@@ -675,6 +676,7 @@ static void acpi_unregister_gsi_ioapic(u32 gsi) | |||
675 | mutex_unlock(&acpi_ioapic_lock); | 676 | mutex_unlock(&acpi_ioapic_lock); |
676 | #endif | 677 | #endif |
677 | } | 678 | } |
679 | #endif | ||
678 | 680 | ||
679 | int (*__acpi_register_gsi)(struct device *dev, u32 gsi, | 681 | int (*__acpi_register_gsi)(struct device *dev, u32 gsi, |
680 | int trigger, int polarity) = acpi_register_gsi_pic; | 682 | int trigger, int polarity) = acpi_register_gsi_pic; |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 29b5b18afa27..b665d241efad 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -134,9 +134,6 @@ static inline void imcr_apic_to_pic(void) | |||
134 | */ | 134 | */ |
135 | static int force_enable_local_apic __initdata; | 135 | static int force_enable_local_apic __initdata; |
136 | 136 | ||
137 | /* Control whether x2APIC mode is enabled or not */ | ||
138 | static bool nox2apic __initdata; | ||
139 | |||
140 | /* | 137 | /* |
141 | * APIC command line parameters | 138 | * APIC command line parameters |
142 | */ | 139 | */ |
@@ -161,33 +158,6 @@ static __init int setup_apicpmtimer(char *s) | |||
161 | __setup("apicpmtimer", setup_apicpmtimer); | 158 | __setup("apicpmtimer", setup_apicpmtimer); |
162 | #endif | 159 | #endif |
163 | 160 | ||
164 | int x2apic_mode; | ||
165 | #ifdef CONFIG_X86_X2APIC | ||
166 | /* x2apic enabled before OS handover */ | ||
167 | int x2apic_preenabled; | ||
168 | static int x2apic_disabled; | ||
169 | static int __init setup_nox2apic(char *str) | ||
170 | { | ||
171 | if (x2apic_enabled()) { | ||
172 | int apicid = native_apic_msr_read(APIC_ID); | ||
173 | |||
174 | if (apicid >= 255) { | ||
175 | pr_warning("Apicid: %08x, cannot enforce nox2apic\n", | ||
176 | apicid); | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | pr_warning("x2apic already enabled. will disable it\n"); | ||
181 | } else | ||
182 | setup_clear_cpu_cap(X86_FEATURE_X2APIC); | ||
183 | |||
184 | nox2apic = true; | ||
185 | |||
186 | return 0; | ||
187 | } | ||
188 | early_param("nox2apic", setup_nox2apic); | ||
189 | #endif | ||
190 | |||
191 | unsigned long mp_lapic_addr; | 161 | unsigned long mp_lapic_addr; |
192 | int disable_apic; | 162 | int disable_apic; |
193 | /* Disable local APIC timer from the kernel commandline or via dmi quirk */ | 163 | /* Disable local APIC timer from the kernel commandline or via dmi quirk */ |
@@ -1475,7 +1445,7 @@ void setup_local_APIC(void) | |||
1475 | #endif | 1445 | #endif |
1476 | } | 1446 | } |
1477 | 1447 | ||
1478 | void end_local_APIC_setup(void) | 1448 | static void end_local_APIC_setup(void) |
1479 | { | 1449 | { |
1480 | lapic_setup_esr(); | 1450 | lapic_setup_esr(); |
1481 | 1451 | ||
@@ -1492,116 +1462,184 @@ void end_local_APIC_setup(void) | |||
1492 | apic_pm_activate(); | 1462 | apic_pm_activate(); |
1493 | } | 1463 | } |
1494 | 1464 | ||
1495 | void __init bsp_end_local_APIC_setup(void) | 1465 | /* |
1466 | * APIC setup function for application processors. Called from smpboot.c | ||
1467 | */ | ||
1468 | void apic_ap_setup(void) | ||
1496 | { | 1469 | { |
1470 | setup_local_APIC(); | ||
1497 | end_local_APIC_setup(); | 1471 | end_local_APIC_setup(); |
1498 | |||
1499 | /* | ||
1500 | * Now that local APIC setup is completed for BP, configure the fault | ||
1501 | * handling for interrupt remapping. | ||
1502 | */ | ||
1503 | irq_remap_enable_fault_handling(); | ||
1504 | |||
1505 | } | 1472 | } |
1506 | 1473 | ||
1507 | #ifdef CONFIG_X86_X2APIC | 1474 | #ifdef CONFIG_X86_X2APIC |
1508 | /* | 1475 | int x2apic_mode; |
1509 | * Need to disable xapic and x2apic at the same time and then enable xapic mode | ||
1510 | */ | ||
1511 | static inline void __disable_x2apic(u64 msr) | ||
1512 | { | ||
1513 | wrmsrl(MSR_IA32_APICBASE, | ||
1514 | msr & ~(X2APIC_ENABLE | XAPIC_ENABLE)); | ||
1515 | wrmsrl(MSR_IA32_APICBASE, msr & ~X2APIC_ENABLE); | ||
1516 | } | ||
1517 | 1476 | ||
1518 | static __init void disable_x2apic(void) | 1477 | enum { |
1478 | X2APIC_OFF, | ||
1479 | X2APIC_ON, | ||
1480 | X2APIC_DISABLED, | ||
1481 | }; | ||
1482 | static int x2apic_state; | ||
1483 | |||
1484 | static inline void __x2apic_disable(void) | ||
1519 | { | 1485 | { |
1520 | u64 msr; | 1486 | u64 msr; |
1521 | 1487 | ||
1522 | if (!cpu_has_x2apic) | 1488 | if (cpu_has_apic) |
1523 | return; | 1489 | return; |
1524 | 1490 | ||
1525 | rdmsrl(MSR_IA32_APICBASE, msr); | 1491 | rdmsrl(MSR_IA32_APICBASE, msr); |
1526 | if (msr & X2APIC_ENABLE) { | 1492 | if (!(msr & X2APIC_ENABLE)) |
1527 | u32 x2apic_id = read_apic_id(); | 1493 | return; |
1528 | 1494 | /* Disable xapic and x2apic first and then reenable xapic mode */ | |
1529 | if (x2apic_id >= 255) | 1495 | wrmsrl(MSR_IA32_APICBASE, msr & ~(X2APIC_ENABLE | XAPIC_ENABLE)); |
1530 | panic("Cannot disable x2apic, id: %08x\n", x2apic_id); | 1496 | wrmsrl(MSR_IA32_APICBASE, msr & ~X2APIC_ENABLE); |
1497 | printk_once(KERN_INFO "x2apic disabled\n"); | ||
1498 | } | ||
1531 | 1499 | ||
1532 | pr_info("Disabling x2apic\n"); | 1500 | static inline void __x2apic_enable(void) |
1533 | __disable_x2apic(msr); | 1501 | { |
1502 | u64 msr; | ||
1534 | 1503 | ||
1535 | if (nox2apic) { | 1504 | rdmsrl(MSR_IA32_APICBASE, msr); |
1536 | clear_cpu_cap(&cpu_data(0), X86_FEATURE_X2APIC); | 1505 | if (msr & X2APIC_ENABLE) |
1537 | setup_clear_cpu_cap(X86_FEATURE_X2APIC); | 1506 | return; |
1538 | } | 1507 | wrmsrl(MSR_IA32_APICBASE, msr | X2APIC_ENABLE); |
1508 | printk_once(KERN_INFO "x2apic enabled\n"); | ||
1509 | } | ||
1539 | 1510 | ||
1540 | x2apic_disabled = 1; | 1511 | static int __init setup_nox2apic(char *str) |
1541 | x2apic_mode = 0; | 1512 | { |
1513 | if (x2apic_enabled()) { | ||
1514 | int apicid = native_apic_msr_read(APIC_ID); | ||
1542 | 1515 | ||
1543 | register_lapic_address(mp_lapic_addr); | 1516 | if (apicid >= 255) { |
1517 | pr_warning("Apicid: %08x, cannot enforce nox2apic\n", | ||
1518 | apicid); | ||
1519 | return 0; | ||
1520 | } | ||
1521 | pr_warning("x2apic already enabled.\n"); | ||
1522 | __x2apic_disable(); | ||
1544 | } | 1523 | } |
1524 | setup_clear_cpu_cap(X86_FEATURE_X2APIC); | ||
1525 | x2apic_state = X2APIC_DISABLED; | ||
1526 | x2apic_mode = 0; | ||
1527 | return 0; | ||
1545 | } | 1528 | } |
1529 | early_param("nox2apic", setup_nox2apic); | ||
1546 | 1530 | ||
1547 | void check_x2apic(void) | 1531 | /* Called from cpu_init() to enable x2apic on (secondary) cpus */ |
1532 | void x2apic_setup(void) | ||
1548 | { | 1533 | { |
1549 | if (x2apic_enabled()) { | 1534 | /* |
1550 | pr_info("x2apic enabled by BIOS, switching to x2apic ops\n"); | 1535 | * If x2apic is not in ON state, disable it if already enabled |
1551 | x2apic_preenabled = x2apic_mode = 1; | 1536 | * from BIOS. |
1537 | */ | ||
1538 | if (x2apic_state != X2APIC_ON) { | ||
1539 | __x2apic_disable(); | ||
1540 | return; | ||
1552 | } | 1541 | } |
1542 | __x2apic_enable(); | ||
1553 | } | 1543 | } |
1554 | 1544 | ||
1555 | void enable_x2apic(void) | 1545 | static __init void x2apic_disable(void) |
1556 | { | 1546 | { |
1557 | u64 msr; | 1547 | u32 x2apic_id; |
1558 | 1548 | ||
1559 | rdmsrl(MSR_IA32_APICBASE, msr); | 1549 | if (x2apic_state != X2APIC_ON) |
1560 | if (x2apic_disabled) { | 1550 | goto out; |
1561 | __disable_x2apic(msr); | 1551 | |
1552 | x2apic_id = read_apic_id(); | ||
1553 | if (x2apic_id >= 255) | ||
1554 | panic("Cannot disable x2apic, id: %08x\n", x2apic_id); | ||
1555 | |||
1556 | __x2apic_disable(); | ||
1557 | register_lapic_address(mp_lapic_addr); | ||
1558 | out: | ||
1559 | x2apic_state = X2APIC_DISABLED; | ||
1560 | x2apic_mode = 0; | ||
1561 | } | ||
1562 | |||
1563 | static __init void x2apic_enable(void) | ||
1564 | { | ||
1565 | if (x2apic_state != X2APIC_OFF) | ||
1562 | return; | 1566 | return; |
1563 | } | ||
1564 | 1567 | ||
1565 | if (!x2apic_mode) | 1568 | x2apic_mode = 1; |
1569 | x2apic_state = X2APIC_ON; | ||
1570 | __x2apic_enable(); | ||
1571 | } | ||
1572 | |||
1573 | static __init void try_to_enable_x2apic(int remap_mode) | ||
1574 | { | ||
1575 | if (x2apic_state == X2APIC_DISABLED) | ||
1566 | return; | 1576 | return; |
1567 | 1577 | ||
1568 | if (!(msr & X2APIC_ENABLE)) { | 1578 | if (remap_mode != IRQ_REMAP_X2APIC_MODE) { |
1569 | printk_once(KERN_INFO "Enabling x2apic\n"); | 1579 | /* IR is required if there is APIC ID > 255 even when running |
1570 | wrmsrl(MSR_IA32_APICBASE, msr | X2APIC_ENABLE); | 1580 | * under KVM |
1581 | */ | ||
1582 | if (max_physical_apicid > 255 || | ||
1583 | (IS_ENABLED(CONFIG_HYPERVISOR_GUEST) && | ||
1584 | !hypervisor_x2apic_available())) { | ||
1585 | pr_info("x2apic: IRQ remapping doesn't support X2APIC mode\n"); | ||
1586 | x2apic_disable(); | ||
1587 | return; | ||
1588 | } | ||
1589 | |||
1590 | /* | ||
1591 | * without IR all CPUs can be addressed by IOAPIC/MSI | ||
1592 | * only in physical mode | ||
1593 | */ | ||
1594 | x2apic_phys = 1; | ||
1571 | } | 1595 | } |
1596 | x2apic_enable(); | ||
1572 | } | 1597 | } |
1573 | #endif /* CONFIG_X86_X2APIC */ | ||
1574 | 1598 | ||
1575 | int __init enable_IR(void) | 1599 | void __init check_x2apic(void) |
1576 | { | 1600 | { |
1577 | #ifdef CONFIG_IRQ_REMAP | 1601 | if (x2apic_enabled()) { |
1578 | if (!irq_remapping_supported()) { | 1602 | pr_info("x2apic: enabled by BIOS, switching to x2apic ops\n"); |
1579 | pr_debug("intr-remapping not supported\n"); | 1603 | x2apic_mode = 1; |
1580 | return -1; | 1604 | x2apic_state = X2APIC_ON; |
1605 | } else if (!cpu_has_x2apic) { | ||
1606 | x2apic_state = X2APIC_DISABLED; | ||
1581 | } | 1607 | } |
1608 | } | ||
1609 | #else /* CONFIG_X86_X2APIC */ | ||
1610 | static int __init validate_x2apic(void) | ||
1611 | { | ||
1612 | if (!apic_is_x2apic_enabled()) | ||
1613 | return 0; | ||
1614 | /* | ||
1615 | * Checkme: Can we simply turn off x2apic here instead of panic? | ||
1616 | */ | ||
1617 | panic("BIOS has enabled x2apic but kernel doesn't support x2apic, please disable x2apic in BIOS.\n"); | ||
1618 | } | ||
1619 | early_initcall(validate_x2apic); | ||
1582 | 1620 | ||
1583 | if (!x2apic_preenabled && skip_ioapic_setup) { | 1621 | static inline void try_to_enable_x2apic(int remap_mode) { } |
1584 | pr_info("Skipped enabling intr-remap because of skipping " | 1622 | static inline void __x2apic_enable(void) { } |
1585 | "io-apic setup\n"); | 1623 | #endif /* !CONFIG_X86_X2APIC */ |
1624 | |||
1625 | static int __init try_to_enable_IR(void) | ||
1626 | { | ||
1627 | #ifdef CONFIG_X86_IO_APIC | ||
1628 | if (!x2apic_enabled() && skip_ioapic_setup) { | ||
1629 | pr_info("Not enabling interrupt remapping due to skipped IO-APIC setup\n"); | ||
1586 | return -1; | 1630 | return -1; |
1587 | } | 1631 | } |
1588 | |||
1589 | return irq_remapping_enable(); | ||
1590 | #endif | 1632 | #endif |
1591 | return -1; | 1633 | return irq_remapping_enable(); |
1592 | } | 1634 | } |
1593 | 1635 | ||
1594 | void __init enable_IR_x2apic(void) | 1636 | void __init enable_IR_x2apic(void) |
1595 | { | 1637 | { |
1596 | unsigned long flags; | 1638 | unsigned long flags; |
1597 | int ret, x2apic_enabled = 0; | 1639 | int ret, ir_stat; |
1598 | int hardware_init_ret; | ||
1599 | |||
1600 | /* Make sure irq_remap_ops are initialized */ | ||
1601 | setup_irq_remapping_ops(); | ||
1602 | 1640 | ||
1603 | hardware_init_ret = irq_remapping_prepare(); | 1641 | ir_stat = irq_remapping_prepare(); |
1604 | if (hardware_init_ret && !x2apic_supported()) | 1642 | if (ir_stat < 0 && !x2apic_supported()) |
1605 | return; | 1643 | return; |
1606 | 1644 | ||
1607 | ret = save_ioapic_entries(); | 1645 | ret = save_ioapic_entries(); |
@@ -1614,49 +1652,13 @@ void __init enable_IR_x2apic(void) | |||
1614 | legacy_pic->mask_all(); | 1652 | legacy_pic->mask_all(); |
1615 | mask_ioapic_entries(); | 1653 | mask_ioapic_entries(); |
1616 | 1654 | ||
1617 | if (x2apic_preenabled && nox2apic) | 1655 | /* If irq_remapping_prepare() succeded, try to enable it */ |
1618 | disable_x2apic(); | 1656 | if (ir_stat >= 0) |
1619 | 1657 | ir_stat = try_to_enable_IR(); | |
1620 | if (hardware_init_ret) | 1658 | /* ir_stat contains the remap mode or an error code */ |
1621 | ret = -1; | 1659 | try_to_enable_x2apic(ir_stat); |
1622 | else | ||
1623 | ret = enable_IR(); | ||
1624 | |||
1625 | if (!x2apic_supported()) | ||
1626 | goto skip_x2apic; | ||
1627 | 1660 | ||
1628 | if (ret < 0) { | 1661 | if (ir_stat < 0) |
1629 | /* IR is required if there is APIC ID > 255 even when running | ||
1630 | * under KVM | ||
1631 | */ | ||
1632 | if (max_physical_apicid > 255 || | ||
1633 | !hypervisor_x2apic_available()) { | ||
1634 | if (x2apic_preenabled) | ||
1635 | disable_x2apic(); | ||
1636 | goto skip_x2apic; | ||
1637 | } | ||
1638 | /* | ||
1639 | * without IR all CPUs can be addressed by IOAPIC/MSI | ||
1640 | * only in physical mode | ||
1641 | */ | ||
1642 | x2apic_force_phys(); | ||
1643 | } | ||
1644 | |||
1645 | if (ret == IRQ_REMAP_XAPIC_MODE) { | ||
1646 | pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n"); | ||
1647 | goto skip_x2apic; | ||
1648 | } | ||
1649 | |||
1650 | x2apic_enabled = 1; | ||
1651 | |||
1652 | if (x2apic_supported() && !x2apic_mode) { | ||
1653 | x2apic_mode = 1; | ||
1654 | enable_x2apic(); | ||
1655 | pr_info("Enabled x2apic\n"); | ||
1656 | } | ||
1657 | |||
1658 | skip_x2apic: | ||
1659 | if (ret < 0) /* IR enabling failed */ | ||
1660 | restore_ioapic_entries(); | 1662 | restore_ioapic_entries(); |
1661 | legacy_pic->restore_mask(); | 1663 | legacy_pic->restore_mask(); |
1662 | local_irq_restore(flags); | 1664 | local_irq_restore(flags); |
@@ -1847,82 +1849,8 @@ void __init register_lapic_address(unsigned long address) | |||
1847 | } | 1849 | } |
1848 | } | 1850 | } |
1849 | 1851 | ||
1850 | /* | ||
1851 | * This initializes the IO-APIC and APIC hardware if this is | ||
1852 | * a UP kernel. | ||
1853 | */ | ||
1854 | int apic_version[MAX_LOCAL_APIC]; | 1852 | int apic_version[MAX_LOCAL_APIC]; |
1855 | 1853 | ||
1856 | int __init APIC_init_uniprocessor(void) | ||
1857 | { | ||
1858 | if (disable_apic) { | ||
1859 | pr_info("Apic disabled\n"); | ||
1860 | return -1; | ||
1861 | } | ||
1862 | #ifdef CONFIG_X86_64 | ||
1863 | if (!cpu_has_apic) { | ||
1864 | disable_apic = 1; | ||
1865 | pr_info("Apic disabled by BIOS\n"); | ||
1866 | return -1; | ||
1867 | } | ||
1868 | #else | ||
1869 | if (!smp_found_config && !cpu_has_apic) | ||
1870 | return -1; | ||
1871 | |||
1872 | /* | ||
1873 | * Complain if the BIOS pretends there is one. | ||
1874 | */ | ||
1875 | if (!cpu_has_apic && | ||
1876 | APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { | ||
1877 | pr_err("BIOS bug, local APIC 0x%x not detected!...\n", | ||
1878 | boot_cpu_physical_apicid); | ||
1879 | return -1; | ||
1880 | } | ||
1881 | #endif | ||
1882 | |||
1883 | default_setup_apic_routing(); | ||
1884 | |||
1885 | verify_local_APIC(); | ||
1886 | connect_bsp_APIC(); | ||
1887 | |||
1888 | #ifdef CONFIG_X86_64 | ||
1889 | apic_write(APIC_ID, SET_APIC_ID(boot_cpu_physical_apicid)); | ||
1890 | #else | ||
1891 | /* | ||
1892 | * Hack: In case of kdump, after a crash, kernel might be booting | ||
1893 | * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid | ||
1894 | * might be zero if read from MP tables. Get it from LAPIC. | ||
1895 | */ | ||
1896 | # ifdef CONFIG_CRASH_DUMP | ||
1897 | boot_cpu_physical_apicid = read_apic_id(); | ||
1898 | # endif | ||
1899 | #endif | ||
1900 | physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); | ||
1901 | setup_local_APIC(); | ||
1902 | |||
1903 | #ifdef CONFIG_X86_IO_APIC | ||
1904 | /* | ||
1905 | * Now enable IO-APICs, actually call clear_IO_APIC | ||
1906 | * We need clear_IO_APIC before enabling error vector | ||
1907 | */ | ||
1908 | if (!skip_ioapic_setup && nr_ioapics) | ||
1909 | enable_IO_APIC(); | ||
1910 | #endif | ||
1911 | |||
1912 | bsp_end_local_APIC_setup(); | ||
1913 | |||
1914 | #ifdef CONFIG_X86_IO_APIC | ||
1915 | if (smp_found_config && !skip_ioapic_setup && nr_ioapics) | ||
1916 | setup_IO_APIC(); | ||
1917 | else { | ||
1918 | nr_ioapics = 0; | ||
1919 | } | ||
1920 | #endif | ||
1921 | |||
1922 | x86_init.timers.setup_percpu_clockev(); | ||
1923 | return 0; | ||
1924 | } | ||
1925 | |||
1926 | /* | 1854 | /* |
1927 | * Local APIC interrupts | 1855 | * Local APIC interrupts |
1928 | */ | 1856 | */ |
@@ -2027,7 +1955,7 @@ __visible void smp_trace_error_interrupt(struct pt_regs *regs) | |||
2027 | /** | 1955 | /** |
2028 | * connect_bsp_APIC - attach the APIC to the interrupt system | 1956 | * connect_bsp_APIC - attach the APIC to the interrupt system |
2029 | */ | 1957 | */ |
2030 | void __init connect_bsp_APIC(void) | 1958 | static void __init connect_bsp_APIC(void) |
2031 | { | 1959 | { |
2032 | #ifdef CONFIG_X86_32 | 1960 | #ifdef CONFIG_X86_32 |
2033 | if (pic_mode) { | 1961 | if (pic_mode) { |
@@ -2274,6 +2202,100 @@ void __init apic_set_eoi_write(void (*eoi_write)(u32 reg, u32 v)) | |||
2274 | } | 2202 | } |
2275 | } | 2203 | } |
2276 | 2204 | ||
2205 | static void __init apic_bsp_up_setup(void) | ||
2206 | { | ||
2207 | #ifdef CONFIG_X86_64 | ||
2208 | apic_write(APIC_ID, SET_APIC_ID(boot_cpu_physical_apicid)); | ||
2209 | #else | ||
2210 | /* | ||
2211 | * Hack: In case of kdump, after a crash, kernel might be booting | ||
2212 | * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid | ||
2213 | * might be zero if read from MP tables. Get it from LAPIC. | ||
2214 | */ | ||
2215 | # ifdef CONFIG_CRASH_DUMP | ||
2216 | boot_cpu_physical_apicid = read_apic_id(); | ||
2217 | # endif | ||
2218 | #endif | ||
2219 | physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); | ||
2220 | } | ||
2221 | |||
2222 | /** | ||
2223 | * apic_bsp_setup - Setup function for local apic and io-apic | ||
2224 | * @upmode: Force UP mode (for APIC_init_uniprocessor) | ||
2225 | * | ||
2226 | * Returns: | ||
2227 | * apic_id of BSP APIC | ||
2228 | */ | ||
2229 | int __init apic_bsp_setup(bool upmode) | ||
2230 | { | ||
2231 | int id; | ||
2232 | |||
2233 | connect_bsp_APIC(); | ||
2234 | if (upmode) | ||
2235 | apic_bsp_up_setup(); | ||
2236 | setup_local_APIC(); | ||
2237 | |||
2238 | if (x2apic_mode) | ||
2239 | id = apic_read(APIC_LDR); | ||
2240 | else | ||
2241 | id = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR)); | ||
2242 | |||
2243 | enable_IO_APIC(); | ||
2244 | end_local_APIC_setup(); | ||
2245 | irq_remap_enable_fault_handling(); | ||
2246 | setup_IO_APIC(); | ||
2247 | /* Setup local timer */ | ||
2248 | x86_init.timers.setup_percpu_clockev(); | ||
2249 | return id; | ||
2250 | } | ||
2251 | |||
2252 | /* | ||
2253 | * This initializes the IO-APIC and APIC hardware if this is | ||
2254 | * a UP kernel. | ||
2255 | */ | ||
2256 | int __init APIC_init_uniprocessor(void) | ||
2257 | { | ||
2258 | if (disable_apic) { | ||
2259 | pr_info("Apic disabled\n"); | ||
2260 | return -1; | ||
2261 | } | ||
2262 | #ifdef CONFIG_X86_64 | ||
2263 | if (!cpu_has_apic) { | ||
2264 | disable_apic = 1; | ||
2265 | pr_info("Apic disabled by BIOS\n"); | ||
2266 | return -1; | ||
2267 | } | ||
2268 | #else | ||
2269 | if (!smp_found_config && !cpu_has_apic) | ||
2270 | return -1; | ||
2271 | |||
2272 | /* | ||
2273 | * Complain if the BIOS pretends there is one. | ||
2274 | */ | ||
2275 | if (!cpu_has_apic && | ||
2276 | APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { | ||
2277 | pr_err("BIOS bug, local APIC 0x%x not detected!...\n", | ||
2278 | boot_cpu_physical_apicid); | ||
2279 | return -1; | ||
2280 | } | ||
2281 | #endif | ||
2282 | |||
2283 | if (!smp_found_config) | ||
2284 | disable_ioapic_support(); | ||
2285 | |||
2286 | default_setup_apic_routing(); | ||
2287 | verify_local_APIC(); | ||
2288 | apic_bsp_setup(true); | ||
2289 | return 0; | ||
2290 | } | ||
2291 | |||
2292 | #ifdef CONFIG_UP_LATE_INIT | ||
2293 | void __init up_late_init(void) | ||
2294 | { | ||
2295 | APIC_init_uniprocessor(); | ||
2296 | } | ||
2297 | #endif | ||
2298 | |||
2277 | /* | 2299 | /* |
2278 | * Power management | 2300 | * Power management |
2279 | */ | 2301 | */ |
@@ -2359,9 +2381,9 @@ static void lapic_resume(void) | |||
2359 | mask_ioapic_entries(); | 2381 | mask_ioapic_entries(); |
2360 | legacy_pic->mask_all(); | 2382 | legacy_pic->mask_all(); |
2361 | 2383 | ||
2362 | if (x2apic_mode) | 2384 | if (x2apic_mode) { |
2363 | enable_x2apic(); | 2385 | __x2apic_enable(); |
2364 | else { | 2386 | } else { |
2365 | /* | 2387 | /* |
2366 | * Make sure the APICBASE points to the right address | 2388 | * Make sure the APICBASE points to the right address |
2367 | * | 2389 | * |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 3f5f60406ab1..f4dc2462a1ac 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -1507,7 +1507,10 @@ void __init enable_IO_APIC(void) | |||
1507 | int i8259_apic, i8259_pin; | 1507 | int i8259_apic, i8259_pin; |
1508 | int apic, pin; | 1508 | int apic, pin; |
1509 | 1509 | ||
1510 | if (!nr_legacy_irqs()) | 1510 | if (skip_ioapic_setup) |
1511 | nr_ioapics = 0; | ||
1512 | |||
1513 | if (!nr_legacy_irqs() || !nr_ioapics) | ||
1511 | return; | 1514 | return; |
1512 | 1515 | ||
1513 | for_each_ioapic_pin(apic, pin) { | 1516 | for_each_ioapic_pin(apic, pin) { |
@@ -2295,7 +2298,7 @@ static inline void __init check_timer(void) | |||
2295 | } | 2298 | } |
2296 | local_irq_disable(); | 2299 | local_irq_disable(); |
2297 | apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n"); | 2300 | apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n"); |
2298 | if (x2apic_preenabled) | 2301 | if (apic_is_x2apic_enabled()) |
2299 | apic_printk(APIC_QUIET, KERN_INFO | 2302 | apic_printk(APIC_QUIET, KERN_INFO |
2300 | "Perhaps problem with the pre-enabled x2apic mode\n" | 2303 | "Perhaps problem with the pre-enabled x2apic mode\n" |
2301 | "Try booting with x2apic and interrupt-remapping disabled in the bios.\n"); | 2304 | "Try booting with x2apic and interrupt-remapping disabled in the bios.\n"); |
@@ -2373,9 +2376,9 @@ void __init setup_IO_APIC(void) | |||
2373 | { | 2376 | { |
2374 | int ioapic; | 2377 | int ioapic; |
2375 | 2378 | ||
2376 | /* | 2379 | if (skip_ioapic_setup || !nr_ioapics) |
2377 | * calling enable_IO_APIC() is moved to setup_local_APIC for BP | 2380 | return; |
2378 | */ | 2381 | |
2379 | io_apic_irqs = nr_legacy_irqs() ? ~PIC_IRQS : ~0UL; | 2382 | io_apic_irqs = nr_legacy_irqs() ? ~PIC_IRQS : ~0UL; |
2380 | 2383 | ||
2381 | apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n"); | 2384 | apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n"); |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index c6049650c093..cb5692551b98 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -1332,7 +1332,7 @@ void cpu_init(void) | |||
1332 | barrier(); | 1332 | barrier(); |
1333 | 1333 | ||
1334 | x86_configure_nx(); | 1334 | x86_configure_nx(); |
1335 | enable_x2apic(); | 1335 | x2apic_setup(); |
1336 | 1336 | ||
1337 | /* | 1337 | /* |
1338 | * set up and load the per-CPU TSS | 1338 | * set up and load the per-CPU TSS |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 6d7022c683e3..febc6aabc72e 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -73,7 +73,6 @@ | |||
73 | #include <asm/setup.h> | 73 | #include <asm/setup.h> |
74 | #include <asm/uv/uv.h> | 74 | #include <asm/uv/uv.h> |
75 | #include <linux/mc146818rtc.h> | 75 | #include <linux/mc146818rtc.h> |
76 | #include <asm/smpboot_hooks.h> | ||
77 | #include <asm/i8259.h> | 76 | #include <asm/i8259.h> |
78 | #include <asm/realmode.h> | 77 | #include <asm/realmode.h> |
79 | #include <asm/misc.h> | 78 | #include <asm/misc.h> |
@@ -104,6 +103,43 @@ EXPORT_PER_CPU_SYMBOL(cpu_info); | |||
104 | 103 | ||
105 | atomic_t init_deasserted; | 104 | atomic_t init_deasserted; |
106 | 105 | ||
106 | static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip) | ||
107 | { | ||
108 | unsigned long flags; | ||
109 | |||
110 | spin_lock_irqsave(&rtc_lock, flags); | ||
111 | CMOS_WRITE(0xa, 0xf); | ||
112 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
113 | local_flush_tlb(); | ||
114 | pr_debug("1.\n"); | ||
115 | *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) = | ||
116 | start_eip >> 4; | ||
117 | pr_debug("2.\n"); | ||
118 | *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = | ||
119 | start_eip & 0xf; | ||
120 | pr_debug("3.\n"); | ||
121 | } | ||
122 | |||
123 | static inline void smpboot_restore_warm_reset_vector(void) | ||
124 | { | ||
125 | unsigned long flags; | ||
126 | |||
127 | /* | ||
128 | * Install writable page 0 entry to set BIOS data area. | ||
129 | */ | ||
130 | local_flush_tlb(); | ||
131 | |||
132 | /* | ||
133 | * Paranoid: Set warm reset code and vector here back | ||
134 | * to default values. | ||
135 | */ | ||
136 | spin_lock_irqsave(&rtc_lock, flags); | ||
137 | CMOS_WRITE(0, 0xf); | ||
138 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
139 | |||
140 | *((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0; | ||
141 | } | ||
142 | |||
107 | /* | 143 | /* |
108 | * Report back to the Boot Processor during boot time or to the caller processor | 144 | * Report back to the Boot Processor during boot time or to the caller processor |
109 | * during CPU online. | 145 | * during CPU online. |
@@ -136,8 +172,7 @@ static void smp_callin(void) | |||
136 | * CPU, first the APIC. (this is probably redundant on most | 172 | * CPU, first the APIC. (this is probably redundant on most |
137 | * boards) | 173 | * boards) |
138 | */ | 174 | */ |
139 | setup_local_APIC(); | 175 | apic_ap_setup(); |
140 | end_local_APIC_setup(); | ||
141 | 176 | ||
142 | /* | 177 | /* |
143 | * Need to setup vector mappings before we enable interrupts. | 178 | * Need to setup vector mappings before we enable interrupts. |
@@ -955,9 +990,12 @@ void arch_disable_smp_support(void) | |||
955 | */ | 990 | */ |
956 | static __init void disable_smp(void) | 991 | static __init void disable_smp(void) |
957 | { | 992 | { |
993 | pr_info("SMP disabled\n"); | ||
994 | |||
995 | disable_ioapic_support(); | ||
996 | |||
958 | init_cpu_present(cpumask_of(0)); | 997 | init_cpu_present(cpumask_of(0)); |
959 | init_cpu_possible(cpumask_of(0)); | 998 | init_cpu_possible(cpumask_of(0)); |
960 | smpboot_clear_io_apic_irqs(); | ||
961 | 999 | ||
962 | if (smp_found_config) | 1000 | if (smp_found_config) |
963 | physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); | 1001 | physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); |
@@ -967,6 +1005,13 @@ static __init void disable_smp(void) | |||
967 | cpumask_set_cpu(0, cpu_core_mask(0)); | 1005 | cpumask_set_cpu(0, cpu_core_mask(0)); |
968 | } | 1006 | } |
969 | 1007 | ||
1008 | enum { | ||
1009 | SMP_OK, | ||
1010 | SMP_NO_CONFIG, | ||
1011 | SMP_NO_APIC, | ||
1012 | SMP_FORCE_UP, | ||
1013 | }; | ||
1014 | |||
970 | /* | 1015 | /* |
971 | * Various sanity checks. | 1016 | * Various sanity checks. |
972 | */ | 1017 | */ |
@@ -1014,10 +1059,7 @@ static int __init smp_sanity_check(unsigned max_cpus) | |||
1014 | if (!smp_found_config && !acpi_lapic) { | 1059 | if (!smp_found_config && !acpi_lapic) { |
1015 | preempt_enable(); | 1060 | preempt_enable(); |
1016 | pr_notice("SMP motherboard not detected\n"); | 1061 | pr_notice("SMP motherboard not detected\n"); |
1017 | disable_smp(); | 1062 | return SMP_NO_CONFIG; |
1018 | if (APIC_init_uniprocessor()) | ||
1019 | pr_notice("Local APIC not detected. Using dummy APIC emulation.\n"); | ||
1020 | return -1; | ||
1021 | } | 1063 | } |
1022 | 1064 | ||
1023 | /* | 1065 | /* |
@@ -1041,9 +1083,7 @@ static int __init smp_sanity_check(unsigned max_cpus) | |||
1041 | boot_cpu_physical_apicid); | 1083 | boot_cpu_physical_apicid); |
1042 | pr_err("... forcing use of dummy APIC emulation (tell your hw vendor)\n"); | 1084 | pr_err("... forcing use of dummy APIC emulation (tell your hw vendor)\n"); |
1043 | } | 1085 | } |
1044 | smpboot_clear_io_apic(); | 1086 | return SMP_NO_APIC; |
1045 | disable_ioapic_support(); | ||
1046 | return -1; | ||
1047 | } | 1087 | } |
1048 | 1088 | ||
1049 | verify_local_APIC(); | 1089 | verify_local_APIC(); |
@@ -1053,15 +1093,10 @@ static int __init smp_sanity_check(unsigned max_cpus) | |||
1053 | */ | 1093 | */ |
1054 | if (!max_cpus) { | 1094 | if (!max_cpus) { |
1055 | pr_info("SMP mode deactivated\n"); | 1095 | pr_info("SMP mode deactivated\n"); |
1056 | smpboot_clear_io_apic(); | 1096 | return SMP_FORCE_UP; |
1057 | |||
1058 | connect_bsp_APIC(); | ||
1059 | setup_local_APIC(); | ||
1060 | bsp_end_local_APIC_setup(); | ||
1061 | return -1; | ||
1062 | } | 1097 | } |
1063 | 1098 | ||
1064 | return 0; | 1099 | return SMP_OK; |
1065 | } | 1100 | } |
1066 | 1101 | ||
1067 | static void __init smp_cpu_index_default(void) | 1102 | static void __init smp_cpu_index_default(void) |
@@ -1101,10 +1136,21 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) | |||
1101 | } | 1136 | } |
1102 | set_cpu_sibling_map(0); | 1137 | set_cpu_sibling_map(0); |
1103 | 1138 | ||
1104 | if (smp_sanity_check(max_cpus) < 0) { | 1139 | switch (smp_sanity_check(max_cpus)) { |
1105 | pr_info("SMP disabled\n"); | 1140 | case SMP_NO_CONFIG: |
1106 | disable_smp(); | 1141 | disable_smp(); |
1142 | if (APIC_init_uniprocessor()) | ||
1143 | pr_notice("Local APIC not detected. Using dummy APIC emulation.\n"); | ||
1107 | return; | 1144 | return; |
1145 | case SMP_NO_APIC: | ||
1146 | disable_smp(); | ||
1147 | return; | ||
1148 | case SMP_FORCE_UP: | ||
1149 | disable_smp(); | ||
1150 | apic_bsp_setup(false); | ||
1151 | return; | ||
1152 | case SMP_OK: | ||
1153 | break; | ||
1108 | } | 1154 | } |
1109 | 1155 | ||
1110 | default_setup_apic_routing(); | 1156 | default_setup_apic_routing(); |
@@ -1115,33 +1161,10 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) | |||
1115 | /* Or can we switch back to PIC here? */ | 1161 | /* Or can we switch back to PIC here? */ |
1116 | } | 1162 | } |
1117 | 1163 | ||
1118 | connect_bsp_APIC(); | 1164 | cpu0_logical_apicid = apic_bsp_setup(false); |
1119 | |||
1120 | /* | ||
1121 | * Switch from PIC to APIC mode. | ||
1122 | */ | ||
1123 | setup_local_APIC(); | ||
1124 | |||
1125 | if (x2apic_mode) | ||
1126 | cpu0_logical_apicid = apic_read(APIC_LDR); | ||
1127 | else | ||
1128 | cpu0_logical_apicid = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR)); | ||
1129 | |||
1130 | /* | ||
1131 | * Enable IO APIC before setting up error vector | ||
1132 | */ | ||
1133 | if (!skip_ioapic_setup && nr_ioapics) | ||
1134 | enable_IO_APIC(); | ||
1135 | |||
1136 | bsp_end_local_APIC_setup(); | ||
1137 | smpboot_setup_io_apic(); | ||
1138 | /* | ||
1139 | * Set up local APIC timer on boot CPU. | ||
1140 | */ | ||
1141 | 1165 | ||
1142 | pr_info("CPU%d: ", 0); | 1166 | pr_info("CPU%d: ", 0); |
1143 | print_cpu_info(&cpu_data(0)); | 1167 | print_cpu_info(&cpu_data(0)); |
1144 | x86_init.timers.setup_percpu_clockev(); | ||
1145 | 1168 | ||
1146 | if (is_uv_system()) | 1169 | if (is_uv_system()) |
1147 | uv_system_init(); | 1170 | uv_system_init(); |
@@ -1177,9 +1200,7 @@ void __init native_smp_cpus_done(unsigned int max_cpus) | |||
1177 | 1200 | ||
1178 | nmi_selftest(); | 1201 | nmi_selftest(); |
1179 | impress_friends(); | 1202 | impress_friends(); |
1180 | #ifdef CONFIG_X86_IO_APIC | ||
1181 | setup_ioapic_dest(); | 1203 | setup_ioapic_dest(); |
1182 | #endif | ||
1183 | mtrr_aps_init(); | 1204 | mtrr_aps_init(); |
1184 | } | 1205 | } |
1185 | 1206 | ||