diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/include/asm/apic.h | 7 | ||||
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 83 | ||||
-rw-r--r-- | arch/x86/kernel/apic/probe_64.c | 6 |
3 files changed, 56 insertions, 40 deletions
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index bb7d47925847..586b7adb8e53 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h | |||
@@ -183,6 +183,10 @@ static inline int x2apic_enabled(void) | |||
183 | } | 183 | } |
184 | 184 | ||
185 | #define x2apic_supported() (cpu_has_x2apic) | 185 | #define x2apic_supported() (cpu_has_x2apic) |
186 | static inline void x2apic_force_phys(void) | ||
187 | { | ||
188 | x2apic_phys = 1; | ||
189 | } | ||
186 | #else | 190 | #else |
187 | static inline void check_x2apic(void) | 191 | static inline void check_x2apic(void) |
188 | { | 192 | { |
@@ -194,6 +198,9 @@ static inline int x2apic_enabled(void) | |||
194 | { | 198 | { |
195 | return 0; | 199 | return 0; |
196 | } | 200 | } |
201 | static inline void x2apic_force_phys(void) | ||
202 | { | ||
203 | } | ||
197 | 204 | ||
198 | #define x2apic_preenabled 0 | 205 | #define x2apic_preenabled 0 |
199 | #define x2apic_supported() 0 | 206 | #define x2apic_supported() 0 |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 0b021c56e822..de039fcdd053 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <asm/mtrr.h> | 49 | #include <asm/mtrr.h> |
50 | #include <asm/smp.h> | 50 | #include <asm/smp.h> |
51 | #include <asm/mce.h> | 51 | #include <asm/mce.h> |
52 | #include <asm/kvm_para.h> | ||
52 | 53 | ||
53 | unsigned int num_processors; | 54 | unsigned int num_processors; |
54 | 55 | ||
@@ -1361,52 +1362,76 @@ void enable_x2apic(void) | |||
1361 | } | 1362 | } |
1362 | #endif /* CONFIG_X86_X2APIC */ | 1363 | #endif /* CONFIG_X86_X2APIC */ |
1363 | 1364 | ||
1364 | void __init enable_IR_x2apic(void) | 1365 | int __init enable_IR(void) |
1365 | { | 1366 | { |
1366 | #ifdef CONFIG_INTR_REMAP | 1367 | #ifdef CONFIG_INTR_REMAP |
1367 | int ret; | 1368 | int ret; |
1368 | unsigned long flags; | ||
1369 | struct IO_APIC_route_entry **ioapic_entries = NULL; | ||
1370 | 1369 | ||
1371 | ret = dmar_table_init(); | 1370 | ret = dmar_table_init(); |
1372 | if (ret) { | 1371 | if (ret) { |
1373 | pr_debug("dmar_table_init() failed with %d:\n", ret); | 1372 | pr_debug("dmar_table_init() failed with %d:\n", ret); |
1374 | goto ir_failed; | 1373 | return 0; |
1375 | } | 1374 | } |
1376 | 1375 | ||
1377 | if (!intr_remapping_supported()) { | 1376 | if (!intr_remapping_supported()) { |
1378 | pr_debug("intr-remapping not supported\n"); | 1377 | pr_debug("intr-remapping not supported\n"); |
1379 | goto ir_failed; | 1378 | return 0; |
1380 | } | 1379 | } |
1381 | 1380 | ||
1382 | |||
1383 | if (!x2apic_preenabled && skip_ioapic_setup) { | 1381 | if (!x2apic_preenabled && skip_ioapic_setup) { |
1384 | pr_info("Skipped enabling intr-remap because of skipping " | 1382 | pr_info("Skipped enabling intr-remap because of skipping " |
1385 | "io-apic setup\n"); | 1383 | "io-apic setup\n"); |
1386 | return; | 1384 | return 0; |
1387 | } | 1385 | } |
1388 | 1386 | ||
1387 | if (enable_intr_remapping(x2apic_supported())) | ||
1388 | return 0; | ||
1389 | |||
1390 | pr_info("Enabled Interrupt-remapping\n"); | ||
1391 | |||
1392 | return 1; | ||
1393 | |||
1394 | #endif | ||
1395 | return 0; | ||
1396 | } | ||
1397 | |||
1398 | void __init enable_IR_x2apic(void) | ||
1399 | { | ||
1400 | unsigned long flags; | ||
1401 | struct IO_APIC_route_entry **ioapic_entries = NULL; | ||
1402 | int ret, x2apic_enabled = 0; | ||
1403 | |||
1389 | ioapic_entries = alloc_ioapic_entries(); | 1404 | ioapic_entries = alloc_ioapic_entries(); |
1390 | if (!ioapic_entries) { | 1405 | if (!ioapic_entries) { |
1391 | pr_info("Allocate ioapic_entries failed: %d\n", ret); | 1406 | pr_err("Allocate ioapic_entries failed\n"); |
1392 | goto end; | 1407 | goto out; |
1393 | } | 1408 | } |
1394 | 1409 | ||
1395 | ret = save_IO_APIC_setup(ioapic_entries); | 1410 | ret = save_IO_APIC_setup(ioapic_entries); |
1396 | if (ret) { | 1411 | if (ret) { |
1397 | pr_info("Saving IO-APIC state failed: %d\n", ret); | 1412 | pr_info("Saving IO-APIC state failed: %d\n", ret); |
1398 | goto end; | 1413 | goto out; |
1399 | } | 1414 | } |
1400 | 1415 | ||
1401 | local_irq_save(flags); | 1416 | local_irq_save(flags); |
1402 | mask_IO_APIC_setup(ioapic_entries); | ||
1403 | mask_8259A(); | 1417 | mask_8259A(); |
1418 | mask_IO_APIC_setup(ioapic_entries); | ||
1404 | 1419 | ||
1405 | ret = enable_intr_remapping(x2apic_supported()); | 1420 | ret = enable_IR(); |
1406 | if (ret) | 1421 | if (!ret) { |
1407 | goto end_restore; | 1422 | /* IR is required if there is APIC ID > 255 even when running |
1423 | * under KVM | ||
1424 | */ | ||
1425 | if (max_physical_apicid > 255 || !kvm_para_available()) | ||
1426 | goto nox2apic; | ||
1427 | /* | ||
1428 | * without IR all CPUs can be addressed by IOAPIC/MSI | ||
1429 | * only in physical mode | ||
1430 | */ | ||
1431 | x2apic_force_phys(); | ||
1432 | } | ||
1408 | 1433 | ||
1409 | pr_info("Enabled Interrupt-remapping\n"); | 1434 | x2apic_enabled = 1; |
1410 | 1435 | ||
1411 | if (x2apic_supported() && !x2apic_mode) { | 1436 | if (x2apic_supported() && !x2apic_mode) { |
1412 | x2apic_mode = 1; | 1437 | x2apic_mode = 1; |
@@ -1414,41 +1439,25 @@ void __init enable_IR_x2apic(void) | |||
1414 | pr_info("Enabled x2apic\n"); | 1439 | pr_info("Enabled x2apic\n"); |
1415 | } | 1440 | } |
1416 | 1441 | ||
1417 | end_restore: | 1442 | nox2apic: |
1418 | if (ret) | 1443 | if (!ret) /* IR enabling failed */ |
1419 | /* | ||
1420 | * IR enabling failed | ||
1421 | */ | ||
1422 | restore_IO_APIC_setup(ioapic_entries); | 1444 | restore_IO_APIC_setup(ioapic_entries); |
1423 | |||
1424 | unmask_8259A(); | 1445 | unmask_8259A(); |
1425 | local_irq_restore(flags); | 1446 | local_irq_restore(flags); |
1426 | 1447 | ||
1427 | end: | 1448 | out: |
1428 | if (ioapic_entries) | 1449 | if (ioapic_entries) |
1429 | free_ioapic_entries(ioapic_entries); | 1450 | free_ioapic_entries(ioapic_entries); |
1430 | 1451 | ||
1431 | if (!ret) | 1452 | if (x2apic_enabled) |
1432 | return; | 1453 | return; |
1433 | 1454 | ||
1434 | ir_failed: | ||
1435 | if (x2apic_preenabled) | 1455 | if (x2apic_preenabled) |
1436 | panic("x2apic enabled by bios. But IR enabling failed"); | 1456 | panic("x2apic: enabled by BIOS but kernel init failed."); |
1437 | else if (cpu_has_x2apic) | 1457 | else if (cpu_has_x2apic) |
1438 | pr_info("Not enabling x2apic,Intr-remapping\n"); | 1458 | pr_info("Not enabling x2apic, Intr-remapping init failed.\n"); |
1439 | #else | ||
1440 | if (!cpu_has_x2apic) | ||
1441 | return; | ||
1442 | |||
1443 | if (x2apic_preenabled) | ||
1444 | panic("x2apic enabled prior OS handover," | ||
1445 | " enable CONFIG_X86_X2APIC, CONFIG_INTR_REMAP"); | ||
1446 | #endif | ||
1447 | |||
1448 | return; | ||
1449 | } | 1459 | } |
1450 | 1460 | ||
1451 | |||
1452 | #ifdef CONFIG_X86_64 | 1461 | #ifdef CONFIG_X86_64 |
1453 | /* | 1462 | /* |
1454 | * Detect and enable local APICs on non-SMP boards. | 1463 | * Detect and enable local APICs on non-SMP boards. |
diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c index bc3e880f9b82..f3b1037076e4 100644 --- a/arch/x86/kernel/apic/probe_64.c +++ b/arch/x86/kernel/apic/probe_64.c | |||
@@ -50,11 +50,11 @@ static struct apic *apic_probe[] __initdata = { | |||
50 | void __init default_setup_apic_routing(void) | 50 | void __init default_setup_apic_routing(void) |
51 | { | 51 | { |
52 | #ifdef CONFIG_X86_X2APIC | 52 | #ifdef CONFIG_X86_X2APIC |
53 | if (x2apic_mode && (apic != &apic_x2apic_phys && | 53 | if (x2apic_mode |
54 | #ifdef CONFIG_X86_UV | 54 | #ifdef CONFIG_X86_UV |
55 | apic != &apic_x2apic_uv_x && | 55 | && apic != &apic_x2apic_uv_x |
56 | #endif | 56 | #endif |
57 | apic != &apic_x2apic_cluster)) { | 57 | ) { |
58 | if (x2apic_phys) | 58 | if (x2apic_phys) |
59 | apic = &apic_x2apic_phys; | 59 | apic = &apic_x2apic_phys; |
60 | else | 60 | else |