]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.arch/x2APIC_PATCH_25_of_41_6e1cb38a2aef7680975e71f23de187859ee8b158
Reenabled linux-xen and xen-image build
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.arch / x2APIC_PATCH_25_of_41_6e1cb38a2aef7680975e71f23de187859ee8b158
1 From: Suresh Siddha <suresh.b.siddha@intel.com>
2 Subject: x64, x2apic/intr-remap: add x2apic support, including enabling interrupt-remapping
3 References: fate #303948 and fate #303984
4 Patch-Mainline: queued for .28
5 Commit-ID: 6e1cb38a2aef7680975e71f23de187859ee8b158
6
7 Signed-off-by: Thomas Renninger <trenn@suse.de>
8
9 x2apic support. Interrupt-remapping must be enabled before enabling x2apic,
10 this is needed to ensure that IO interrupts continue to work properly after the
11 cpu mode is changed to x2apic(which uses 32bit extended physical/cluster
12 apic id).
13
14 On systems where apicid's are > 255, BIOS can handover the control to OS in
15 x2apic mode. Or if the OS handover was in legacy xapic mode, check
16 if it is capable of x2apic mode. And if we succeed in enabling
17 Interrupt-remapping, then we can enable x2apic mode in the CPU.
18
19 Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
20 Cc: akpm@linux-foundation.org
21 Cc: arjan@linux.intel.com
22 Cc: andi@firstfloor.org
23 Cc: ebiederm@xmission.com
24 Cc: jbarnes@virtuousgeek.org
25 Cc: steiner@sgi.com
26 Signed-off-by: Ingo Molnar <mingo@elte.hu>
27
28 ---
29 Documentation/kernel-parameters.txt | 2
30 arch/x86/kernel/acpi/boot.c | 2
31 arch/x86/kernel/apic_64.c | 154 +++++++++++++++++++++++++++++++++++-
32 arch/x86/kernel/cpu/common_64.c | 2
33 arch/x86/kernel/mpparse.c | 2
34 arch/x86/kernel/setup.c | 2
35 arch/x86/kernel/smpboot.c | 5 +
36 include/asm-x86/apic.h | 14 +--
37 8 files changed, 172 insertions(+), 11 deletions(-)
38
39 --- a/Documentation/kernel-parameters.txt
40 +++ b/Documentation/kernel-parameters.txt
41 @@ -1428,6 +1428,8 @@ and is between 256 and 4096 characters.
42
43 nolapic_timer [X86-32,APIC] Do not use the local APIC timer.
44
45 + nox2apic [X86-64,APIC] Do not enable x2APIC mode.
46 +
47 noltlbs [PPC] Do not use large page/tlb entries for kernel
48 lowmem mapping on PPC40x.
49
50 --- a/arch/x86/kernel/acpi/boot.c
51 +++ b/arch/x86/kernel/acpi/boot.c
52 @@ -1351,7 +1351,9 @@ static void __init acpi_process_madt(voi
53 acpi_ioapic = 1;
54
55 smp_found_config = 1;
56 +#ifdef CONFIG_X86_32
57 setup_apic_routing();
58 +#endif
59 }
60 }
61 if (error == -EINVAL) {
62 --- a/arch/x86/kernel/apic_64.c
63 +++ b/arch/x86/kernel/apic_64.c
64 @@ -27,6 +27,7 @@
65 #include <linux/clockchips.h>
66 #include <linux/acpi_pmtmr.h>
67 #include <linux/module.h>
68 +#include <linux/dmar.h>
69
70 #include <asm/atomic.h>
71 #include <asm/smp.h>
72 @@ -39,6 +40,7 @@
73 #include <asm/proto.h>
74 #include <asm/timex.h>
75 #include <asm/apic.h>
76 +#include <asm/i8259.h>
77
78 #include <mach_ipi.h>
79 #include <mach_apic.h>
80 @@ -46,8 +48,12 @@
81 static int disable_apic_timer __cpuinitdata;
82 static int apic_calibrate_pmtmr __initdata;
83 int disable_apic;
84 +int disable_x2apic;
85 int x2apic;
86
87 +/* x2apic enabled before OS handover */
88 +int x2apic_preenabled;
89 +
90 /* Local APIC timer works in C2 */
91 int local_apic_timer_c2_ok;
92 EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
93 @@ -898,6 +904,125 @@ void __cpuinit end_local_APIC_setup(void
94 apic_pm_activate();
95 }
96
97 +void check_x2apic(void)
98 +{
99 + int msr, msr2;
100 +
101 + rdmsr(MSR_IA32_APICBASE, msr, msr2);
102 +
103 + if (msr & X2APIC_ENABLE) {
104 + printk("x2apic enabled by BIOS, switching to x2apic ops\n");
105 + x2apic_preenabled = x2apic = 1;
106 + apic_ops = &x2apic_ops;
107 + }
108 +}
109 +
110 +void enable_x2apic(void)
111 +{
112 + int msr, msr2;
113 +
114 + rdmsr(MSR_IA32_APICBASE, msr, msr2);
115 + if (!(msr & X2APIC_ENABLE)) {
116 + printk("Enabling x2apic\n");
117 + wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0);
118 + }
119 +}
120 +
121 +void enable_IR_x2apic(void)
122 +{
123 +#ifdef CONFIG_INTR_REMAP
124 + int ret;
125 + unsigned long flags;
126 +
127 + if (!cpu_has_x2apic)
128 + return;
129 +
130 + if (!x2apic_preenabled && disable_x2apic) {
131 + printk(KERN_INFO
132 + "Skipped enabling x2apic and Interrupt-remapping "
133 + "because of nox2apic\n");
134 + return;
135 + }
136 +
137 + if (x2apic_preenabled && disable_x2apic)
138 + panic("Bios already enabled x2apic, can't enforce nox2apic");
139 +
140 + if (!x2apic_preenabled && skip_ioapic_setup) {
141 + printk(KERN_INFO
142 + "Skipped enabling x2apic and Interrupt-remapping "
143 + "because of skipping io-apic setup\n");
144 + return;
145 + }
146 +
147 + ret = dmar_table_init();
148 + if (ret) {
149 + printk(KERN_INFO
150 + "dmar_table_init() failed with %d:\n", ret);
151 +
152 + if (x2apic_preenabled)
153 + panic("x2apic enabled by bios. But IR enabling failed");
154 + else
155 + printk(KERN_INFO
156 + "Not enabling x2apic,Intr-remapping\n");
157 + return;
158 + }
159 +
160 + local_irq_save(flags);
161 + mask_8259A();
162 + save_mask_IO_APIC_setup();
163 +
164 + ret = enable_intr_remapping(1);
165 +
166 + if (ret && x2apic_preenabled) {
167 + local_irq_restore(flags);
168 + panic("x2apic enabled by bios. But IR enabling failed");
169 + }
170 +
171 + if (ret)
172 + goto end;
173 +
174 + if (!x2apic) {
175 + x2apic = 1;
176 + apic_ops = &x2apic_ops;
177 + enable_x2apic();
178 + }
179 +end:
180 + if (ret)
181 + /*
182 + * IR enabling failed
183 + */
184 + restore_IO_APIC_setup();
185 + else
186 + reinit_intr_remapped_IO_APIC(x2apic_preenabled);
187 +
188 + unmask_8259A();
189 + local_irq_restore(flags);
190 +
191 + if (!ret) {
192 + if (!x2apic_preenabled)
193 + printk(KERN_INFO
194 + "Enabled x2apic and interrupt-remapping\n");
195 + else
196 + printk(KERN_INFO
197 + "Enabled Interrupt-remapping\n");
198 + } else
199 + printk(KERN_ERR
200 + "Failed to enable Interrupt-remapping and x2apic\n");
201 +#else
202 + if (!cpu_has_x2apic)
203 + return;
204 +
205 + if (x2apic_preenabled)
206 + panic("x2apic enabled prior OS handover,"
207 + " enable CONFIG_INTR_REMAP");
208 +
209 + printk(KERN_INFO "Enable CONFIG_INTR_REMAP for enabling intr-remapping "
210 + " and x2apic\n");
211 +#endif
212 +
213 + return;
214 +}
215 +
216 /*
217 * Detect and enable local APICs on non-SMP boards.
218 * Original code written by Keir Fraser.
219 @@ -945,6 +1070,11 @@ void __init early_init_lapic_mapping(voi
220 */
221 void __init init_apic_mappings(void)
222 {
223 + if (x2apic) {
224 + boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
225 + return;
226 + }
227 +
228 /*
229 * If no local APIC can be found then set up a fake all
230 * zeroes page to simulate the local APIC and another
231 @@ -983,6 +1113,9 @@ int __init APIC_init_uniprocessor(void)
232 return -1;
233 }
234
235 + enable_IR_x2apic();
236 + setup_apic_routing();
237 +
238 verify_local_APIC();
239
240 connect_bsp_APIC();
241 @@ -1236,10 +1369,14 @@ static int lapic_resume(struct sys_devic
242 maxlvt = lapic_get_maxlvt();
243
244 local_irq_save(flags);
245 - rdmsr(MSR_IA32_APICBASE, l, h);
246 - l &= ~MSR_IA32_APICBASE_BASE;
247 - l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
248 - wrmsr(MSR_IA32_APICBASE, l, h);
249 + if (!x2apic) {
250 + rdmsr(MSR_IA32_APICBASE, l, h);
251 + l &= ~MSR_IA32_APICBASE_BASE;
252 + l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
253 + wrmsr(MSR_IA32_APICBASE, l, h);
254 + } else
255 + enable_x2apic();
256 +
257 apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
258 apic_write(APIC_ID, apic_pm_state.apic_id);
259 apic_write(APIC_DFR, apic_pm_state.apic_dfr);
260 @@ -1379,6 +1516,15 @@ __cpuinit int apic_is_clustered_box(void
261 return (clusters > 2);
262 }
263
264 +static __init int setup_nox2apic(char *str)
265 +{
266 + disable_x2apic = 1;
267 + clear_cpu_cap(&boot_cpu_data, X86_FEATURE_X2APIC);
268 + return 0;
269 +}
270 +early_param("nox2apic", setup_nox2apic);
271 +
272 +
273 /*
274 * APIC command line parameters
275 */
276 --- a/arch/x86/kernel/cpu/common_64.c
277 +++ b/arch/x86/kernel/cpu/common_64.c
278 @@ -636,6 +636,8 @@ void __cpuinit cpu_init(void)
279 barrier();
280
281 check_efer();
282 + if (cpu != 0 && x2apic)
283 + enable_x2apic();
284
285 /*
286 * set up and load the per-CPU TSS
287 --- a/arch/x86/kernel/mpparse.c
288 +++ b/arch/x86/kernel/mpparse.c
289 @@ -397,7 +397,9 @@ static int __init smp_read_mpc(struct mp
290 generic_bigsmp_probe();
291 #endif
292
293 +#ifdef CONFIG_X86_32
294 setup_apic_routing();
295 +#endif
296 if (!num_processors)
297 printk(KERN_ERR "MPTABLE: no processors registered!\n");
298 return num_processors;
299 --- a/arch/x86/kernel/setup.c
300 +++ b/arch/x86/kernel/setup.c
301 @@ -778,6 +778,8 @@ void __init setup_arch(char **cmdline_p)
302 #else
303 num_physpages = max_pfn;
304
305 + if (cpu_has_x2apic)
306 + check_x2apic();
307
308 /* How many end-of-memory variables you have, grandma! */
309 /* need this before calling reserve_initrd */
310 --- a/arch/x86/kernel/smpboot.c
311 +++ b/arch/x86/kernel/smpboot.c
312 @@ -1169,6 +1169,11 @@ void __init native_smp_prepare_cpus(unsi
313 current_thread_info()->cpu = 0; /* needed? */
314 set_cpu_sibling_map(0);
315
316 +#ifdef CONFIG_X86_64
317 + enable_IR_x2apic();
318 + setup_apic_routing();
319 +#endif
320 +
321 if (smp_sanity_check(max_cpus) < 0) {
322 printk(KERN_INFO "SMP disabled\n");
323 disable_smp();
324 --- a/include/asm-x86/apic.h
325 +++ b/include/asm-x86/apic.h
326 @@ -93,12 +93,13 @@ static inline u32 native_apic_msr_read(u
327 return low;
328 }
329
330 -#ifdef CONFIG_X86_32
331 -extern void apic_wait_icr_idle(void);
332 -extern u32 safe_apic_wait_icr_idle(void);
333 -extern void apic_icr_write(u32 low, u32 id);
334 -#else
335 -extern void x2apic_icr_write(u32 low, u32 id);
336 +#ifndef CONFIG_X86_32
337 + extern int x2apic, x2apic_preenabled;
338 + extern void check_x2apic(void);
339 + extern void enable_x2apic(void);
340 + extern void enable_IR_x2apic(void);
341 + extern void x2apic_icr_write(u32 low, u32 id);
342 +#endif
343
344 struct apic_ops {
345 u32 (*read)(u32 reg);
346 @@ -119,7 +120,6 @@ extern struct apic_ops *apic_ops;
347 #define apic_icr_write (apic_ops->icr_write)
348 #define apic_wait_icr_idle (apic_ops->wait_icr_idle)
349 #define safe_apic_wait_icr_idle (apic_ops->safe_wait_icr_idle)
350 -#endif
351
352 extern int get_physical_broadcast(void);
353