diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-06-11 11:55:42 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-06-11 11:55:42 -0400 |
commit | 940010c5a314a7bd9b498593bc6ba1718ac5aec5 (patch) | |
tree | d141e08ced08c40c6a8e3ab2cdecde5ff14e560f /arch/x86/kernel/apic/apic.c | |
parent | 8dc8e5e8bc0ce00b0f656bf972f67cd8a72759e5 (diff) | |
parent | 991ec02cdca33b03a132a0cacfe6f0aa0be9aa8d (diff) |
Merge branch 'linus' into perfcounters/core
Conflicts:
arch/x86/kernel/irqinit.c
arch/x86/kernel/irqinit_64.c
arch/x86/kernel/traps.c
arch/x86/mm/fault.c
include/linux/sched.h
kernel/exit.c
Diffstat (limited to 'arch/x86/kernel/apic/apic.c')
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 311 |
1 files changed, 191 insertions, 120 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 60df2efd7c8..076d3881f3d 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -100,6 +100,29 @@ early_param("lapic", parse_lapic); | |||
100 | /* Local APIC was disabled by the BIOS and enabled by the kernel */ | 100 | /* Local APIC was disabled by the BIOS and enabled by the kernel */ |
101 | static int enabled_via_apicbase; | 101 | static int enabled_via_apicbase; |
102 | 102 | ||
103 | /* | ||
104 | * Handle interrupt mode configuration register (IMCR). | ||
105 | * This register controls whether the interrupt signals | ||
106 | * that reach the BSP come from the master PIC or from the | ||
107 | * local APIC. Before entering Symmetric I/O Mode, either | ||
108 | * the BIOS or the operating system must switch out of | ||
109 | * PIC Mode by changing the IMCR. | ||
110 | */ | ||
111 | static inline void imcr_pic_to_apic(void) | ||
112 | { | ||
113 | /* select IMCR register */ | ||
114 | outb(0x70, 0x22); | ||
115 | /* NMI and 8259 INTR go through APIC */ | ||
116 | outb(0x01, 0x23); | ||
117 | } | ||
118 | |||
119 | static inline void imcr_apic_to_pic(void) | ||
120 | { | ||
121 | /* select IMCR register */ | ||
122 | outb(0x70, 0x22); | ||
123 | /* NMI and 8259 INTR go directly to BSP */ | ||
124 | outb(0x00, 0x23); | ||
125 | } | ||
103 | #endif | 126 | #endif |
104 | 127 | ||
105 | #ifdef CONFIG_X86_64 | 128 | #ifdef CONFIG_X86_64 |
@@ -113,13 +136,19 @@ static __init int setup_apicpmtimer(char *s) | |||
113 | __setup("apicpmtimer", setup_apicpmtimer); | 136 | __setup("apicpmtimer", setup_apicpmtimer); |
114 | #endif | 137 | #endif |
115 | 138 | ||
139 | int x2apic_mode; | ||
116 | #ifdef CONFIG_X86_X2APIC | 140 | #ifdef CONFIG_X86_X2APIC |
117 | int x2apic; | ||
118 | /* x2apic enabled before OS handover */ | 141 | /* x2apic enabled before OS handover */ |
119 | static int x2apic_preenabled; | 142 | static int x2apic_preenabled; |
120 | static int disable_x2apic; | 143 | static int disable_x2apic; |
121 | static __init int setup_nox2apic(char *str) | 144 | static __init int setup_nox2apic(char *str) |
122 | { | 145 | { |
146 | if (x2apic_enabled()) { | ||
147 | pr_warning("Bios already enabled x2apic, " | ||
148 | "can't enforce nox2apic"); | ||
149 | return 0; | ||
150 | } | ||
151 | |||
123 | disable_x2apic = 1; | 152 | disable_x2apic = 1; |
124 | setup_clear_cpu_cap(X86_FEATURE_X2APIC); | 153 | setup_clear_cpu_cap(X86_FEATURE_X2APIC); |
125 | return 0; | 154 | return 0; |
@@ -211,6 +240,31 @@ static int modern_apic(void) | |||
211 | return lapic_get_version() >= 0x14; | 240 | return lapic_get_version() >= 0x14; |
212 | } | 241 | } |
213 | 242 | ||
243 | /* | ||
244 | * bare function to substitute write operation | ||
245 | * and it's _that_ fast :) | ||
246 | */ | ||
247 | static void native_apic_write_dummy(u32 reg, u32 v) | ||
248 | { | ||
249 | WARN_ON_ONCE((cpu_has_apic || !disable_apic)); | ||
250 | } | ||
251 | |||
252 | static u32 native_apic_read_dummy(u32 reg) | ||
253 | { | ||
254 | WARN_ON_ONCE((cpu_has_apic && !disable_apic)); | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | /* | ||
259 | * right after this call apic->write/read doesn't do anything | ||
260 | * note that there is no restore operation it works one way | ||
261 | */ | ||
262 | void apic_disable(void) | ||
263 | { | ||
264 | apic->read = native_apic_read_dummy; | ||
265 | apic->write = native_apic_write_dummy; | ||
266 | } | ||
267 | |||
214 | void native_apic_wait_icr_idle(void) | 268 | void native_apic_wait_icr_idle(void) |
215 | { | 269 | { |
216 | while (apic_read(APIC_ICR) & APIC_ICR_BUSY) | 270 | while (apic_read(APIC_ICR) & APIC_ICR_BUSY) |
@@ -350,7 +404,7 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) | |||
350 | 404 | ||
351 | static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask) | 405 | static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask) |
352 | { | 406 | { |
353 | unsigned long reg = (lvt_off << 4) + APIC_EILVT0; | 407 | unsigned long reg = (lvt_off << 4) + APIC_EILVTn(0); |
354 | unsigned int v = (mask << 16) | (msg_type << 8) | vector; | 408 | unsigned int v = (mask << 16) | (msg_type << 8) | vector; |
355 | 409 | ||
356 | apic_write(reg, v); | 410 | apic_write(reg, v); |
@@ -817,7 +871,7 @@ void clear_local_APIC(void) | |||
817 | u32 v; | 871 | u32 v; |
818 | 872 | ||
819 | /* APIC hasn't been mapped yet */ | 873 | /* APIC hasn't been mapped yet */ |
820 | if (!x2apic && !apic_phys) | 874 | if (!x2apic_mode && !apic_phys) |
821 | return; | 875 | return; |
822 | 876 | ||
823 | maxlvt = lapic_get_maxlvt(); | 877 | maxlvt = lapic_get_maxlvt(); |
@@ -1290,7 +1344,7 @@ void check_x2apic(void) | |||
1290 | { | 1344 | { |
1291 | if (x2apic_enabled()) { | 1345 | if (x2apic_enabled()) { |
1292 | pr_info("x2apic enabled by BIOS, switching to x2apic ops\n"); | 1346 | pr_info("x2apic enabled by BIOS, switching to x2apic ops\n"); |
1293 | x2apic_preenabled = x2apic = 1; | 1347 | x2apic_preenabled = x2apic_mode = 1; |
1294 | } | 1348 | } |
1295 | } | 1349 | } |
1296 | 1350 | ||
@@ -1298,7 +1352,7 @@ void enable_x2apic(void) | |||
1298 | { | 1352 | { |
1299 | int msr, msr2; | 1353 | int msr, msr2; |
1300 | 1354 | ||
1301 | if (!x2apic) | 1355 | if (!x2apic_mode) |
1302 | return; | 1356 | return; |
1303 | 1357 | ||
1304 | rdmsr(MSR_IA32_APICBASE, msr, msr2); | 1358 | rdmsr(MSR_IA32_APICBASE, msr, msr2); |
@@ -1307,6 +1361,7 @@ void enable_x2apic(void) | |||
1307 | wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0); | 1361 | wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0); |
1308 | } | 1362 | } |
1309 | } | 1363 | } |
1364 | #endif /* CONFIG_X86_X2APIC */ | ||
1310 | 1365 | ||
1311 | void __init enable_IR_x2apic(void) | 1366 | void __init enable_IR_x2apic(void) |
1312 | { | 1367 | { |
@@ -1315,32 +1370,21 @@ void __init enable_IR_x2apic(void) | |||
1315 | unsigned long flags; | 1370 | unsigned long flags; |
1316 | struct IO_APIC_route_entry **ioapic_entries = NULL; | 1371 | struct IO_APIC_route_entry **ioapic_entries = NULL; |
1317 | 1372 | ||
1318 | if (!cpu_has_x2apic) | 1373 | ret = dmar_table_init(); |
1319 | return; | 1374 | if (ret) { |
1320 | 1375 | pr_debug("dmar_table_init() failed with %d:\n", ret); | |
1321 | if (!x2apic_preenabled && disable_x2apic) { | 1376 | goto ir_failed; |
1322 | pr_info("Skipped enabling x2apic and Interrupt-remapping " | ||
1323 | "because of nox2apic\n"); | ||
1324 | return; | ||
1325 | } | 1377 | } |
1326 | 1378 | ||
1327 | if (x2apic_preenabled && disable_x2apic) | 1379 | if (!intr_remapping_supported()) { |
1328 | panic("Bios already enabled x2apic, can't enforce nox2apic"); | 1380 | pr_debug("intr-remapping not supported\n"); |
1329 | 1381 | goto ir_failed; | |
1330 | if (!x2apic_preenabled && skip_ioapic_setup) { | ||
1331 | pr_info("Skipped enabling x2apic and Interrupt-remapping " | ||
1332 | "because of skipping io-apic setup\n"); | ||
1333 | return; | ||
1334 | } | 1382 | } |
1335 | 1383 | ||
1336 | ret = dmar_table_init(); | ||
1337 | if (ret) { | ||
1338 | pr_info("dmar_table_init() failed with %d:\n", ret); | ||
1339 | 1384 | ||
1340 | if (x2apic_preenabled) | 1385 | if (!x2apic_preenabled && skip_ioapic_setup) { |
1341 | panic("x2apic enabled by bios. But IR enabling failed"); | 1386 | pr_info("Skipped enabling intr-remap because of skipping " |
1342 | else | 1387 | "io-apic setup\n"); |
1343 | pr_info("Not enabling x2apic,Intr-remapping\n"); | ||
1344 | return; | 1388 | return; |
1345 | } | 1389 | } |
1346 | 1390 | ||
@@ -1360,19 +1404,16 @@ void __init enable_IR_x2apic(void) | |||
1360 | mask_IO_APIC_setup(ioapic_entries); | 1404 | mask_IO_APIC_setup(ioapic_entries); |
1361 | mask_8259A(); | 1405 | mask_8259A(); |
1362 | 1406 | ||
1363 | ret = enable_intr_remapping(EIM_32BIT_APIC_ID); | 1407 | ret = enable_intr_remapping(x2apic_supported()); |
1364 | |||
1365 | if (ret && x2apic_preenabled) { | ||
1366 | local_irq_restore(flags); | ||
1367 | panic("x2apic enabled by bios. But IR enabling failed"); | ||
1368 | } | ||
1369 | |||
1370 | if (ret) | 1408 | if (ret) |
1371 | goto end_restore; | 1409 | goto end_restore; |
1372 | 1410 | ||
1373 | if (!x2apic) { | 1411 | pr_info("Enabled Interrupt-remapping\n"); |
1374 | x2apic = 1; | 1412 | |
1413 | if (x2apic_supported() && !x2apic_mode) { | ||
1414 | x2apic_mode = 1; | ||
1375 | enable_x2apic(); | 1415 | enable_x2apic(); |
1416 | pr_info("Enabled x2apic\n"); | ||
1376 | } | 1417 | } |
1377 | 1418 | ||
1378 | end_restore: | 1419 | end_restore: |
@@ -1381,37 +1422,34 @@ end_restore: | |||
1381 | * IR enabling failed | 1422 | * IR enabling failed |
1382 | */ | 1423 | */ |
1383 | restore_IO_APIC_setup(ioapic_entries); | 1424 | restore_IO_APIC_setup(ioapic_entries); |
1384 | else | ||
1385 | reinit_intr_remapped_IO_APIC(x2apic_preenabled, ioapic_entries); | ||
1386 | 1425 | ||
1387 | unmask_8259A(); | 1426 | unmask_8259A(); |
1388 | local_irq_restore(flags); | 1427 | local_irq_restore(flags); |
1389 | 1428 | ||
1390 | end: | 1429 | end: |
1391 | if (!ret) { | ||
1392 | if (!x2apic_preenabled) | ||
1393 | pr_info("Enabled x2apic and interrupt-remapping\n"); | ||
1394 | else | ||
1395 | pr_info("Enabled Interrupt-remapping\n"); | ||
1396 | } else | ||
1397 | pr_err("Failed to enable Interrupt-remapping and x2apic\n"); | ||
1398 | if (ioapic_entries) | 1430 | if (ioapic_entries) |
1399 | free_ioapic_entries(ioapic_entries); | 1431 | free_ioapic_entries(ioapic_entries); |
1432 | |||
1433 | if (!ret) | ||
1434 | return; | ||
1435 | |||
1436 | ir_failed: | ||
1437 | if (x2apic_preenabled) | ||
1438 | panic("x2apic enabled by bios. But IR enabling failed"); | ||
1439 | else if (cpu_has_x2apic) | ||
1440 | pr_info("Not enabling x2apic,Intr-remapping\n"); | ||
1400 | #else | 1441 | #else |
1401 | if (!cpu_has_x2apic) | 1442 | if (!cpu_has_x2apic) |
1402 | return; | 1443 | return; |
1403 | 1444 | ||
1404 | if (x2apic_preenabled) | 1445 | if (x2apic_preenabled) |
1405 | panic("x2apic enabled prior OS handover," | 1446 | panic("x2apic enabled prior OS handover," |
1406 | " enable CONFIG_INTR_REMAP"); | 1447 | " enable CONFIG_X86_X2APIC, CONFIG_INTR_REMAP"); |
1407 | |||
1408 | pr_info("Enable CONFIG_INTR_REMAP for enabling intr-remapping " | ||
1409 | " and x2apic\n"); | ||
1410 | #endif | 1448 | #endif |
1411 | 1449 | ||
1412 | return; | 1450 | return; |
1413 | } | 1451 | } |
1414 | #endif /* CONFIG_X86_X2APIC */ | 1452 | |
1415 | 1453 | ||
1416 | #ifdef CONFIG_X86_64 | 1454 | #ifdef CONFIG_X86_64 |
1417 | /* | 1455 | /* |
@@ -1428,7 +1466,6 @@ static int __init detect_init_APIC(void) | |||
1428 | } | 1466 | } |
1429 | 1467 | ||
1430 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; | 1468 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; |
1431 | boot_cpu_physical_apicid = 0; | ||
1432 | return 0; | 1469 | return 0; |
1433 | } | 1470 | } |
1434 | #else | 1471 | #else |
@@ -1542,32 +1579,49 @@ void __init early_init_lapic_mapping(void) | |||
1542 | */ | 1579 | */ |
1543 | void __init init_apic_mappings(void) | 1580 | void __init init_apic_mappings(void) |
1544 | { | 1581 | { |
1545 | if (x2apic) { | 1582 | unsigned int new_apicid; |
1583 | |||
1584 | if (x2apic_mode) { | ||
1546 | boot_cpu_physical_apicid = read_apic_id(); | 1585 | boot_cpu_physical_apicid = read_apic_id(); |
1547 | return; | 1586 | return; |
1548 | } | 1587 | } |
1549 | 1588 | ||
1550 | /* | 1589 | /* If no local APIC can be found return early */ |
1551 | * If no local APIC can be found then set up a fake all | ||
1552 | * zeroes page to simulate the local APIC and another | ||
1553 | * one for the IO-APIC. | ||
1554 | */ | ||
1555 | if (!smp_found_config && detect_init_APIC()) { | 1590 | if (!smp_found_config && detect_init_APIC()) { |
1556 | apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); | 1591 | /* lets NOP'ify apic operations */ |
1557 | apic_phys = __pa(apic_phys); | 1592 | pr_info("APIC: disable apic facility\n"); |
1558 | } else | 1593 | apic_disable(); |
1594 | } else { | ||
1559 | apic_phys = mp_lapic_addr; | 1595 | apic_phys = mp_lapic_addr; |
1560 | 1596 | ||
1561 | set_fixmap_nocache(FIX_APIC_BASE, apic_phys); | 1597 | /* |
1562 | apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n", | 1598 | * acpi lapic path already maps that address in |
1563 | APIC_BASE, apic_phys); | 1599 | * acpi_register_lapic_address() |
1600 | */ | ||
1601 | if (!acpi_lapic) | ||
1602 | set_fixmap_nocache(FIX_APIC_BASE, apic_phys); | ||
1603 | |||
1604 | apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n", | ||
1605 | APIC_BASE, apic_phys); | ||
1606 | } | ||
1564 | 1607 | ||
1565 | /* | 1608 | /* |
1566 | * Fetch the APIC ID of the BSP in case we have a | 1609 | * Fetch the APIC ID of the BSP in case we have a |
1567 | * default configuration (or the MP table is broken). | 1610 | * default configuration (or the MP table is broken). |
1568 | */ | 1611 | */ |
1569 | if (boot_cpu_physical_apicid == -1U) | 1612 | new_apicid = read_apic_id(); |
1570 | boot_cpu_physical_apicid = read_apic_id(); | 1613 | if (boot_cpu_physical_apicid != new_apicid) { |
1614 | boot_cpu_physical_apicid = new_apicid; | ||
1615 | /* | ||
1616 | * yeah -- we lie about apic_version | ||
1617 | * in case if apic was disabled via boot option | ||
1618 | * but it's not a problem for SMP compiled kernel | ||
1619 | * since smp_sanity_check is prepared for such a case | ||
1620 | * and disable smp mode | ||
1621 | */ | ||
1622 | apic_version[new_apicid] = | ||
1623 | GET_APIC_VERSION(apic_read(APIC_LVR)); | ||
1624 | } | ||
1571 | } | 1625 | } |
1572 | 1626 | ||
1573 | /* | 1627 | /* |
@@ -1736,8 +1790,7 @@ void __init connect_bsp_APIC(void) | |||
1736 | */ | 1790 | */ |
1737 | apic_printk(APIC_VERBOSE, "leaving PIC mode, " | 1791 | apic_printk(APIC_VERBOSE, "leaving PIC mode, " |
1738 | "enabling APIC mode.\n"); | 1792 | "enabling APIC mode.\n"); |
1739 | outb(0x70, 0x22); | 1793 | imcr_pic_to_apic(); |
1740 | outb(0x01, 0x23); | ||
1741 | } | 1794 | } |
1742 | #endif | 1795 | #endif |
1743 | if (apic->enable_apic_mode) | 1796 | if (apic->enable_apic_mode) |
@@ -1765,8 +1818,7 @@ void disconnect_bsp_APIC(int virt_wire_setup) | |||
1765 | */ | 1818 | */ |
1766 | apic_printk(APIC_VERBOSE, "disabling APIC mode, " | 1819 | apic_printk(APIC_VERBOSE, "disabling APIC mode, " |
1767 | "entering PIC mode.\n"); | 1820 | "entering PIC mode.\n"); |
1768 | outb(0x70, 0x22); | 1821 | imcr_apic_to_pic(); |
1769 | outb(0x00, 0x23); | ||
1770 | return; | 1822 | return; |
1771 | } | 1823 | } |
1772 | #endif | 1824 | #endif |
@@ -1972,10 +2024,10 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state) | |||
1972 | 2024 | ||
1973 | local_irq_save(flags); | 2025 | local_irq_save(flags); |
1974 | disable_local_APIC(); | 2026 | disable_local_APIC(); |
1975 | #ifdef CONFIG_INTR_REMAP | 2027 | |
1976 | if (intr_remapping_enabled) | 2028 | if (intr_remapping_enabled) |
1977 | disable_intr_remapping(); | 2029 | disable_intr_remapping(); |
1978 | #endif | 2030 | |
1979 | local_irq_restore(flags); | 2031 | local_irq_restore(flags); |
1980 | return 0; | 2032 | return 0; |
1981 | } | 2033 | } |
@@ -1985,42 +2037,34 @@ static int lapic_resume(struct sys_device *dev) | |||
1985 | unsigned int l, h; | 2037 | unsigned int l, h; |
1986 | unsigned long flags; | 2038 | unsigned long flags; |
1987 | int maxlvt; | 2039 | int maxlvt; |
1988 | 2040 | int ret = 0; | |
1989 | #ifdef CONFIG_INTR_REMAP | ||
1990 | int ret; | ||
1991 | struct IO_APIC_route_entry **ioapic_entries = NULL; | 2041 | struct IO_APIC_route_entry **ioapic_entries = NULL; |
1992 | 2042 | ||
1993 | if (!apic_pm_state.active) | 2043 | if (!apic_pm_state.active) |
1994 | return 0; | 2044 | return 0; |
1995 | 2045 | ||
1996 | local_irq_save(flags); | 2046 | local_irq_save(flags); |
1997 | if (x2apic) { | 2047 | if (intr_remapping_enabled) { |
1998 | ioapic_entries = alloc_ioapic_entries(); | 2048 | ioapic_entries = alloc_ioapic_entries(); |
1999 | if (!ioapic_entries) { | 2049 | if (!ioapic_entries) { |
2000 | WARN(1, "Alloc ioapic_entries in lapic resume failed."); | 2050 | WARN(1, "Alloc ioapic_entries in lapic resume failed."); |
2001 | return -ENOMEM; | 2051 | ret = -ENOMEM; |
2052 | goto restore; | ||
2002 | } | 2053 | } |
2003 | 2054 | ||
2004 | ret = save_IO_APIC_setup(ioapic_entries); | 2055 | ret = save_IO_APIC_setup(ioapic_entries); |
2005 | if (ret) { | 2056 | if (ret) { |
2006 | WARN(1, "Saving IO-APIC state failed: %d\n", ret); | 2057 | WARN(1, "Saving IO-APIC state failed: %d\n", ret); |
2007 | free_ioapic_entries(ioapic_entries); | 2058 | free_ioapic_entries(ioapic_entries); |
2008 | return ret; | 2059 | goto restore; |
2009 | } | 2060 | } |
2010 | 2061 | ||
2011 | mask_IO_APIC_setup(ioapic_entries); | 2062 | mask_IO_APIC_setup(ioapic_entries); |
2012 | mask_8259A(); | 2063 | mask_8259A(); |
2013 | enable_x2apic(); | ||
2014 | } | 2064 | } |
2015 | #else | ||
2016 | if (!apic_pm_state.active) | ||
2017 | return 0; | ||
2018 | 2065 | ||
2019 | local_irq_save(flags); | 2066 | if (x2apic_mode) |
2020 | if (x2apic) | ||
2021 | enable_x2apic(); | 2067 | enable_x2apic(); |
2022 | #endif | ||
2023 | |||
2024 | else { | 2068 | else { |
2025 | /* | 2069 | /* |
2026 | * Make sure the APICBASE points to the right address | 2070 | * Make sure the APICBASE points to the right address |
@@ -2058,21 +2102,16 @@ static int lapic_resume(struct sys_device *dev) | |||
2058 | apic_write(APIC_ESR, 0); | 2102 | apic_write(APIC_ESR, 0); |
2059 | apic_read(APIC_ESR); | 2103 | apic_read(APIC_ESR); |
2060 | 2104 | ||
2061 | #ifdef CONFIG_INTR_REMAP | 2105 | if (intr_remapping_enabled) { |
2062 | if (intr_remapping_enabled) | 2106 | reenable_intr_remapping(x2apic_mode); |
2063 | reenable_intr_remapping(EIM_32BIT_APIC_ID); | ||
2064 | |||
2065 | if (x2apic) { | ||
2066 | unmask_8259A(); | 2107 | unmask_8259A(); |
2067 | restore_IO_APIC_setup(ioapic_entries); | 2108 | restore_IO_APIC_setup(ioapic_entries); |
2068 | free_ioapic_entries(ioapic_entries); | 2109 | free_ioapic_entries(ioapic_entries); |
2069 | } | 2110 | } |
2070 | #endif | 2111 | restore: |
2071 | |||
2072 | local_irq_restore(flags); | 2112 | local_irq_restore(flags); |
2073 | 2113 | ||
2074 | 2114 | return ret; | |
2075 | return 0; | ||
2076 | } | 2115 | } |
2077 | 2116 | ||
2078 | /* | 2117 | /* |
@@ -2120,31 +2159,14 @@ static void apic_pm_activate(void) { } | |||
2120 | #endif /* CONFIG_PM */ | 2159 | #endif /* CONFIG_PM */ |
2121 | 2160 | ||
2122 | #ifdef CONFIG_X86_64 | 2161 | #ifdef CONFIG_X86_64 |
2123 | /* | 2162 | |
2124 | * apic_is_clustered_box() -- Check if we can expect good TSC | 2163 | static int __cpuinit apic_cluster_num(void) |
2125 | * | ||
2126 | * Thus far, the major user of this is IBM's Summit2 series: | ||
2127 | * | ||
2128 | * Clustered boxes may have unsynced TSC problems if they are | ||
2129 | * multi-chassis. Use available data to take a good guess. | ||
2130 | * If in doubt, go HPET. | ||
2131 | */ | ||
2132 | __cpuinit int apic_is_clustered_box(void) | ||
2133 | { | 2164 | { |
2134 | int i, clusters, zeros; | 2165 | int i, clusters, zeros; |
2135 | unsigned id; | 2166 | unsigned id; |
2136 | u16 *bios_cpu_apicid; | 2167 | u16 *bios_cpu_apicid; |
2137 | DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS); | 2168 | DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS); |
2138 | 2169 | ||
2139 | /* | ||
2140 | * there is not this kind of box with AMD CPU yet. | ||
2141 | * Some AMD box with quadcore cpu and 8 sockets apicid | ||
2142 | * will be [4, 0x23] or [8, 0x27] could be thought to | ||
2143 | * vsmp box still need checking... | ||
2144 | */ | ||
2145 | if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && !is_vsmp_box()) | ||
2146 | return 0; | ||
2147 | |||
2148 | bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid); | 2170 | bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid); |
2149 | bitmap_zero(clustermap, NUM_APIC_CLUSTERS); | 2171 | bitmap_zero(clustermap, NUM_APIC_CLUSTERS); |
2150 | 2172 | ||
@@ -2180,18 +2202,67 @@ __cpuinit int apic_is_clustered_box(void) | |||
2180 | ++zeros; | 2202 | ++zeros; |
2181 | } | 2203 | } |
2182 | 2204 | ||
2183 | /* ScaleMP vSMPowered boxes have one cluster per board and TSCs are | 2205 | return clusters; |
2184 | * not guaranteed to be synced between boards | 2206 | } |
2185 | */ | 2207 | |
2186 | if (is_vsmp_box() && clusters > 1) | 2208 | static int __cpuinitdata multi_checked; |
2209 | static int __cpuinitdata multi; | ||
2210 | |||
2211 | static int __cpuinit set_multi(const struct dmi_system_id *d) | ||
2212 | { | ||
2213 | if (multi) | ||
2214 | return 0; | ||
2215 | pr_info("APIC: %s detected, Multi Chassis\n", d->ident); | ||
2216 | multi = 1; | ||
2217 | return 0; | ||
2218 | } | ||
2219 | |||
2220 | static const __cpuinitconst struct dmi_system_id multi_dmi_table[] = { | ||
2221 | { | ||
2222 | .callback = set_multi, | ||
2223 | .ident = "IBM System Summit2", | ||
2224 | .matches = { | ||
2225 | DMI_MATCH(DMI_SYS_VENDOR, "IBM"), | ||
2226 | DMI_MATCH(DMI_PRODUCT_NAME, "Summit2"), | ||
2227 | }, | ||
2228 | }, | ||
2229 | {} | ||
2230 | }; | ||
2231 | |||
2232 | static void __cpuinit dmi_check_multi(void) | ||
2233 | { | ||
2234 | if (multi_checked) | ||
2235 | return; | ||
2236 | |||
2237 | dmi_check_system(multi_dmi_table); | ||
2238 | multi_checked = 1; | ||
2239 | } | ||
2240 | |||
2241 | /* | ||
2242 | * apic_is_clustered_box() -- Check if we can expect good TSC | ||
2243 | * | ||
2244 | * Thus far, the major user of this is IBM's Summit2 series: | ||
2245 | * Clustered boxes may have unsynced TSC problems if they are | ||
2246 | * multi-chassis. | ||
2247 | * Use DMI to check them | ||
2248 | */ | ||
2249 | __cpuinit int apic_is_clustered_box(void) | ||
2250 | { | ||
2251 | dmi_check_multi(); | ||
2252 | if (multi) | ||
2187 | return 1; | 2253 | return 1; |
2188 | 2254 | ||
2255 | if (!is_vsmp_box()) | ||
2256 | return 0; | ||
2257 | |||
2189 | /* | 2258 | /* |
2190 | * If clusters > 2, then should be multi-chassis. | 2259 | * ScaleMP vSMPowered boxes have one cluster per board and TSCs are |
2191 | * May have to revisit this when multi-core + hyperthreaded CPUs come | 2260 | * not guaranteed to be synced between boards |
2192 | * out, but AFAIK this will work even for them. | ||
2193 | */ | 2261 | */ |
2194 | return (clusters > 2); | 2262 | if (apic_cluster_num() > 1) |
2263 | return 1; | ||
2264 | |||
2265 | return 0; | ||
2195 | } | 2266 | } |
2196 | #endif | 2267 | #endif |
2197 | 2268 | ||