diff options
| -rw-r--r-- | arch/x86/Kconfig | 4 | ||||
| -rw-r--r-- | arch/x86/include/asm/apic.h | 58 | ||||
| -rw-r--r-- | arch/x86/include/asm/io_apic.h | 5 | ||||
| -rw-r--r-- | arch/x86/include/asm/irq_remapping.h | 4 | ||||
| -rw-r--r-- | arch/x86/include/asm/smpboot_hooks.h | 68 | ||||
| -rw-r--r-- | arch/x86/kernel/acpi/boot.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/apic.c | 456 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 13 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/common.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/smpboot.c | 113 | ||||
| -rw-r--r-- | drivers/iommu/amd_iommu.c | 1 | ||||
| -rw-r--r-- | drivers/iommu/amd_iommu_init.c | 15 | ||||
| -rw-r--r-- | drivers/iommu/amd_iommu_proto.h | 1 | ||||
| -rw-r--r-- | drivers/iommu/intel_irq_remapping.c | 96 | ||||
| -rw-r--r-- | drivers/iommu/irq_remapping.c | 74 | ||||
| -rw-r--r-- | drivers/iommu/irq_remapping.h | 5 | ||||
| -rw-r--r-- | include/linux/smp.h | 7 | ||||
| -rw-r--r-- | init/main.c | 13 |
18 files changed, 436 insertions, 501 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 85588a891c06..5e28e2be3a41 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -856,6 +856,10 @@ config SCHED_MC | |||
| 856 | 856 | ||
| 857 | source "kernel/Kconfig.preempt" | 857 | source "kernel/Kconfig.preempt" |
| 858 | 858 | ||
| 859 | config UP_LATE_INIT | ||
| 860 | def_bool y | ||
| 861 | depends on !SMP && X86_LOCAL_APIC | ||
| 862 | |||
| 859 | config X86_UP_APIC | 863 | config X86_UP_APIC |
| 860 | bool "Local APIC support on uniprocessors" | 864 | bool "Local APIC support on uniprocessors" |
| 861 | depends on X86_32 && !SMP && !X86_32_NON_STANDARD | 865 | depends on X86_32 && !SMP && !X86_32_NON_STANDARD |
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 465b309af254..92003f3c8a42 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h | |||
| @@ -106,7 +106,14 @@ extern u32 native_safe_apic_wait_icr_idle(void); | |||
| 106 | extern void native_apic_icr_write(u32 low, u32 id); | 106 | extern void native_apic_icr_write(u32 low, u32 id); |
| 107 | extern u64 native_apic_icr_read(void); | 107 | extern u64 native_apic_icr_read(void); |
| 108 | 108 | ||
| 109 | extern int x2apic_mode; | 109 | static inline bool apic_is_x2apic_enabled(void) |
| 110 | { | ||
| 111 | u64 msr; | ||
| 112 | |||
| 113 | if (rdmsrl_safe(MSR_IA32_APICBASE, &msr)) | ||
| 114 | return false; | ||
| 115 | return msr & X2APIC_ENABLE; | ||
| 116 | } | ||
| 110 | 117 | ||
| 111 | #ifdef CONFIG_X86_X2APIC | 118 | #ifdef CONFIG_X86_X2APIC |
| 112 | /* | 119 | /* |
| @@ -169,48 +176,23 @@ static inline u64 native_x2apic_icr_read(void) | |||
| 169 | return val; | 176 | return val; |
| 170 | } | 177 | } |
| 171 | 178 | ||
| 179 | extern int x2apic_mode; | ||
| 172 | extern int x2apic_phys; | 180 | extern int x2apic_phys; |
| 173 | extern int x2apic_preenabled; | 181 | extern void __init check_x2apic(void); |
| 174 | extern void check_x2apic(void); | 182 | extern void x2apic_setup(void); |
| 175 | extern void enable_x2apic(void); | ||
| 176 | static inline int x2apic_enabled(void) | 183 | static inline int x2apic_enabled(void) |
| 177 | { | 184 | { |
| 178 | u64 msr; | 185 | return cpu_has_x2apic && apic_is_x2apic_enabled(); |
| 179 | |||
| 180 | if (!cpu_has_x2apic) | ||
| 181 | return 0; | ||
| 182 | |||
| 183 | rdmsrl(MSR_IA32_APICBASE, msr); | ||
| 184 | if (msr & X2APIC_ENABLE) | ||
| 185 | return 1; | ||
| 186 | return 0; | ||
| 187 | } | 186 | } |
| 188 | 187 | ||
| 189 | #define x2apic_supported() (cpu_has_x2apic) | 188 | #define x2apic_supported() (cpu_has_x2apic) |
| 190 | static inline void x2apic_force_phys(void) | ||
| 191 | { | ||
| 192 | x2apic_phys = 1; | ||
| 193 | } | ||
| 194 | #else | 189 | #else |
| 195 | static inline void disable_x2apic(void) | 190 | static inline void check_x2apic(void) { } |
| 196 | { | 191 | static inline void x2apic_setup(void) { } |
| 197 | } | 192 | static inline int x2apic_enabled(void) { return 0; } |
| 198 | static inline void check_x2apic(void) | ||
| 199 | { | ||
| 200 | } | ||
| 201 | static inline void enable_x2apic(void) | ||
| 202 | { | ||
| 203 | } | ||
| 204 | static inline int x2apic_enabled(void) | ||
| 205 | { | ||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | static inline void x2apic_force_phys(void) | ||
| 209 | { | ||
| 210 | } | ||
| 211 | 193 | ||
| 212 | #define x2apic_preenabled 0 | 194 | #define x2apic_mode (0) |
| 213 | #define x2apic_supported() 0 | 195 | #define x2apic_supported() (0) |
| 214 | #endif | 196 | #endif |
| 215 | 197 | ||
| 216 | extern void enable_IR_x2apic(void); | 198 | extern void enable_IR_x2apic(void); |
| @@ -219,7 +201,6 @@ extern int get_physical_broadcast(void); | |||
| 219 | 201 | ||
| 220 | extern int lapic_get_maxlvt(void); | 202 | extern int lapic_get_maxlvt(void); |
| 221 | extern void clear_local_APIC(void); | 203 | extern void clear_local_APIC(void); |
| 222 | extern void connect_bsp_APIC(void); | ||
| 223 | extern void disconnect_bsp_APIC(int virt_wire_setup); | 204 | extern void disconnect_bsp_APIC(int virt_wire_setup); |
| 224 | extern void disable_local_APIC(void); | 205 | extern void disable_local_APIC(void); |
| 225 | extern void lapic_shutdown(void); | 206 | extern void lapic_shutdown(void); |
| @@ -227,8 +208,6 @@ extern int verify_local_APIC(void); | |||
| 227 | extern void sync_Arb_IDs(void); | 208 | extern void sync_Arb_IDs(void); |
| 228 | extern void init_bsp_APIC(void); | 209 | extern void init_bsp_APIC(void); |
| 229 | extern void setup_local_APIC(void); | 210 | extern void setup_local_APIC(void); |
| 230 | extern void end_local_APIC_setup(void); | ||
| 231 | extern void bsp_end_local_APIC_setup(void); | ||
| 232 | extern void init_apic_mappings(void); | 211 | extern void init_apic_mappings(void); |
| 233 | void register_lapic_address(unsigned long address); | 212 | void register_lapic_address(unsigned long address); |
| 234 | extern void setup_boot_APIC_clock(void); | 213 | extern void setup_boot_APIC_clock(void); |
| @@ -236,6 +215,9 @@ extern void setup_secondary_APIC_clock(void); | |||
| 236 | extern int APIC_init_uniprocessor(void); | 215 | extern int APIC_init_uniprocessor(void); |
| 237 | extern int apic_force_enable(unsigned long addr); | 216 | extern int apic_force_enable(unsigned long addr); |
| 238 | 217 | ||
| 218 | extern int apic_bsp_setup(bool upmode); | ||
| 219 | extern void apic_ap_setup(void); | ||
| 220 | |||
| 239 | /* | 221 | /* |
| 240 | * On 32bit this is mach-xxx local | 222 | * On 32bit this is mach-xxx local |
| 241 | */ | 223 | */ |
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index bf006cce9418..2f91685fe1cd 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h | |||
| @@ -279,6 +279,11 @@ static inline void disable_ioapic_support(void) { } | |||
| 279 | #define native_ioapic_set_affinity NULL | 279 | #define native_ioapic_set_affinity NULL |
| 280 | #define native_setup_ioapic_entry NULL | 280 | #define native_setup_ioapic_entry NULL |
| 281 | #define native_eoi_ioapic_pin NULL | 281 | #define native_eoi_ioapic_pin NULL |
| 282 | |||
| 283 | static inline void setup_IO_APIC(void) { } | ||
| 284 | static inline void enable_IO_APIC(void) { } | ||
| 285 | static inline void setup_ioapic_dest(void) { } | ||
| 286 | |||
| 282 | #endif | 287 | #endif |
| 283 | 288 | ||
| 284 | #endif /* _ASM_X86_IO_APIC_H */ | 289 | #endif /* _ASM_X86_IO_APIC_H */ |
diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h index b7747c4c2cf2..6224d316c405 100644 --- a/arch/x86/include/asm/irq_remapping.h +++ b/arch/x86/include/asm/irq_remapping.h | |||
| @@ -33,8 +33,6 @@ struct irq_cfg; | |||
| 33 | 33 | ||
| 34 | #ifdef CONFIG_IRQ_REMAP | 34 | #ifdef CONFIG_IRQ_REMAP |
| 35 | 35 | ||
| 36 | extern void setup_irq_remapping_ops(void); | ||
| 37 | extern int irq_remapping_supported(void); | ||
| 38 | extern void set_irq_remapping_broken(void); | 36 | extern void set_irq_remapping_broken(void); |
| 39 | extern int irq_remapping_prepare(void); | 37 | extern int irq_remapping_prepare(void); |
| 40 | extern int irq_remapping_enable(void); | 38 | extern int irq_remapping_enable(void); |
| @@ -60,8 +58,6 @@ void irq_remap_modify_chip_defaults(struct irq_chip *chip); | |||
| 60 | 58 | ||
| 61 | #else /* CONFIG_IRQ_REMAP */ | 59 | #else /* CONFIG_IRQ_REMAP */ |
| 62 | 60 | ||
| 63 | static inline void setup_irq_remapping_ops(void) { } | ||
| 64 | static inline int irq_remapping_supported(void) { return 0; } | ||
| 65 | static inline void set_irq_remapping_broken(void) { } | 61 | static inline void set_irq_remapping_broken(void) { } |
| 66 | static inline int irq_remapping_prepare(void) { return -ENODEV; } | 62 | static inline int irq_remapping_prepare(void) { return -ENODEV; } |
| 67 | static inline int irq_remapping_enable(void) { return -ENODEV; } | 63 | static inline int irq_remapping_enable(void) { return -ENODEV; } |
diff --git a/arch/x86/include/asm/smpboot_hooks.h b/arch/x86/include/asm/smpboot_hooks.h deleted file mode 100644 index 0da7409f0bec..000000000000 --- a/arch/x86/include/asm/smpboot_hooks.h +++ /dev/null | |||
| @@ -1,68 +0,0 @@ | |||
| 1 | /* two abstractions specific to kernel/smpboot.c, mainly to cater to visws | ||
| 2 | * which needs to alter them. */ | ||
| 3 | |||
| 4 | static inline void smpboot_clear_io_apic_irqs(void) | ||
| 5 | { | ||
| 6 | #ifdef CONFIG_X86_IO_APIC | ||
| 7 | io_apic_irqs = 0; | ||
| 8 | #endif | ||
| 9 | } | ||
| 10 | |||
| 11 | static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip) | ||
| 12 | { | ||
| 13 | unsigned long flags; | ||
| 14 | |||
| 15 | spin_lock_irqsave(&rtc_lock, flags); | ||
| 16 | CMOS_WRITE(0xa, 0xf); | ||
| 17 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 18 | local_flush_tlb(); | ||
| 19 | pr_debug("1.\n"); | ||
| 20 | *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) = | ||
| 21 | start_eip >> 4; | ||
| 22 | pr_debug("2.\n"); | ||
| 23 | *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = | ||
| 24 | start_eip & 0xf; | ||
| 25 | pr_debug("3.\n"); | ||
| 26 | } | ||
| 27 | |||
| 28 | static inline void smpboot_restore_warm_reset_vector(void) | ||
| 29 | { | ||
| 30 | unsigned long flags; | ||
| 31 | |||
| 32 | /* | ||
| 33 | * Install writable page 0 entry to set BIOS data area. | ||
| 34 | */ | ||
| 35 | local_flush_tlb(); | ||
| 36 | |||
| 37 | /* | ||
| 38 | * Paranoid: Set warm reset code and vector here back | ||
| 39 | * to default values. | ||
| 40 | */ | ||
| 41 | spin_lock_irqsave(&rtc_lock, flags); | ||
| 42 | CMOS_WRITE(0, 0xf); | ||
| 43 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 44 | |||
| 45 | *((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0; | ||
| 46 | } | ||
| 47 | |||
| 48 | static inline void __init smpboot_setup_io_apic(void) | ||
| 49 | { | ||
| 50 | #ifdef CONFIG_X86_IO_APIC | ||
| 51 | /* | ||
| 52 | * Here we can be sure that there is an IO-APIC in the system. Let's | ||
| 53 | * go and set it up: | ||
| 54 | */ | ||
| 55 | if (!skip_ioapic_setup && nr_ioapics) | ||
| 56 | setup_IO_APIC(); | ||
| 57 | else { | ||
| 58 | nr_ioapics = 0; | ||
| 59 | } | ||
| 60 | #endif | ||
| 61 | } | ||
| 62 | |||
| 63 | static inline void smpboot_clear_io_apic(void) | ||
| 64 | { | ||
| 65 | #ifdef CONFIG_X86_IO_APIC | ||
| 66 | nr_ioapics = 0; | ||
| 67 | #endif | ||
| 68 | } | ||
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index b9e30daa0881..a18fff361c7f 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
| @@ -653,6 +653,7 @@ static int acpi_register_gsi_pic(struct device *dev, u32 gsi, | |||
| 653 | return gsi; | 653 | return gsi; |
| 654 | } | 654 | } |
| 655 | 655 | ||
| 656 | #ifdef CONFIG_X86_LOCAL_APIC | ||
| 656 | static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi, | 657 | static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi, |
| 657 | int trigger, int polarity) | 658 | int trigger, int polarity) |
| 658 | { | 659 | { |
| @@ -675,6 +676,7 @@ static void acpi_unregister_gsi_ioapic(u32 gsi) | |||
| 675 | mutex_unlock(&acpi_ioapic_lock); | 676 | mutex_unlock(&acpi_ioapic_lock); |
| 676 | #endif | 677 | #endif |
| 677 | } | 678 | } |
| 679 | #endif | ||
| 678 | 680 | ||
| 679 | int (*__acpi_register_gsi)(struct device *dev, u32 gsi, | 681 | int (*__acpi_register_gsi)(struct device *dev, u32 gsi, |
| 680 | int trigger, int polarity) = acpi_register_gsi_pic; | 682 | int trigger, int polarity) = acpi_register_gsi_pic; |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 29b5b18afa27..b665d241efad 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
| @@ -134,9 +134,6 @@ static inline void imcr_apic_to_pic(void) | |||
| 134 | */ | 134 | */ |
| 135 | static int force_enable_local_apic __initdata; | 135 | static int force_enable_local_apic __initdata; |
| 136 | 136 | ||
| 137 | /* Control whether x2APIC mode is enabled or not */ | ||
| 138 | static bool nox2apic __initdata; | ||
| 139 | |||
| 140 | /* | 137 | /* |
| 141 | * APIC command line parameters | 138 | * APIC command line parameters |
| 142 | */ | 139 | */ |
| @@ -161,33 +158,6 @@ static __init int setup_apicpmtimer(char *s) | |||
| 161 | __setup("apicpmtimer", setup_apicpmtimer); | 158 | __setup("apicpmtimer", setup_apicpmtimer); |
| 162 | #endif | 159 | #endif |
| 163 | 160 | ||
| 164 | int x2apic_mode; | ||
| 165 | #ifdef CONFIG_X86_X2APIC | ||
| 166 | /* x2apic enabled before OS handover */ | ||
| 167 | int x2apic_preenabled; | ||
| 168 | static int x2apic_disabled; | ||
| 169 | static int __init setup_nox2apic(char *str) | ||
| 170 | { | ||
| 171 | if (x2apic_enabled()) { | ||
| 172 | int apicid = native_apic_msr_read(APIC_ID); | ||
| 173 | |||
| 174 | if (apicid >= 255) { | ||
| 175 | pr_warning("Apicid: %08x, cannot enforce nox2apic\n", | ||
| 176 | apicid); | ||
| 177 | return 0; | ||
| 178 | } | ||
| 179 | |||
| 180 | pr_warning("x2apic already enabled. will disable it\n"); | ||
| 181 | } else | ||
| 182 | setup_clear_cpu_cap(X86_FEATURE_X2APIC); | ||
| 183 | |||
| 184 | nox2apic = true; | ||
| 185 | |||
| 186 | return 0; | ||
| 187 | } | ||
| 188 | early_param("nox2apic", setup_nox2apic); | ||
| 189 | #endif | ||
| 190 | |||
| 191 | unsigned long mp_lapic_addr; | 161 | unsigned long mp_lapic_addr; |
| 192 | int disable_apic; | 162 | int disable_apic; |
| 193 | /* Disable local APIC timer from the kernel commandline or via dmi quirk */ | 163 | /* Disable local APIC timer from the kernel commandline or via dmi quirk */ |
| @@ -1475,7 +1445,7 @@ void setup_local_APIC(void) | |||
| 1475 | #endif | 1445 | #endif |
| 1476 | } | 1446 | } |
| 1477 | 1447 | ||
| 1478 | void end_local_APIC_setup(void) | 1448 | static void end_local_APIC_setup(void) |
| 1479 | { | 1449 | { |
| 1480 | lapic_setup_esr(); | 1450 | lapic_setup_esr(); |
| 1481 | 1451 | ||
| @@ -1492,116 +1462,184 @@ void end_local_APIC_setup(void) | |||
| 1492 | apic_pm_activate(); | 1462 | apic_pm_activate(); |
| 1493 | } | 1463 | } |
| 1494 | 1464 | ||
| 1495 | void __init bsp_end_local_APIC_setup(void) | 1465 | /* |
| 1466 | * APIC setup function for application processors. Called from smpboot.c | ||
| 1467 | */ | ||
| 1468 | void apic_ap_setup(void) | ||
| 1496 | { | 1469 | { |
| 1470 | setup_local_APIC(); | ||
| 1497 | end_local_APIC_setup(); | 1471 | end_local_APIC_setup(); |
| 1498 | |||
| 1499 | /* | ||
| 1500 | * Now that local APIC setup is completed for BP, configure the fault | ||
| 1501 | * handling for interrupt remapping. | ||
| 1502 | */ | ||
| 1503 | irq_remap_enable_fault_handling(); | ||
| 1504 | |||
| 1505 | } | 1472 | } |
| 1506 | 1473 | ||
| 1507 | #ifdef CONFIG_X86_X2APIC | 1474 | #ifdef CONFIG_X86_X2APIC |
| 1508 | /* | 1475 | int x2apic_mode; |
| 1509 | * Need to disable xapic and x2apic at the same time and then enable xapic mode | ||
| 1510 | */ | ||
| 1511 | static inline void __disable_x2apic(u64 msr) | ||
| 1512 | { | ||
| 1513 | wrmsrl(MSR_IA32_APICBASE, | ||
| 1514 | msr & ~(X2APIC_ENABLE | XAPIC_ENABLE)); | ||
| 1515 | wrmsrl(MSR_IA32_APICBASE, msr & ~X2APIC_ENABLE); | ||
| 1516 | } | ||
| 1517 | 1476 | ||
| 1518 | static __init void disable_x2apic(void) | 1477 | enum { |
| 1478 | X2APIC_OFF, | ||
| 1479 | X2APIC_ON, | ||
| 1480 | X2APIC_DISABLED, | ||
| 1481 | }; | ||
| 1482 | static int x2apic_state; | ||
| 1483 | |||
| 1484 | static inline void __x2apic_disable(void) | ||
| 1519 | { | 1485 | { |
| 1520 | u64 msr; | 1486 | u64 msr; |
| 1521 | 1487 | ||
| 1522 | if (!cpu_has_x2apic) | 1488 | if (cpu_has_apic) |
| 1523 | return; | 1489 | return; |
| 1524 | 1490 | ||
| 1525 | rdmsrl(MSR_IA32_APICBASE, msr); | 1491 | rdmsrl(MSR_IA32_APICBASE, msr); |
| 1526 | if (msr & X2APIC_ENABLE) { | 1492 | if (!(msr & X2APIC_ENABLE)) |
| 1527 | u32 x2apic_id = read_apic_id(); | 1493 | return; |
| 1528 | 1494 | /* Disable xapic and x2apic first and then reenable xapic mode */ | |
| 1529 | if (x2apic_id >= 255) | 1495 | wrmsrl(MSR_IA32_APICBASE, msr & ~(X2APIC_ENABLE | XAPIC_ENABLE)); |
| 1530 | panic("Cannot disable x2apic, id: %08x\n", x2apic_id); | 1496 | wrmsrl(MSR_IA32_APICBASE, msr & ~X2APIC_ENABLE); |
| 1497 | printk_once(KERN_INFO "x2apic disabled\n"); | ||
| 1498 | } | ||
| 1531 | 1499 | ||
| 1532 | pr_info("Disabling x2apic\n"); | 1500 | static inline void __x2apic_enable(void) |
| 1533 | __disable_x2apic(msr); | 1501 | { |
| 1502 | u64 msr; | ||
| 1534 | 1503 | ||
| 1535 | if (nox2apic) { | 1504 | rdmsrl(MSR_IA32_APICBASE, msr); |
| 1536 | clear_cpu_cap(&cpu_data(0), X86_FEATURE_X2APIC); | 1505 | if (msr & X2APIC_ENABLE) |
| 1537 | setup_clear_cpu_cap(X86_FEATURE_X2APIC); | 1506 | return; |
| 1538 | } | 1507 | wrmsrl(MSR_IA32_APICBASE, msr | X2APIC_ENABLE); |
| 1508 | printk_once(KERN_INFO "x2apic enabled\n"); | ||
| 1509 | } | ||
| 1539 | 1510 | ||
| 1540 | x2apic_disabled = 1; | 1511 | static int __init setup_nox2apic(char *str) |
| 1541 | x2apic_mode = 0; | 1512 | { |
| 1513 | if (x2apic_enabled()) { | ||
| 1514 | int apicid = native_apic_msr_read(APIC_ID); | ||
| 1542 | 1515 | ||
| 1543 | register_lapic_address(mp_lapic_addr); | 1516 | if (apicid >= 255) { |
| 1517 | pr_warning("Apicid: %08x, cannot enforce nox2apic\n", | ||
| 1518 | apicid); | ||
| 1519 | return 0; | ||
| 1520 | } | ||
| 1521 | pr_warning("x2apic already enabled.\n"); | ||
| 1522 | __x2apic_disable(); | ||
| 1544 | } | 1523 | } |
| 1524 | setup_clear_cpu_cap(X86_FEATURE_X2APIC); | ||
| 1525 | x2apic_state = X2APIC_DISABLED; | ||
| 1526 | x2apic_mode = 0; | ||
| 1527 | return 0; | ||
| 1545 | } | 1528 | } |
| 1529 | early_param("nox2apic", setup_nox2apic); | ||
| 1546 | 1530 | ||
| 1547 | void check_x2apic(void) | 1531 | /* Called from cpu_init() to enable x2apic on (secondary) cpus */ |
| 1532 | void x2apic_setup(void) | ||
| 1548 | { | 1533 | { |
| 1549 | if (x2apic_enabled()) { | 1534 | /* |
| 1550 | pr_info("x2apic enabled by BIOS, switching to x2apic ops\n"); | 1535 | * If x2apic is not in ON state, disable it if already enabled |
| 1551 | x2apic_preenabled = x2apic_mode = 1; | 1536 | * from BIOS. |
| 1537 | */ | ||
| 1538 | if (x2apic_state != X2APIC_ON) { | ||
| 1539 | __x2apic_disable(); | ||
| 1540 | return; | ||
| 1552 | } | 1541 | } |
| 1542 | __x2apic_enable(); | ||
| 1553 | } | 1543 | } |
| 1554 | 1544 | ||
| 1555 | void enable_x2apic(void) | 1545 | static __init void x2apic_disable(void) |
| 1556 | { | 1546 | { |
| 1557 | u64 msr; | 1547 | u32 x2apic_id; |
| 1558 | 1548 | ||
| 1559 | rdmsrl(MSR_IA32_APICBASE, msr); | 1549 | if (x2apic_state != X2APIC_ON) |
| 1560 | if (x2apic_disabled) { | 1550 | goto out; |
| 1561 | __disable_x2apic(msr); | 1551 | |
| 1552 | x2apic_id = read_apic_id(); | ||
| 1553 | if (x2apic_id >= 255) | ||
| 1554 | panic("Cannot disable x2apic, id: %08x\n", x2apic_id); | ||
| 1555 | |||
| 1556 | __x2apic_disable(); | ||
| 1557 | register_lapic_address(mp_lapic_addr); | ||
| 1558 | out: | ||
| 1559 | x2apic_state = X2APIC_DISABLED; | ||
| 1560 | x2apic_mode = 0; | ||
| 1561 | } | ||
| 1562 | |||
| 1563 | static __init void x2apic_enable(void) | ||
| 1564 | { | ||
| 1565 | if (x2apic_state != X2APIC_OFF) | ||
| 1562 | return; | 1566 | return; |
| 1563 | } | ||
| 1564 | 1567 | ||
| 1565 | if (!x2apic_mode) | 1568 | x2apic_mode = 1; |
| 1569 | x2apic_state = X2APIC_ON; | ||
| 1570 | __x2apic_enable(); | ||
| 1571 | } | ||
| 1572 | |||
| 1573 | static __init void try_to_enable_x2apic(int remap_mode) | ||
| 1574 | { | ||
| 1575 | if (x2apic_state == X2APIC_DISABLED) | ||
| 1566 | return; | 1576 | return; |
| 1567 | 1577 | ||
| 1568 | if (!(msr & X2APIC_ENABLE)) { | 1578 | if (remap_mode != IRQ_REMAP_X2APIC_MODE) { |
| 1569 | printk_once(KERN_INFO "Enabling x2apic\n"); | 1579 | /* IR is required if there is APIC ID > 255 even when running |
| 1570 | wrmsrl(MSR_IA32_APICBASE, msr | X2APIC_ENABLE); | 1580 | * under KVM |
| 1581 | */ | ||
| 1582 | if (max_physical_apicid > 255 || | ||
| 1583 | (IS_ENABLED(CONFIG_HYPERVISOR_GUEST) && | ||
| 1584 | !hypervisor_x2apic_available())) { | ||
| 1585 | pr_info("x2apic: IRQ remapping doesn't support X2APIC mode\n"); | ||
| 1586 | x2apic_disable(); | ||
| 1587 | return; | ||
| 1588 | } | ||
| 1589 | |||
| 1590 | /* | ||
| 1591 | * without IR all CPUs can be addressed by IOAPIC/MSI | ||
| 1592 | * only in physical mode | ||
| 1593 | */ | ||
| 1594 | x2apic_phys = 1; | ||
| 1571 | } | 1595 | } |
| 1596 | x2apic_enable(); | ||
| 1572 | } | 1597 | } |
| 1573 | #endif /* CONFIG_X86_X2APIC */ | ||
| 1574 | 1598 | ||
| 1575 | int __init enable_IR(void) | 1599 | void __init check_x2apic(void) |
| 1576 | { | 1600 | { |
| 1577 | #ifdef CONFIG_IRQ_REMAP | 1601 | if (x2apic_enabled()) { |
| 1578 | if (!irq_remapping_supported()) { | 1602 | pr_info("x2apic: enabled by BIOS, switching to x2apic ops\n"); |
| 1579 | pr_debug("intr-remapping not supported\n"); | 1603 | x2apic_mode = 1; |
| 1580 | return -1; | 1604 | x2apic_state = X2APIC_ON; |
| 1605 | } else if (!cpu_has_x2apic) { | ||
| 1606 | x2apic_state = X2APIC_DISABLED; | ||
| 1581 | } | 1607 | } |
| 1608 | } | ||
| 1609 | #else /* CONFIG_X86_X2APIC */ | ||
| 1610 | static int __init validate_x2apic(void) | ||
| 1611 | { | ||
| 1612 | if (!apic_is_x2apic_enabled()) | ||
| 1613 | return 0; | ||
| 1614 | /* | ||
| 1615 | * Checkme: Can we simply turn off x2apic here instead of panic? | ||
| 1616 | */ | ||
| 1617 | panic("BIOS has enabled x2apic but kernel doesn't support x2apic, please disable x2apic in BIOS.\n"); | ||
| 1618 | } | ||
| 1619 | early_initcall(validate_x2apic); | ||
| 1582 | 1620 | ||
| 1583 | if (!x2apic_preenabled && skip_ioapic_setup) { | 1621 | static inline void try_to_enable_x2apic(int remap_mode) { } |
| 1584 | pr_info("Skipped enabling intr-remap because of skipping " | 1622 | static inline void __x2apic_enable(void) { } |
| 1585 | "io-apic setup\n"); | 1623 | #endif /* !CONFIG_X86_X2APIC */ |
| 1624 | |||
| 1625 | static int __init try_to_enable_IR(void) | ||
| 1626 | { | ||
| 1627 | #ifdef CONFIG_X86_IO_APIC | ||
| 1628 | if (!x2apic_enabled() && skip_ioapic_setup) { | ||
| 1629 | pr_info("Not enabling interrupt remapping due to skipped IO-APIC setup\n"); | ||
| 1586 | return -1; | 1630 | return -1; |
| 1587 | } | 1631 | } |
| 1588 | |||
| 1589 | return irq_remapping_enable(); | ||
| 1590 | #endif | 1632 | #endif |
| 1591 | return -1; | 1633 | return irq_remapping_enable(); |
| 1592 | } | 1634 | } |
| 1593 | 1635 | ||
| 1594 | void __init enable_IR_x2apic(void) | 1636 | void __init enable_IR_x2apic(void) |
| 1595 | { | 1637 | { |
| 1596 | unsigned long flags; | 1638 | unsigned long flags; |
| 1597 | int ret, x2apic_enabled = 0; | 1639 | int ret, ir_stat; |
| 1598 | int hardware_init_ret; | ||
| 1599 | |||
| 1600 | /* Make sure irq_remap_ops are initialized */ | ||
| 1601 | setup_irq_remapping_ops(); | ||
| 1602 | 1640 | ||
| 1603 | hardware_init_ret = irq_remapping_prepare(); | 1641 | ir_stat = irq_remapping_prepare(); |
| 1604 | if (hardware_init_ret && !x2apic_supported()) | 1642 | if (ir_stat < 0 && !x2apic_supported()) |
| 1605 | return; | 1643 | return; |
| 1606 | 1644 | ||
| 1607 | ret = save_ioapic_entries(); | 1645 | ret = save_ioapic_entries(); |
| @@ -1614,49 +1652,13 @@ void __init enable_IR_x2apic(void) | |||
| 1614 | legacy_pic->mask_all(); | 1652 | legacy_pic->mask_all(); |
| 1615 | mask_ioapic_entries(); | 1653 | mask_ioapic_entries(); |
| 1616 | 1654 | ||
| 1617 | if (x2apic_preenabled && nox2apic) | 1655 | /* If irq_remapping_prepare() succeded, try to enable it */ |
| 1618 | disable_x2apic(); | 1656 | if (ir_stat >= 0) |
| 1619 | 1657 | ir_stat = try_to_enable_IR(); | |
| 1620 | if (hardware_init_ret) | 1658 | /* ir_stat contains the remap mode or an error code */ |
| 1621 | ret = -1; | 1659 | try_to_enable_x2apic(ir_stat); |
| 1622 | else | ||
| 1623 | ret = enable_IR(); | ||
| 1624 | |||
| 1625 | if (!x2apic_supported()) | ||
| 1626 | goto skip_x2apic; | ||
| 1627 | 1660 | ||
| 1628 | if (ret < 0) { | 1661 | if (ir_stat < 0) |
| 1629 | /* IR is required if there is APIC ID > 255 even when running | ||
| 1630 | * under KVM | ||
| 1631 | */ | ||
| 1632 | if (max_physical_apicid > 255 || | ||
| 1633 | !hypervisor_x2apic_available()) { | ||
| 1634 | if (x2apic_preenabled) | ||
| 1635 | disable_x2apic(); | ||
| 1636 | goto skip_x2apic; | ||
| 1637 | } | ||
| 1638 | /* | ||
| 1639 | * without IR all CPUs can be addressed by IOAPIC/MSI | ||
| 1640 | * only in physical mode | ||
| 1641 | */ | ||
| 1642 | x2apic_force_phys(); | ||
| 1643 | } | ||
| 1644 | |||
| 1645 | if (ret == IRQ_REMAP_XAPIC_MODE) { | ||
| 1646 | pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n"); | ||
| 1647 | goto skip_x2apic; | ||
| 1648 | } | ||
| 1649 | |||
| 1650 | x2apic_enabled = 1; | ||
| 1651 | |||
| 1652 | if (x2apic_supported() && !x2apic_mode) { | ||
| 1653 | x2apic_mode = 1; | ||
| 1654 | enable_x2apic(); | ||
| 1655 | pr_info("Enabled x2apic\n"); | ||
| 1656 | } | ||
| 1657 | |||
| 1658 | skip_x2apic: | ||
| 1659 | if (ret < 0) /* IR enabling failed */ | ||
| 1660 | restore_ioapic_entries(); | 1662 | restore_ioapic_entries(); |
| 1661 | legacy_pic->restore_mask(); | 1663 | legacy_pic->restore_mask(); |
| 1662 | local_irq_restore(flags); | 1664 | local_irq_restore(flags); |
| @@ -1847,82 +1849,8 @@ void __init register_lapic_address(unsigned long address) | |||
| 1847 | } | 1849 | } |
| 1848 | } | 1850 | } |
| 1849 | 1851 | ||
| 1850 | /* | ||
| 1851 | * This initializes the IO-APIC and APIC hardware if this is | ||
| 1852 | * a UP kernel. | ||
| 1853 | */ | ||
| 1854 | int apic_version[MAX_LOCAL_APIC]; | 1852 | int apic_version[MAX_LOCAL_APIC]; |
| 1855 | 1853 | ||
| 1856 | int __init APIC_init_uniprocessor(void) | ||
| 1857 | { | ||
| 1858 | if (disable_apic) { | ||
| 1859 | pr_info("Apic disabled\n"); | ||
| 1860 | return -1; | ||
| 1861 | } | ||
| 1862 | #ifdef CONFIG_X86_64 | ||
| 1863 | if (!cpu_has_apic) { | ||
| 1864 | disable_apic = 1; | ||
| 1865 | pr_info("Apic disabled by BIOS\n"); | ||
| 1866 | return -1; | ||
| 1867 | } | ||
| 1868 | #else | ||
| 1869 | if (!smp_found_config && !cpu_has_apic) | ||
| 1870 | return -1; | ||
| 1871 | |||
| 1872 | /* | ||
| 1873 | * Complain if the BIOS pretends there is one. | ||
| 1874 | */ | ||
| 1875 | if (!cpu_has_apic && | ||
| 1876 | APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { | ||
| 1877 | pr_err("BIOS bug, local APIC 0x%x not detected!...\n", | ||
| 1878 | boot_cpu_physical_apicid); | ||
| 1879 | return -1; | ||
| 1880 | } | ||
| 1881 | #endif | ||
| 1882 | |||
| 1883 | default_setup_apic_routing(); | ||
| 1884 | |||
| 1885 | verify_local_APIC(); | ||
| 1886 | connect_bsp_APIC(); | ||
| 1887 | |||
| 1888 | #ifdef CONFIG_X86_64 | ||
| 1889 | apic_write(APIC_ID, SET_APIC_ID(boot_cpu_physical_apicid)); | ||
| 1890 | #else | ||
| 1891 | /* | ||
| 1892 | * Hack: In case of kdump, after a crash, kernel might be booting | ||
| 1893 | * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid | ||
| 1894 | * might be zero if read from MP tables. Get it from LAPIC. | ||
| 1895 | */ | ||
| 1896 | # ifdef CONFIG_CRASH_DUMP | ||
| 1897 | boot_cpu_physical_apicid = read_apic_id(); | ||
| 1898 | # endif | ||
| 1899 | #endif | ||
| 1900 | physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); | ||
| 1901 | setup_local_APIC(); | ||
| 1902 | |||
| 1903 | #ifdef CONFIG_X86_IO_APIC | ||
| 1904 | /* | ||
| 1905 | * Now enable IO-APICs, actually call clear_IO_APIC | ||
| 1906 | * We need clear_IO_APIC before enabling error vector | ||
| 1907 | */ | ||
| 1908 | if (!skip_ioapic_setup && nr_ioapics) | ||
| 1909 | enable_IO_APIC(); | ||
| 1910 | #endif | ||
| 1911 | |||
| 1912 | bsp_end_local_APIC_setup(); | ||
| 1913 | |||
| 1914 | #ifdef CONFIG_X86_IO_APIC | ||
| 1915 | if (smp_found_config && !skip_ioapic_setup && nr_ioapics) | ||
| 1916 | setup_IO_APIC(); | ||
| 1917 | else { | ||
| 1918 | nr_ioapics = 0; | ||
| 1919 | } | ||
| 1920 | #endif | ||
| 1921 | |||
| 1922 | x86_init.timers.setup_percpu_clockev(); | ||
| 1923 | return 0; | ||
| 1924 | } | ||
| 1925 | |||
| 1926 | /* | 1854 | /* |
| 1927 | * Local APIC interrupts | 1855 | * Local APIC interrupts |
| 1928 | */ | 1856 | */ |
| @@ -2027,7 +1955,7 @@ __visible void smp_trace_error_interrupt(struct pt_regs *regs) | |||
| 2027 | /** | 1955 | /** |
| 2028 | * connect_bsp_APIC - attach the APIC to the interrupt system | 1956 | * connect_bsp_APIC - attach the APIC to the interrupt system |
| 2029 | */ | 1957 | */ |
| 2030 | void __init connect_bsp_APIC(void) | 1958 | static void __init connect_bsp_APIC(void) |
| 2031 | { | 1959 | { |
| 2032 | #ifdef CONFIG_X86_32 | 1960 | #ifdef CONFIG_X86_32 |
| 2033 | if (pic_mode) { | 1961 | if (pic_mode) { |
| @@ -2274,6 +2202,100 @@ void __init apic_set_eoi_write(void (*eoi_write)(u32 reg, u32 v)) | |||
| 2274 | } | 2202 | } |
| 2275 | } | 2203 | } |
| 2276 | 2204 | ||
| 2205 | static void __init apic_bsp_up_setup(void) | ||
| 2206 | { | ||
| 2207 | #ifdef CONFIG_X86_64 | ||
| 2208 | apic_write(APIC_ID, SET_APIC_ID(boot_cpu_physical_apicid)); | ||
| 2209 | #else | ||
| 2210 | /* | ||
| 2211 | * Hack: In case of kdump, after a crash, kernel might be booting | ||
| 2212 | * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid | ||
| 2213 | * might be zero if read from MP tables. Get it from LAPIC. | ||
| 2214 | */ | ||
| 2215 | # ifdef CONFIG_CRASH_DUMP | ||
| 2216 | boot_cpu_physical_apicid = read_apic_id(); | ||
| 2217 | # endif | ||
| 2218 | #endif | ||
| 2219 | physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); | ||
| 2220 | } | ||
| 2221 | |||
| 2222 | /** | ||
| 2223 | * apic_bsp_setup - Setup function for local apic and io-apic | ||
| 2224 | * @upmode: Force UP mode (for APIC_init_uniprocessor) | ||
| 2225 | * | ||
| 2226 | * Returns: | ||
| 2227 | * apic_id of BSP APIC | ||
| 2228 | */ | ||
| 2229 | int __init apic_bsp_setup(bool upmode) | ||
| 2230 | { | ||
| 2231 | int id; | ||
| 2232 | |||
| 2233 | connect_bsp_APIC(); | ||
| 2234 | if (upmode) | ||
| 2235 | apic_bsp_up_setup(); | ||
| 2236 | setup_local_APIC(); | ||
| 2237 | |||
| 2238 | if (x2apic_mode) | ||
| 2239 | id = apic_read(APIC_LDR); | ||
| 2240 | else | ||
| 2241 | id = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR)); | ||
| 2242 | |||
| 2243 | enable_IO_APIC(); | ||
| 2244 | end_local_APIC_setup(); | ||
| 2245 | irq_remap_enable_fault_handling(); | ||
| 2246 | setup_IO_APIC(); | ||
| 2247 | /* Setup local timer */ | ||
| 2248 | x86_init.timers.setup_percpu_clockev(); | ||
| 2249 | return id; | ||
| 2250 | } | ||
| 2251 | |||
| 2252 | /* | ||
| 2253 | * This initializes the IO-APIC and APIC hardware if this is | ||
| 2254 | * a UP kernel. | ||
| 2255 | */ | ||
| 2256 | int __init APIC_init_uniprocessor(void) | ||
| 2257 | { | ||
| 2258 | if (disable_apic) { | ||
| 2259 | pr_info("Apic disabled\n"); | ||
| 2260 | return -1; | ||
| 2261 | } | ||
| 2262 | #ifdef CONFIG_X86_64 | ||
| 2263 | if (!cpu_has_apic) { | ||
| 2264 | disable_apic = 1; | ||
| 2265 | pr_info("Apic disabled by BIOS\n"); | ||
| 2266 | return -1; | ||
| 2267 | } | ||
| 2268 | #else | ||
| 2269 | if (!smp_found_config && !cpu_has_apic) | ||
| 2270 | return -1; | ||
| 2271 | |||
| 2272 | /* | ||
| 2273 | * Complain if the BIOS pretends there is one. | ||
| 2274 | */ | ||
| 2275 | if (!cpu_has_apic && | ||
| 2276 | APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { | ||
| 2277 | pr_err("BIOS bug, local APIC 0x%x not detected!...\n", | ||
| 2278 | boot_cpu_physical_apicid); | ||
| 2279 | return -1; | ||
| 2280 | } | ||
| 2281 | #endif | ||
| 2282 | |||
| 2283 | if (!smp_found_config) | ||
| 2284 | disable_ioapic_support(); | ||
| 2285 | |||
| 2286 | default_setup_apic_routing(); | ||
| 2287 | verify_local_APIC(); | ||
| 2288 | apic_bsp_setup(true); | ||
| 2289 | return 0; | ||
| 2290 | } | ||
| 2291 | |||
| 2292 | #ifdef CONFIG_UP_LATE_INIT | ||
| 2293 | void __init up_late_init(void) | ||
| 2294 | { | ||
| 2295 | APIC_init_uniprocessor(); | ||
| 2296 | } | ||
| 2297 | #endif | ||
| 2298 | |||
| 2277 | /* | 2299 | /* |
| 2278 | * Power management | 2300 | * Power management |
| 2279 | */ | 2301 | */ |
| @@ -2359,9 +2381,9 @@ static void lapic_resume(void) | |||
| 2359 | mask_ioapic_entries(); | 2381 | mask_ioapic_entries(); |
| 2360 | legacy_pic->mask_all(); | 2382 | legacy_pic->mask_all(); |
| 2361 | 2383 | ||
| 2362 | if (x2apic_mode) | 2384 | if (x2apic_mode) { |
| 2363 | enable_x2apic(); | 2385 | __x2apic_enable(); |
| 2364 | else { | 2386 | } else { |
| 2365 | /* | 2387 | /* |
| 2366 | * Make sure the APICBASE points to the right address | 2388 | * Make sure the APICBASE points to the right address |
| 2367 | * | 2389 | * |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 3f5f60406ab1..f4dc2462a1ac 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
| @@ -1507,7 +1507,10 @@ void __init enable_IO_APIC(void) | |||
| 1507 | int i8259_apic, i8259_pin; | 1507 | int i8259_apic, i8259_pin; |
| 1508 | int apic, pin; | 1508 | int apic, pin; |
| 1509 | 1509 | ||
| 1510 | if (!nr_legacy_irqs()) | 1510 | if (skip_ioapic_setup) |
| 1511 | nr_ioapics = 0; | ||
| 1512 | |||
| 1513 | if (!nr_legacy_irqs() || !nr_ioapics) | ||
| 1511 | return; | 1514 | return; |
| 1512 | 1515 | ||
| 1513 | for_each_ioapic_pin(apic, pin) { | 1516 | for_each_ioapic_pin(apic, pin) { |
| @@ -2295,7 +2298,7 @@ static inline void __init check_timer(void) | |||
| 2295 | } | 2298 | } |
| 2296 | local_irq_disable(); | 2299 | local_irq_disable(); |
| 2297 | apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n"); | 2300 | apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n"); |
| 2298 | if (x2apic_preenabled) | 2301 | if (apic_is_x2apic_enabled()) |
| 2299 | apic_printk(APIC_QUIET, KERN_INFO | 2302 | apic_printk(APIC_QUIET, KERN_INFO |
| 2300 | "Perhaps problem with the pre-enabled x2apic mode\n" | 2303 | "Perhaps problem with the pre-enabled x2apic mode\n" |
| 2301 | "Try booting with x2apic and interrupt-remapping disabled in the bios.\n"); | 2304 | "Try booting with x2apic and interrupt-remapping disabled in the bios.\n"); |
| @@ -2373,9 +2376,9 @@ void __init setup_IO_APIC(void) | |||
| 2373 | { | 2376 | { |
| 2374 | int ioapic; | 2377 | int ioapic; |
| 2375 | 2378 | ||
| 2376 | /* | 2379 | if (skip_ioapic_setup || !nr_ioapics) |
| 2377 | * calling enable_IO_APIC() is moved to setup_local_APIC for BP | 2380 | return; |
| 2378 | */ | 2381 | |
| 2379 | io_apic_irqs = nr_legacy_irqs() ? ~PIC_IRQS : ~0UL; | 2382 | io_apic_irqs = nr_legacy_irqs() ? ~PIC_IRQS : ~0UL; |
| 2380 | 2383 | ||
| 2381 | apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n"); | 2384 | apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n"); |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index c6049650c093..cb5692551b98 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
| @@ -1332,7 +1332,7 @@ void cpu_init(void) | |||
| 1332 | barrier(); | 1332 | barrier(); |
| 1333 | 1333 | ||
| 1334 | x86_configure_nx(); | 1334 | x86_configure_nx(); |
| 1335 | enable_x2apic(); | 1335 | x2apic_setup(); |
| 1336 | 1336 | ||
| 1337 | /* | 1337 | /* |
| 1338 | * set up and load the per-CPU TSS | 1338 | * set up and load the per-CPU TSS |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 6d7022c683e3..febc6aabc72e 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
| @@ -73,7 +73,6 @@ | |||
| 73 | #include <asm/setup.h> | 73 | #include <asm/setup.h> |
| 74 | #include <asm/uv/uv.h> | 74 | #include <asm/uv/uv.h> |
| 75 | #include <linux/mc146818rtc.h> | 75 | #include <linux/mc146818rtc.h> |
| 76 | #include <asm/smpboot_hooks.h> | ||
| 77 | #include <asm/i8259.h> | 76 | #include <asm/i8259.h> |
| 78 | #include <asm/realmode.h> | 77 | #include <asm/realmode.h> |
| 79 | #include <asm/misc.h> | 78 | #include <asm/misc.h> |
| @@ -104,6 +103,43 @@ EXPORT_PER_CPU_SYMBOL(cpu_info); | |||
| 104 | 103 | ||
| 105 | atomic_t init_deasserted; | 104 | atomic_t init_deasserted; |
| 106 | 105 | ||
| 106 | static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip) | ||
| 107 | { | ||
| 108 | unsigned long flags; | ||
| 109 | |||
| 110 | spin_lock_irqsave(&rtc_lock, flags); | ||
| 111 | CMOS_WRITE(0xa, 0xf); | ||
| 112 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 113 | local_flush_tlb(); | ||
| 114 | pr_debug("1.\n"); | ||
| 115 | *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) = | ||
| 116 | start_eip >> 4; | ||
| 117 | pr_debug("2.\n"); | ||
| 118 | *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = | ||
| 119 | start_eip & 0xf; | ||
| 120 | pr_debug("3.\n"); | ||
| 121 | } | ||
| 122 | |||
| 123 | static inline void smpboot_restore_warm_reset_vector(void) | ||
| 124 | { | ||
| 125 | unsigned long flags; | ||
| 126 | |||
| 127 | /* | ||
| 128 | * Install writable page 0 entry to set BIOS data area. | ||
| 129 | */ | ||
| 130 | local_flush_tlb(); | ||
| 131 | |||
| 132 | /* | ||
| 133 | * Paranoid: Set warm reset code and vector here back | ||
| 134 | * to default values. | ||
| 135 | */ | ||
| 136 | spin_lock_irqsave(&rtc_lock, flags); | ||
| 137 | CMOS_WRITE(0, 0xf); | ||
| 138 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 139 | |||
| 140 | *((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0; | ||
| 141 | } | ||
| 142 | |||
| 107 | /* | 143 | /* |
| 108 | * Report back to the Boot Processor during boot time or to the caller processor | 144 | * Report back to the Boot Processor during boot time or to the caller processor |
| 109 | * during CPU online. | 145 | * during CPU online. |
| @@ -136,8 +172,7 @@ static void smp_callin(void) | |||
| 136 | * CPU, first the APIC. (this is probably redundant on most | 172 | * CPU, first the APIC. (this is probably redundant on most |
| 137 | * boards) | 173 | * boards) |
| 138 | */ | 174 | */ |
| 139 | setup_local_APIC(); | 175 | apic_ap_setup(); |
| 140 | end_local_APIC_setup(); | ||
| 141 | 176 | ||
| 142 | /* | 177 | /* |
| 143 | * Need to setup vector mappings before we enable interrupts. | 178 | * Need to setup vector mappings before we enable interrupts. |
| @@ -955,9 +990,12 @@ void arch_disable_smp_support(void) | |||
| 955 | */ | 990 | */ |
| 956 | static __init void disable_smp(void) | 991 | static __init void disable_smp(void) |
| 957 | { | 992 | { |
| 993 | pr_info("SMP disabled\n"); | ||
| 994 | |||
| 995 | disable_ioapic_support(); | ||
| 996 | |||
| 958 | init_cpu_present(cpumask_of(0)); | 997 | init_cpu_present(cpumask_of(0)); |
| 959 | init_cpu_possible(cpumask_of(0)); | 998 | init_cpu_possible(cpumask_of(0)); |
| 960 | smpboot_clear_io_apic_irqs(); | ||
| 961 | 999 | ||
| 962 | if (smp_found_config) | 1000 | if (smp_found_config) |
| 963 | physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); | 1001 | physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map); |
| @@ -967,6 +1005,13 @@ static __init void disable_smp(void) | |||
| 967 | cpumask_set_cpu(0, cpu_core_mask(0)); | 1005 | cpumask_set_cpu(0, cpu_core_mask(0)); |
| 968 | } | 1006 | } |
| 969 | 1007 | ||
| 1008 | enum { | ||
| 1009 | SMP_OK, | ||
| 1010 | SMP_NO_CONFIG, | ||
| 1011 | SMP_NO_APIC, | ||
| 1012 | SMP_FORCE_UP, | ||
| 1013 | }; | ||
| 1014 | |||
| 970 | /* | 1015 | /* |
| 971 | * Various sanity checks. | 1016 | * Various sanity checks. |
| 972 | */ | 1017 | */ |
| @@ -1014,10 +1059,7 @@ static int __init smp_sanity_check(unsigned max_cpus) | |||
| 1014 | if (!smp_found_config && !acpi_lapic) { | 1059 | if (!smp_found_config && !acpi_lapic) { |
| 1015 | preempt_enable(); | 1060 | preempt_enable(); |
| 1016 | pr_notice("SMP motherboard not detected\n"); | 1061 | pr_notice("SMP motherboard not detected\n"); |
| 1017 | disable_smp(); | 1062 | return SMP_NO_CONFIG; |
| 1018 | if (APIC_init_uniprocessor()) | ||
| 1019 | pr_notice("Local APIC not detected. Using dummy APIC emulation.\n"); | ||
| 1020 | return -1; | ||
| 1021 | } | 1063 | } |
| 1022 | 1064 | ||
| 1023 | /* | 1065 | /* |
| @@ -1041,9 +1083,7 @@ static int __init smp_sanity_check(unsigned max_cpus) | |||
| 1041 | boot_cpu_physical_apicid); | 1083 | boot_cpu_physical_apicid); |
| 1042 | pr_err("... forcing use of dummy APIC emulation (tell your hw vendor)\n"); | 1084 | pr_err("... forcing use of dummy APIC emulation (tell your hw vendor)\n"); |
| 1043 | } | 1085 | } |
| 1044 | smpboot_clear_io_apic(); | 1086 | return SMP_NO_APIC; |
| 1045 | disable_ioapic_support(); | ||
| 1046 | return -1; | ||
| 1047 | } | 1087 | } |
| 1048 | 1088 | ||
| 1049 | verify_local_APIC(); | 1089 | verify_local_APIC(); |
| @@ -1053,15 +1093,10 @@ static int __init smp_sanity_check(unsigned max_cpus) | |||
| 1053 | */ | 1093 | */ |
| 1054 | if (!max_cpus) { | 1094 | if (!max_cpus) { |
| 1055 | pr_info("SMP mode deactivated\n"); | 1095 | pr_info("SMP mode deactivated\n"); |
| 1056 | smpboot_clear_io_apic(); | 1096 | return SMP_FORCE_UP; |
| 1057 | |||
| 1058 | connect_bsp_APIC(); | ||
| 1059 | setup_local_APIC(); | ||
| 1060 | bsp_end_local_APIC_setup(); | ||
| 1061 | return -1; | ||
| 1062 | } | 1097 | } |
| 1063 | 1098 | ||
| 1064 | return 0; | 1099 | return SMP_OK; |
| 1065 | } | 1100 | } |
| 1066 | 1101 | ||
| 1067 | static void __init smp_cpu_index_default(void) | 1102 | static void __init smp_cpu_index_default(void) |
| @@ -1101,10 +1136,21 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) | |||
| 1101 | } | 1136 | } |
| 1102 | set_cpu_sibling_map(0); | 1137 | set_cpu_sibling_map(0); |
| 1103 | 1138 | ||
| 1104 | if (smp_sanity_check(max_cpus) < 0) { | 1139 | switch (smp_sanity_check(max_cpus)) { |
| 1105 | pr_info("SMP disabled\n"); | 1140 | case SMP_NO_CONFIG: |
| 1106 | disable_smp(); | 1141 | disable_smp(); |
| 1142 | if (APIC_init_uniprocessor()) | ||
| 1143 | pr_notice("Local APIC not detected. Using dummy APIC emulation.\n"); | ||
| 1107 | return; | 1144 | return; |
| 1145 | case SMP_NO_APIC: | ||
| 1146 | disable_smp(); | ||
| 1147 | return; | ||
| 1148 | case SMP_FORCE_UP: | ||
| 1149 | disable_smp(); | ||
| 1150 | apic_bsp_setup(false); | ||
| 1151 | return; | ||
| 1152 | case SMP_OK: | ||
| 1153 | break; | ||
| 1108 | } | 1154 | } |
| 1109 | 1155 | ||
| 1110 | default_setup_apic_routing(); | 1156 | default_setup_apic_routing(); |
| @@ -1115,33 +1161,10 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) | |||
| 1115 | /* Or can we switch back to PIC here? */ | 1161 | /* Or can we switch back to PIC here? */ |
| 1116 | } | 1162 | } |
| 1117 | 1163 | ||
| 1118 | connect_bsp_APIC(); | 1164 | cpu0_logical_apicid = apic_bsp_setup(false); |
| 1119 | |||
| 1120 | /* | ||
| 1121 | * Switch from PIC to APIC mode. | ||
| 1122 | */ | ||
| 1123 | setup_local_APIC(); | ||
| 1124 | |||
| 1125 | if (x2apic_mode) | ||
| 1126 | cpu0_logical_apicid = apic_read(APIC_LDR); | ||
| 1127 | else | ||
| 1128 | cpu0_logical_apicid = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR)); | ||
| 1129 | |||
| 1130 | /* | ||
| 1131 | * Enable IO APIC before setting up error vector | ||
| 1132 | */ | ||
| 1133 | if (!skip_ioapic_setup && nr_ioapics) | ||
| 1134 | enable_IO_APIC(); | ||
| 1135 | |||
| 1136 | bsp_end_local_APIC_setup(); | ||
| 1137 | smpboot_setup_io_apic(); | ||
| 1138 | /* | ||
| 1139 | * Set up local APIC timer on boot CPU. | ||
| 1140 | */ | ||
| 1141 | 1165 | ||
| 1142 | pr_info("CPU%d: ", 0); | 1166 | pr_info("CPU%d: ", 0); |
| 1143 | print_cpu_info(&cpu_data(0)); | 1167 | print_cpu_info(&cpu_data(0)); |
| 1144 | x86_init.timers.setup_percpu_clockev(); | ||
| 1145 | 1168 | ||
| 1146 | if (is_uv_system()) | 1169 | if (is_uv_system()) |
| 1147 | uv_system_init(); | 1170 | uv_system_init(); |
| @@ -1177,9 +1200,7 @@ void __init native_smp_cpus_done(unsigned int max_cpus) | |||
| 1177 | 1200 | ||
| 1178 | nmi_selftest(); | 1201 | nmi_selftest(); |
| 1179 | impress_friends(); | 1202 | impress_friends(); |
| 1180 | #ifdef CONFIG_X86_IO_APIC | ||
| 1181 | setup_ioapic_dest(); | 1203 | setup_ioapic_dest(); |
| 1182 | #endif | ||
| 1183 | mtrr_aps_init(); | 1204 | mtrr_aps_init(); |
| 1184 | } | 1205 | } |
| 1185 | 1206 | ||
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 98024856df07..59de6364a910 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
| @@ -4284,7 +4284,6 @@ static int alloc_hpet_msi(unsigned int irq, unsigned int id) | |||
| 4284 | } | 4284 | } |
| 4285 | 4285 | ||
| 4286 | struct irq_remap_ops amd_iommu_irq_ops = { | 4286 | struct irq_remap_ops amd_iommu_irq_ops = { |
| 4287 | .supported = amd_iommu_supported, | ||
| 4288 | .prepare = amd_iommu_prepare, | 4287 | .prepare = amd_iommu_prepare, |
| 4289 | .enable = amd_iommu_enable, | 4288 | .enable = amd_iommu_enable, |
| 4290 | .disable = amd_iommu_disable, | 4289 | .disable = amd_iommu_disable, |
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index b0522f15730f..9a20248e7068 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c | |||
| @@ -2014,9 +2014,6 @@ static bool detect_ivrs(void) | |||
| 2014 | /* Make sure ACS will be enabled during PCI probe */ | 2014 | /* Make sure ACS will be enabled during PCI probe */ |
| 2015 | pci_request_acs(); | 2015 | pci_request_acs(); |
| 2016 | 2016 | ||
| 2017 | if (!disable_irq_remap) | ||
| 2018 | amd_iommu_irq_remap = true; | ||
| 2019 | |||
| 2020 | return true; | 2017 | return true; |
| 2021 | } | 2018 | } |
| 2022 | 2019 | ||
| @@ -2123,12 +2120,14 @@ static int __init iommu_go_to_state(enum iommu_init_state state) | |||
| 2123 | #ifdef CONFIG_IRQ_REMAP | 2120 | #ifdef CONFIG_IRQ_REMAP |
| 2124 | int __init amd_iommu_prepare(void) | 2121 | int __init amd_iommu_prepare(void) |
| 2125 | { | 2122 | { |
| 2126 | return iommu_go_to_state(IOMMU_ACPI_FINISHED); | 2123 | int ret; |
| 2127 | } | ||
| 2128 | 2124 | ||
| 2129 | int __init amd_iommu_supported(void) | 2125 | amd_iommu_irq_remap = true; |
| 2130 | { | 2126 | |
| 2131 | return amd_iommu_irq_remap ? 1 : 0; | 2127 | ret = iommu_go_to_state(IOMMU_ACPI_FINISHED); |
| 2128 | if (ret) | ||
| 2129 | return ret; | ||
| 2130 | return amd_iommu_irq_remap ? 0 : -ENODEV; | ||
| 2132 | } | 2131 | } |
| 2133 | 2132 | ||
| 2134 | int __init amd_iommu_enable(void) | 2133 | int __init amd_iommu_enable(void) |
diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h index 95ed6deae47f..861af9d8338a 100644 --- a/drivers/iommu/amd_iommu_proto.h +++ b/drivers/iommu/amd_iommu_proto.h | |||
| @@ -33,7 +33,6 @@ extern void amd_iommu_init_notifier(void); | |||
| 33 | extern void amd_iommu_init_api(void); | 33 | extern void amd_iommu_init_api(void); |
| 34 | 34 | ||
| 35 | /* Needed for interrupt remapping */ | 35 | /* Needed for interrupt remapping */ |
| 36 | extern int amd_iommu_supported(void); | ||
| 37 | extern int amd_iommu_prepare(void); | 36 | extern int amd_iommu_prepare(void); |
| 38 | extern int amd_iommu_enable(void); | 37 | extern int amd_iommu_enable(void); |
| 39 | extern void amd_iommu_disable(void); | 38 | extern void amd_iommu_disable(void); |
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index a55b207b9425..14de1ab223c8 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c | |||
| @@ -32,8 +32,9 @@ struct hpet_scope { | |||
| 32 | }; | 32 | }; |
| 33 | 33 | ||
| 34 | #define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0) | 34 | #define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0) |
| 35 | #define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8) | 35 | #define IRTE_DEST(dest) ((eim_mode) ? dest : dest << 8) |
| 36 | 36 | ||
| 37 | static int __read_mostly eim_mode; | ||
| 37 | static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; | 38 | static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; |
| 38 | static struct hpet_scope ir_hpet[MAX_HPET_TBS]; | 39 | static struct hpet_scope ir_hpet[MAX_HPET_TBS]; |
| 39 | 40 | ||
| @@ -481,11 +482,11 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu) | |||
| 481 | if (iommu->ir_table) | 482 | if (iommu->ir_table) |
| 482 | return 0; | 483 | return 0; |
| 483 | 484 | ||
| 484 | ir_table = kzalloc(sizeof(struct ir_table), GFP_ATOMIC); | 485 | ir_table = kzalloc(sizeof(struct ir_table), GFP_KERNEL); |
| 485 | if (!ir_table) | 486 | if (!ir_table) |
| 486 | return -ENOMEM; | 487 | return -ENOMEM; |
| 487 | 488 | ||
| 488 | pages = alloc_pages_node(iommu->node, GFP_ATOMIC | __GFP_ZERO, | 489 | pages = alloc_pages_node(iommu->node, GFP_KERNEL | __GFP_ZERO, |
| 489 | INTR_REMAP_PAGE_ORDER); | 490 | INTR_REMAP_PAGE_ORDER); |
| 490 | 491 | ||
| 491 | if (!pages) { | 492 | if (!pages) { |
| @@ -566,13 +567,27 @@ static int __init dmar_x2apic_optout(void) | |||
| 566 | return dmar->flags & DMAR_X2APIC_OPT_OUT; | 567 | return dmar->flags & DMAR_X2APIC_OPT_OUT; |
| 567 | } | 568 | } |
| 568 | 569 | ||
| 569 | static int __init intel_irq_remapping_supported(void) | 570 | static void __init intel_cleanup_irq_remapping(void) |
| 571 | { | ||
| 572 | struct dmar_drhd_unit *drhd; | ||
| 573 | struct intel_iommu *iommu; | ||
| 574 | |||
| 575 | for_each_iommu(iommu, drhd) { | ||
| 576 | if (ecap_ir_support(iommu->ecap)) { | ||
| 577 | iommu_disable_irq_remapping(iommu); | ||
| 578 | intel_teardown_irq_remapping(iommu); | ||
| 579 | } | ||
| 580 | } | ||
| 581 | |||
| 582 | if (x2apic_supported()) | ||
| 583 | pr_warn("Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n"); | ||
| 584 | } | ||
| 585 | |||
| 586 | static int __init intel_prepare_irq_remapping(void) | ||
| 570 | { | 587 | { |
| 571 | struct dmar_drhd_unit *drhd; | 588 | struct dmar_drhd_unit *drhd; |
| 572 | struct intel_iommu *iommu; | 589 | struct intel_iommu *iommu; |
| 573 | 590 | ||
| 574 | if (disable_irq_remap) | ||
| 575 | return 0; | ||
| 576 | if (irq_remap_broken) { | 591 | if (irq_remap_broken) { |
| 577 | printk(KERN_WARNING | 592 | printk(KERN_WARNING |
| 578 | "This system BIOS has enabled interrupt remapping\n" | 593 | "This system BIOS has enabled interrupt remapping\n" |
| @@ -581,38 +596,45 @@ static int __init intel_irq_remapping_supported(void) | |||
| 581 | "interrupt remapping is being disabled. Please\n" | 596 | "interrupt remapping is being disabled. Please\n" |
| 582 | "contact your BIOS vendor for an update\n"); | 597 | "contact your BIOS vendor for an update\n"); |
| 583 | add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); | 598 | add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); |
| 584 | disable_irq_remap = 1; | 599 | return -ENODEV; |
| 585 | return 0; | ||
| 586 | } | 600 | } |
| 587 | 601 | ||
| 602 | if (dmar_table_init() < 0) | ||
| 603 | return -ENODEV; | ||
| 604 | |||
| 588 | if (!dmar_ir_support()) | 605 | if (!dmar_ir_support()) |
| 589 | return 0; | 606 | return -ENODEV; |
| 607 | |||
| 608 | if (parse_ioapics_under_ir() != 1) { | ||
| 609 | printk(KERN_INFO "Not enabling interrupt remapping\n"); | ||
| 610 | goto error; | ||
| 611 | } | ||
| 590 | 612 | ||
| 613 | /* First make sure all IOMMUs support IRQ remapping */ | ||
| 591 | for_each_iommu(iommu, drhd) | 614 | for_each_iommu(iommu, drhd) |
| 592 | if (!ecap_ir_support(iommu->ecap)) | 615 | if (!ecap_ir_support(iommu->ecap)) |
| 593 | return 0; | 616 | goto error; |
| 594 | 617 | ||
| 595 | return 1; | 618 | /* Do the allocations early */ |
| 619 | for_each_iommu(iommu, drhd) | ||
| 620 | if (intel_setup_irq_remapping(iommu)) | ||
| 621 | goto error; | ||
| 622 | |||
| 623 | return 0; | ||
| 624 | |||
| 625 | error: | ||
| 626 | intel_cleanup_irq_remapping(); | ||
| 627 | return -ENODEV; | ||
| 596 | } | 628 | } |
| 597 | 629 | ||
| 598 | static int __init intel_enable_irq_remapping(void) | 630 | static int __init intel_enable_irq_remapping(void) |
| 599 | { | 631 | { |
| 600 | struct dmar_drhd_unit *drhd; | 632 | struct dmar_drhd_unit *drhd; |
| 601 | struct intel_iommu *iommu; | 633 | struct intel_iommu *iommu; |
| 602 | bool x2apic_present; | ||
| 603 | int setup = 0; | 634 | int setup = 0; |
| 604 | int eim = 0; | 635 | int eim = 0; |
| 605 | 636 | ||
| 606 | x2apic_present = x2apic_supported(); | 637 | if (x2apic_supported()) { |
| 607 | |||
| 608 | if (parse_ioapics_under_ir() != 1) { | ||
| 609 | printk(KERN_INFO "Not enable interrupt remapping\n"); | ||
| 610 | goto error; | ||
| 611 | } | ||
| 612 | |||
| 613 | if (x2apic_present) { | ||
| 614 | pr_info("Queued invalidation will be enabled to support x2apic and Intr-remapping.\n"); | ||
| 615 | |||
| 616 | eim = !dmar_x2apic_optout(); | 638 | eim = !dmar_x2apic_optout(); |
| 617 | if (!eim) | 639 | if (!eim) |
| 618 | printk(KERN_WARNING | 640 | printk(KERN_WARNING |
| @@ -646,16 +668,15 @@ static int __init intel_enable_irq_remapping(void) | |||
| 646 | /* | 668 | /* |
| 647 | * check for the Interrupt-remapping support | 669 | * check for the Interrupt-remapping support |
| 648 | */ | 670 | */ |
| 649 | for_each_iommu(iommu, drhd) { | 671 | for_each_iommu(iommu, drhd) |
| 650 | if (!ecap_ir_support(iommu->ecap)) | ||
| 651 | continue; | ||
| 652 | |||
| 653 | if (eim && !ecap_eim_support(iommu->ecap)) { | 672 | if (eim && !ecap_eim_support(iommu->ecap)) { |
| 654 | printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, " | 673 | printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, " |
| 655 | " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap); | 674 | " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap); |
| 656 | goto error; | 675 | eim = 0; |
| 657 | } | 676 | } |
| 658 | } | 677 | eim_mode = eim; |
| 678 | if (eim) | ||
| 679 | pr_info("Queued invalidation will be enabled to support x2apic and Intr-remapping.\n"); | ||
| 659 | 680 | ||
| 660 | /* | 681 | /* |
| 661 | * Enable queued invalidation for all the DRHD's. | 682 | * Enable queued invalidation for all the DRHD's. |
| @@ -675,12 +696,6 @@ static int __init intel_enable_irq_remapping(void) | |||
| 675 | * Setup Interrupt-remapping for all the DRHD's now. | 696 | * Setup Interrupt-remapping for all the DRHD's now. |
| 676 | */ | 697 | */ |
| 677 | for_each_iommu(iommu, drhd) { | 698 | for_each_iommu(iommu, drhd) { |
| 678 | if (!ecap_ir_support(iommu->ecap)) | ||
| 679 | continue; | ||
| 680 | |||
| 681 | if (intel_setup_irq_remapping(iommu)) | ||
| 682 | goto error; | ||
| 683 | |||
| 684 | iommu_set_irq_remapping(iommu, eim); | 699 | iommu_set_irq_remapping(iommu, eim); |
| 685 | setup = 1; | 700 | setup = 1; |
| 686 | } | 701 | } |
| @@ -702,15 +717,7 @@ static int __init intel_enable_irq_remapping(void) | |||
| 702 | return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE; | 717 | return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE; |
| 703 | 718 | ||
| 704 | error: | 719 | error: |
| 705 | for_each_iommu(iommu, drhd) | 720 | intel_cleanup_irq_remapping(); |
| 706 | if (ecap_ir_support(iommu->ecap)) { | ||
| 707 | iommu_disable_irq_remapping(iommu); | ||
| 708 | intel_teardown_irq_remapping(iommu); | ||
| 709 | } | ||
| 710 | |||
| 711 | if (x2apic_present) | ||
| 712 | pr_warn("Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n"); | ||
| 713 | |||
| 714 | return -1; | 721 | return -1; |
| 715 | } | 722 | } |
| 716 | 723 | ||
| @@ -1199,8 +1206,7 @@ static int intel_alloc_hpet_msi(unsigned int irq, unsigned int id) | |||
| 1199 | } | 1206 | } |
| 1200 | 1207 | ||
| 1201 | struct irq_remap_ops intel_irq_remap_ops = { | 1208 | struct irq_remap_ops intel_irq_remap_ops = { |
| 1202 | .supported = intel_irq_remapping_supported, | 1209 | .prepare = intel_prepare_irq_remapping, |
| 1203 | .prepare = dmar_table_init, | ||
| 1204 | .enable = intel_enable_irq_remapping, | 1210 | .enable = intel_enable_irq_remapping, |
| 1205 | .disable = disable_irq_remapping, | 1211 | .disable = disable_irq_remapping, |
| 1206 | .reenable = reenable_irq_remapping, | 1212 | .reenable = reenable_irq_remapping, |
diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 89c4846683be..390079ee1350 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c | |||
| @@ -17,12 +17,11 @@ | |||
| 17 | #include "irq_remapping.h" | 17 | #include "irq_remapping.h" |
| 18 | 18 | ||
| 19 | int irq_remapping_enabled; | 19 | int irq_remapping_enabled; |
| 20 | |||
| 21 | int disable_irq_remap; | ||
| 22 | int irq_remap_broken; | 20 | int irq_remap_broken; |
| 23 | int disable_sourceid_checking; | 21 | int disable_sourceid_checking; |
| 24 | int no_x2apic_optout; | 22 | int no_x2apic_optout; |
| 25 | 23 | ||
| 24 | static int disable_irq_remap; | ||
| 26 | static struct irq_remap_ops *remap_ops; | 25 | static struct irq_remap_ops *remap_ops; |
| 27 | 26 | ||
| 28 | static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec); | 27 | static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec); |
| @@ -194,45 +193,32 @@ static __init int setup_irqremap(char *str) | |||
| 194 | } | 193 | } |
| 195 | early_param("intremap", setup_irqremap); | 194 | early_param("intremap", setup_irqremap); |
| 196 | 195 | ||
| 197 | void __init setup_irq_remapping_ops(void) | ||
| 198 | { | ||
| 199 | remap_ops = &intel_irq_remap_ops; | ||
| 200 | |||
| 201 | #ifdef CONFIG_AMD_IOMMU | ||
| 202 | if (amd_iommu_irq_ops.prepare() == 0) | ||
| 203 | remap_ops = &amd_iommu_irq_ops; | ||
| 204 | #endif | ||
| 205 | } | ||
| 206 | |||
| 207 | void set_irq_remapping_broken(void) | 196 | void set_irq_remapping_broken(void) |
| 208 | { | 197 | { |
| 209 | irq_remap_broken = 1; | 198 | irq_remap_broken = 1; |
| 210 | } | 199 | } |
| 211 | 200 | ||
| 212 | int irq_remapping_supported(void) | 201 | int __init irq_remapping_prepare(void) |
| 213 | { | 202 | { |
| 214 | if (disable_irq_remap) | 203 | if (disable_irq_remap) |
| 215 | return 0; | 204 | return -ENOSYS; |
| 216 | |||
| 217 | if (!remap_ops || !remap_ops->supported) | ||
| 218 | return 0; | ||
| 219 | |||
| 220 | return remap_ops->supported(); | ||
| 221 | } | ||
| 222 | 205 | ||
| 223 | int __init irq_remapping_prepare(void) | 206 | if (intel_irq_remap_ops.prepare() == 0) |
| 224 | { | 207 | remap_ops = &intel_irq_remap_ops; |
| 225 | if (!remap_ops || !remap_ops->prepare) | 208 | else if (IS_ENABLED(CONFIG_AMD_IOMMU) && |
| 226 | return -ENODEV; | 209 | amd_iommu_irq_ops.prepare() == 0) |
| 210 | remap_ops = &amd_iommu_irq_ops; | ||
| 211 | else | ||
| 212 | return -ENOSYS; | ||
| 227 | 213 | ||
| 228 | return remap_ops->prepare(); | 214 | return 0; |
| 229 | } | 215 | } |
| 230 | 216 | ||
| 231 | int __init irq_remapping_enable(void) | 217 | int __init irq_remapping_enable(void) |
| 232 | { | 218 | { |
| 233 | int ret; | 219 | int ret; |
| 234 | 220 | ||
| 235 | if (!remap_ops || !remap_ops->enable) | 221 | if (!remap_ops->enable) |
| 236 | return -ENODEV; | 222 | return -ENODEV; |
| 237 | 223 | ||
| 238 | ret = remap_ops->enable(); | 224 | ret = remap_ops->enable(); |
| @@ -245,22 +231,16 @@ int __init irq_remapping_enable(void) | |||
| 245 | 231 | ||
| 246 | void irq_remapping_disable(void) | 232 | void irq_remapping_disable(void) |
| 247 | { | 233 | { |
| 248 | if (!irq_remapping_enabled || | 234 | if (irq_remapping_enabled && remap_ops->disable) |
| 249 | !remap_ops || | 235 | remap_ops->disable(); |
| 250 | !remap_ops->disable) | ||
| 251 | return; | ||
| 252 | |||
| 253 | remap_ops->disable(); | ||
| 254 | } | 236 | } |
| 255 | 237 | ||
| 256 | int irq_remapping_reenable(int mode) | 238 | int irq_remapping_reenable(int mode) |
| 257 | { | 239 | { |
| 258 | if (!irq_remapping_enabled || | 240 | if (irq_remapping_enabled && remap_ops->reenable) |
| 259 | !remap_ops || | 241 | return remap_ops->reenable(mode); |
| 260 | !remap_ops->reenable) | ||
| 261 | return 0; | ||
| 262 | 242 | ||
| 263 | return remap_ops->reenable(mode); | 243 | return 0; |
| 264 | } | 244 | } |
| 265 | 245 | ||
| 266 | int __init irq_remap_enable_fault_handling(void) | 246 | int __init irq_remap_enable_fault_handling(void) |
| @@ -268,7 +248,7 @@ int __init irq_remap_enable_fault_handling(void) | |||
| 268 | if (!irq_remapping_enabled) | 248 | if (!irq_remapping_enabled) |
| 269 | return 0; | 249 | return 0; |
| 270 | 250 | ||
| 271 | if (!remap_ops || !remap_ops->enable_faulting) | 251 | if (!remap_ops->enable_faulting) |
| 272 | return -ENODEV; | 252 | return -ENODEV; |
| 273 | 253 | ||
| 274 | return remap_ops->enable_faulting(); | 254 | return remap_ops->enable_faulting(); |
| @@ -279,7 +259,7 @@ int setup_ioapic_remapped_entry(int irq, | |||
| 279 | unsigned int destination, int vector, | 259 | unsigned int destination, int vector, |
| 280 | struct io_apic_irq_attr *attr) | 260 | struct io_apic_irq_attr *attr) |
| 281 | { | 261 | { |
| 282 | if (!remap_ops || !remap_ops->setup_ioapic_entry) | 262 | if (!remap_ops->setup_ioapic_entry) |
| 283 | return -ENODEV; | 263 | return -ENODEV; |
| 284 | 264 | ||
| 285 | return remap_ops->setup_ioapic_entry(irq, entry, destination, | 265 | return remap_ops->setup_ioapic_entry(irq, entry, destination, |
| @@ -289,8 +269,7 @@ int setup_ioapic_remapped_entry(int irq, | |||
| 289 | static int set_remapped_irq_affinity(struct irq_data *data, | 269 | static int set_remapped_irq_affinity(struct irq_data *data, |
| 290 | const struct cpumask *mask, bool force) | 270 | const struct cpumask *mask, bool force) |
| 291 | { | 271 | { |
| 292 | if (!config_enabled(CONFIG_SMP) || !remap_ops || | 272 | if (!config_enabled(CONFIG_SMP) || !remap_ops->set_affinity) |
| 293 | !remap_ops->set_affinity) | ||
| 294 | return 0; | 273 | return 0; |
| 295 | 274 | ||
| 296 | return remap_ops->set_affinity(data, mask, force); | 275 | return remap_ops->set_affinity(data, mask, force); |
| @@ -300,10 +279,7 @@ void free_remapped_irq(int irq) | |||
| 300 | { | 279 | { |
| 301 | struct irq_cfg *cfg = irq_cfg(irq); | 280 | struct irq_cfg *cfg = irq_cfg(irq); |
| 302 | 281 | ||
| 303 | if (!remap_ops || !remap_ops->free_irq) | 282 | if (irq_remapped(cfg) && remap_ops->free_irq) |
| 304 | return; | ||
| 305 | |||
| 306 | if (irq_remapped(cfg)) | ||
| 307 | remap_ops->free_irq(irq); | 283 | remap_ops->free_irq(irq); |
| 308 | } | 284 | } |
| 309 | 285 | ||
| @@ -315,13 +291,13 @@ void compose_remapped_msi_msg(struct pci_dev *pdev, | |||
| 315 | 291 | ||
| 316 | if (!irq_remapped(cfg)) | 292 | if (!irq_remapped(cfg)) |
| 317 | native_compose_msi_msg(pdev, irq, dest, msg, hpet_id); | 293 | native_compose_msi_msg(pdev, irq, dest, msg, hpet_id); |
| 318 | else if (remap_ops && remap_ops->compose_msi_msg) | 294 | else if (remap_ops->compose_msi_msg) |
| 319 | remap_ops->compose_msi_msg(pdev, irq, dest, msg, hpet_id); | 295 | remap_ops->compose_msi_msg(pdev, irq, dest, msg, hpet_id); |
| 320 | } | 296 | } |
| 321 | 297 | ||
| 322 | static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec) | 298 | static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec) |
| 323 | { | 299 | { |
| 324 | if (!remap_ops || !remap_ops->msi_alloc_irq) | 300 | if (!remap_ops->msi_alloc_irq) |
| 325 | return -ENODEV; | 301 | return -ENODEV; |
| 326 | 302 | ||
| 327 | return remap_ops->msi_alloc_irq(pdev, irq, nvec); | 303 | return remap_ops->msi_alloc_irq(pdev, irq, nvec); |
| @@ -330,7 +306,7 @@ static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec) | |||
| 330 | static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq, | 306 | static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq, |
| 331 | int index, int sub_handle) | 307 | int index, int sub_handle) |
| 332 | { | 308 | { |
| 333 | if (!remap_ops || !remap_ops->msi_setup_irq) | 309 | if (!remap_ops->msi_setup_irq) |
| 334 | return -ENODEV; | 310 | return -ENODEV; |
| 335 | 311 | ||
| 336 | return remap_ops->msi_setup_irq(pdev, irq, index, sub_handle); | 312 | return remap_ops->msi_setup_irq(pdev, irq, index, sub_handle); |
| @@ -340,7 +316,7 @@ int setup_hpet_msi_remapped(unsigned int irq, unsigned int id) | |||
| 340 | { | 316 | { |
| 341 | int ret; | 317 | int ret; |
| 342 | 318 | ||
| 343 | if (!remap_ops || !remap_ops->alloc_hpet_msi) | 319 | if (!remap_ops->alloc_hpet_msi) |
| 344 | return -ENODEV; | 320 | return -ENODEV; |
| 345 | 321 | ||
| 346 | ret = remap_ops->alloc_hpet_msi(irq, id); | 322 | ret = remap_ops->alloc_hpet_msi(irq, id); |
diff --git a/drivers/iommu/irq_remapping.h b/drivers/iommu/irq_remapping.h index fde250f86e60..c448eb48340a 100644 --- a/drivers/iommu/irq_remapping.h +++ b/drivers/iommu/irq_remapping.h | |||
| @@ -31,16 +31,12 @@ struct cpumask; | |||
| 31 | struct pci_dev; | 31 | struct pci_dev; |
| 32 | struct msi_msg; | 32 | struct msi_msg; |
| 33 | 33 | ||
| 34 | extern int disable_irq_remap; | ||
| 35 | extern int irq_remap_broken; | 34 | extern int irq_remap_broken; |
| 36 | extern int disable_sourceid_checking; | 35 | extern int disable_sourceid_checking; |
| 37 | extern int no_x2apic_optout; | 36 | extern int no_x2apic_optout; |
| 38 | extern int irq_remapping_enabled; | 37 | extern int irq_remapping_enabled; |
| 39 | 38 | ||
| 40 | struct irq_remap_ops { | 39 | struct irq_remap_ops { |
| 41 | /* Check whether Interrupt Remapping is supported */ | ||
| 42 | int (*supported)(void); | ||
| 43 | |||
| 44 | /* Initializes hardware and makes it ready for remapping interrupts */ | 40 | /* Initializes hardware and makes it ready for remapping interrupts */ |
| 45 | int (*prepare)(void); | 41 | int (*prepare)(void); |
| 46 | 42 | ||
| @@ -89,7 +85,6 @@ extern struct irq_remap_ops amd_iommu_irq_ops; | |||
| 89 | #else /* CONFIG_IRQ_REMAP */ | 85 | #else /* CONFIG_IRQ_REMAP */ |
| 90 | 86 | ||
| 91 | #define irq_remapping_enabled 0 | 87 | #define irq_remapping_enabled 0 |
| 92 | #define disable_irq_remap 1 | ||
| 93 | #define irq_remap_broken 0 | 88 | #define irq_remap_broken 0 |
| 94 | 89 | ||
| 95 | #endif /* CONFIG_IRQ_REMAP */ | 90 | #endif /* CONFIG_IRQ_REMAP */ |
diff --git a/include/linux/smp.h b/include/linux/smp.h index 93dff5fff524..be91db2a7017 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h | |||
| @@ -151,6 +151,13 @@ smp_call_function_any(const struct cpumask *mask, smp_call_func_t func, | |||
| 151 | static inline void kick_all_cpus_sync(void) { } | 151 | static inline void kick_all_cpus_sync(void) { } |
| 152 | static inline void wake_up_all_idle_cpus(void) { } | 152 | static inline void wake_up_all_idle_cpus(void) { } |
| 153 | 153 | ||
| 154 | #ifdef CONFIG_UP_LATE_INIT | ||
| 155 | extern void __init up_late_init(void); | ||
| 156 | static inline void smp_init(void) { up_late_init(); } | ||
| 157 | #else | ||
| 158 | static inline void smp_init(void) { } | ||
| 159 | #endif | ||
| 160 | |||
| 154 | #endif /* !SMP */ | 161 | #endif /* !SMP */ |
| 155 | 162 | ||
| 156 | /* | 163 | /* |
diff --git a/init/main.c b/init/main.c index 61b993767db5..179ada15d08a 100644 --- a/init/main.c +++ b/init/main.c | |||
| @@ -87,10 +87,6 @@ | |||
| 87 | #include <asm/sections.h> | 87 | #include <asm/sections.h> |
| 88 | #include <asm/cacheflush.h> | 88 | #include <asm/cacheflush.h> |
| 89 | 89 | ||
| 90 | #ifdef CONFIG_X86_LOCAL_APIC | ||
| 91 | #include <asm/smp.h> | ||
| 92 | #endif | ||
| 93 | |||
| 94 | static int kernel_init(void *); | 90 | static int kernel_init(void *); |
| 95 | 91 | ||
| 96 | extern void init_IRQ(void); | 92 | extern void init_IRQ(void); |
| @@ -351,15 +347,6 @@ __setup("rdinit=", rdinit_setup); | |||
| 351 | 347 | ||
| 352 | #ifndef CONFIG_SMP | 348 | #ifndef CONFIG_SMP |
| 353 | static const unsigned int setup_max_cpus = NR_CPUS; | 349 | static const unsigned int setup_max_cpus = NR_CPUS; |
| 354 | #ifdef CONFIG_X86_LOCAL_APIC | ||
| 355 | static void __init smp_init(void) | ||
| 356 | { | ||
| 357 | APIC_init_uniprocessor(); | ||
| 358 | } | ||
| 359 | #else | ||
| 360 | #define smp_init() do { } while (0) | ||
| 361 | #endif | ||
| 362 | |||
| 363 | static inline void setup_nr_cpu_ids(void) { } | 350 | static inline void setup_nr_cpu_ids(void) { } |
| 364 | static inline void smp_prepare_cpus(unsigned int maxcpus) { } | 351 | static inline void smp_prepare_cpus(unsigned int maxcpus) { } |
| 365 | #endif | 352 | #endif |
