diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-09 19:57:56 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-09 19:57:56 -0500 |
commit | 9d43bade347143b96671b38a7f81c39a81206675 (patch) | |
tree | 9c2126fa29fdbc6274f83be653de5f014e999f32 | |
parent | 0ba97bc4b4b054b71cd348dab838a7545a27b893 (diff) | |
parent | ba360f887a4130b06c55eb93bcb4ae373b262a1c (diff) |
Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 APIC updates from Ingo Molnar:
"Continued fallout of the conversion of the x86 IRQ code to the
hierarchical irqdomain framework: more cleanups, simplifications,
memory allocation behavior enhancements, mainly in the interrupt
remapping and APIC code"
* 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (44 commits)
x86, init: Fix UP boot regression on x86_64
iommu/amd: Fix irq remapping detection logic
x86/acpi: Make acpi_[un]register_gsi_ioapic() depend on CONFIG_X86_LOCAL_APIC
x86: Consolidate boot cpu timer setup
x86/apic: Reuse apic_bsp_setup() for UP APIC setup
x86/smpboot: Sanitize uniprocessor init
x86/smpboot: Move apic init code to apic.c
init: Get rid of x86isms
x86/apic: Move apic_init_uniprocessor code
x86/smpboot: Cleanup ioapic handling
x86/apic: Sanitize ioapic handling
x86/ioapic: Add proper checks to setp/enable_IO_APIC()
x86/ioapic: Provide stub functions for IOAPIC%3Dn
x86/smpboot: Move smpboot inlines to code
x86/x2apic: Use state information for disable
x86/x2apic: Split enable and setup function
x86/x2apic: Disable x2apic from nox2apic setup
x86/x2apic: Add proper state tracking
x86/x2apic: Clarify remapping mode for x2apic enablement
x86/x2apic: Move code in conditional region
...
-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 |