Merge branch 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[safe/jmp/linux-2.6] / arch / x86 / kernel / apic / apic.c
index ce00980..a34601f 100644 (file)
@@ -50,6 +50,7 @@
 #include <asm/mtrr.h>
 #include <asm/smp.h>
 #include <asm/mce.h>
+#include <asm/kvm_para.h>
 
 unsigned int num_processors;
 
@@ -1362,52 +1363,80 @@ void enable_x2apic(void)
 }
 #endif /* CONFIG_X86_X2APIC */
 
-void __init enable_IR_x2apic(void)
+int __init enable_IR(void)
 {
 #ifdef CONFIG_INTR_REMAP
-       int ret;
-       unsigned long flags;
-       struct IO_APIC_route_entry **ioapic_entries = NULL;
-
-       ret = dmar_table_init();
-       if (ret) {
-               pr_debug("dmar_table_init() failed with %d:\n", ret);
-               goto ir_failed;
-       }
-
        if (!intr_remapping_supported()) {
                pr_debug("intr-remapping not supported\n");
-               goto ir_failed;
+               return 0;
        }
 
-
        if (!x2apic_preenabled && skip_ioapic_setup) {
                pr_info("Skipped enabling intr-remap because of skipping "
                        "io-apic setup\n");
-               return;
+               return 0;
        }
 
+       if (enable_intr_remapping(x2apic_supported()))
+               return 0;
+
+       pr_info("Enabled Interrupt-remapping\n");
+
+       return 1;
+
+#endif
+       return 0;
+}
+
+void __init enable_IR_x2apic(void)
+{
+       unsigned long flags;
+       struct IO_APIC_route_entry **ioapic_entries = NULL;
+       int ret, x2apic_enabled = 0;
+       int dmar_table_init_ret = 0;
+
+#ifdef CONFIG_INTR_REMAP
+       dmar_table_init_ret = dmar_table_init();
+       if (dmar_table_init_ret)
+               pr_debug("dmar_table_init() failed with %d:\n",
+                               dmar_table_init_ret);
+#endif
+
        ioapic_entries = alloc_ioapic_entries();
        if (!ioapic_entries) {
-               pr_info("Allocate ioapic_entries failed: %d\n", ret);
-               goto end;
+               pr_err("Allocate ioapic_entries failed\n");
+               goto out;
        }
 
        ret = save_IO_APIC_setup(ioapic_entries);
        if (ret) {
                pr_info("Saving IO-APIC state failed: %d\n", ret);
-               goto end;
+               goto out;
        }
 
        local_irq_save(flags);
-       mask_IO_APIC_setup(ioapic_entries);
        mask_8259A();
+       mask_IO_APIC_setup(ioapic_entries);
 
-       ret = enable_intr_remapping(x2apic_supported());
-       if (ret)
-               goto end_restore;
+       if (dmar_table_init_ret)
+               ret = 0;
+       else
+               ret = enable_IR();
 
-       pr_info("Enabled Interrupt-remapping\n");
+       if (!ret) {
+               /* IR is required if there is APIC ID > 255 even when running
+                * under KVM
+                */
+               if (max_physical_apicid > 255 || !kvm_para_available())
+                       goto nox2apic;
+               /*
+                * without IR all CPUs can be addressed by IOAPIC/MSI
+                * only in physical mode
+                */
+               x2apic_force_phys();
+       }
+
+       x2apic_enabled = 1;
 
        if (x2apic_supported() && !x2apic_mode) {
                x2apic_mode = 1;
@@ -1415,41 +1444,25 @@ void __init enable_IR_x2apic(void)
                pr_info("Enabled x2apic\n");
        }
 
-end_restore:
-       if (ret)
-               /*
-                * IR enabling failed
-                */
+nox2apic:
+       if (!ret) /* IR enabling failed */
                restore_IO_APIC_setup(ioapic_entries);
-
        unmask_8259A();
        local_irq_restore(flags);
 
-end:
+out:
        if (ioapic_entries)
                free_ioapic_entries(ioapic_entries);
 
-       if (!ret)
+       if (x2apic_enabled)
                return;
 
-ir_failed:
        if (x2apic_preenabled)
-               panic("x2apic enabled by bios. But IR enabling failed");
+               panic("x2apic: enabled by BIOS but kernel init failed.");
        else if (cpu_has_x2apic)
-               pr_info("Not enabling x2apic,Intr-remapping\n");
-#else
-       if (!cpu_has_x2apic)
-               return;
-
-       if (x2apic_preenabled)
-               panic("x2apic enabled prior OS handover,"
-                     " enable CONFIG_X86_X2APIC, CONFIG_INTR_REMAP");
-#endif
-
-       return;
+               pr_info("Not enabling x2apic, Intr-remapping init failed.\n");
 }
 
-
 #ifdef CONFIG_X86_64
 /*
  * Detect and enable local APICs on non-SMP boards.
@@ -1550,8 +1563,6 @@ no_apic:
 #ifdef CONFIG_X86_64
 void __init early_init_lapic_mapping(void)
 {
-       unsigned long phys_addr;
-
        /*
         * If no local APIC can be found then go out
         * : it means there is no mpatable and MADT
@@ -1559,11 +1570,9 @@ void __init early_init_lapic_mapping(void)
        if (!smp_found_config)
                return;
 
-       phys_addr = mp_lapic_addr;
-
-       set_fixmap_nocache(FIX_APIC_BASE, phys_addr);
+       set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
        apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
-                   APIC_BASE, phys_addr);
+                   APIC_BASE, mp_lapic_addr);
 
        /*
         * Fetch the APIC ID of the BSP in case we have a
@@ -1652,7 +1661,6 @@ int __init APIC_init_uniprocessor(void)
            APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
                pr_err("BIOS bug, local APIC 0x%x not detected!...\n",
                        boot_cpu_physical_apicid);
-               clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
                return -1;
        }
 #endif