aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2009-07-20 08:24:17 -0400
committerIngo Molnar <mingo@elte.hu>2009-08-05 08:28:50 -0400
commitce69a784504222c3ab6f1b3c357d09ec5772127a (patch)
tree73f6d67be7b923572f6d1942d692ae523074886d /arch
parent9910887af84e33ba98fd6792029470ae80166208 (diff)
x86/apic: Enable x2APIC without interrupt remapping under KVM
KVM would like to provide x2APIC interface to a guest without emulating interrupt remapping device. The reason KVM prefers guest to use x2APIC is that x2APIC interface is better virtualizable and provides better performance than mmio xAPIC interface: - msr exits are faster than mmio (no page table walk, emulation) - no need to read back ICR to look at the busy bit - one 64 bit ICR write instead of two 32 bit writes - shared code with the Hyper-V paravirt interface Included patch changes x2APIC enabling logic to enable it even if IR initialization failed, but kernel runs under KVM and no apic id is greater than 255 (if there is one spec requires BIOS to move to x2apic mode before starting an OS). -v2: fix build -v3: fix bug causing compiler warning Signed-off-by: Gleb Natapov <gleb@redhat.com> Acked-by: Suresh Siddha <suresh.b.siddha@intel.com> Cc: Sheng Yang <sheng@linux.intel.com> Cc: "avi@redhat.com" <avi@redhat.com> LKML-Reference: <20090720122417.GR5638@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/apic.h7
-rw-r--r--arch/x86/kernel/apic/apic.c83
-rw-r--r--arch/x86/kernel/apic/probe_64.c6
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)
186static inline void x2apic_force_phys(void)
187{
188 x2apic_phys = 1;
189}
186#else 190#else
187static inline void check_x2apic(void) 191static 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}
201static 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
53unsigned int num_processors; 54unsigned 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
1364void __init enable_IR_x2apic(void) 1365int __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
1398void __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
1417end_restore: 1442nox2apic:
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
1427end: 1448out:
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
1434ir_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 = {
50void __init default_setup_apic_routing(void) 50void __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