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