blob: a8d38c0bb4490262d951c621e3c338f5cddaebfa [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Intel Multiprocessor Specification 1.1 and 1.4
3 * compliant MP-table parsing routines.
4 *
5 * (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
6 * (c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
7 *
8 * Fixes
9 * Erich Boleyn : MP v1.4 and additional changes.
10 * Alan Cox : Added EBDA scanning
11 * Ingo Molnar : various cleanups and rewrites
12 * Maciej W. Rozycki: Bits for default MP configurations
13 * Paul Diefenbaugh: Added full ACPI support
14 */
15
16#include <linux/mm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include <linux/init.h>
18#include <linux/delay.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <linux/bootmem.h>
20#include <linux/smp_lock.h>
21#include <linux/kernel_stat.h>
22#include <linux/mc146818rtc.h>
23#include <linux/acpi.h>
Christoph Lameter8c5a0902005-06-23 00:08:18 -070024#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025
26#include <asm/smp.h>
27#include <asm/mtrr.h>
28#include <asm/mpspec.h>
29#include <asm/pgalloc.h>
30#include <asm/io_apic.h>
31#include <asm/proto.h>
Andi Kleen8d916402005-05-31 14:39:26 -070032#include <asm/acpi.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
34/* Have we found an MP table */
35int smp_found_config;
36unsigned int __initdata maxcpus = NR_CPUS;
37
38int acpi_found_madt;
39
40/*
41 * Various Linux-internal data structures created from the
42 * MP-table.
43 */
Andi Kleen88931662005-11-05 17:25:54 +010044unsigned char apic_version [MAX_APICS];
Andi Kleen55f05ff2006-09-26 10:52:30 +020045DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
Linus Torvalds1da177e2005-04-16 15:20:36 -070046int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
Linus Torvalds1da177e2005-04-16 15:20:36 -070047
48static int mp_current_pci_id = 0;
49/* I/O APIC entries */
50struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
51
52/* # of MP IRQ source entries */
53struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
54
55/* MP IRQ source entries */
56int mp_irq_entries;
57
58int nr_ioapics;
Linus Torvalds1da177e2005-04-16 15:20:36 -070059unsigned long mp_lapic_addr = 0;
60
61
62
63/* Processor that is doing the boot up */
64unsigned int boot_cpu_id = -1U;
65/* Internal processor count */
Andi Kleen420f8f62005-11-05 17:25:54 +010066unsigned int num_processors __initdata = 0;
67
68unsigned disabled_cpus __initdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -070069
70/* Bitmask of physically existing CPUs */
71physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE;
72
73/* ACPI MADT entry parsing functions */
Len Brown888ba6c2005-08-24 12:07:20 -040074#ifdef CONFIG_ACPI
Linus Torvalds1da177e2005-04-16 15:20:36 -070075extern struct acpi_boot_flags acpi_boot;
Linus Torvalds1da177e2005-04-16 15:20:36 -070076extern int acpi_parse_lapic (acpi_table_entry_header *header);
77extern int acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header);
78extern int acpi_parse_lapic_nmi (acpi_table_entry_header *header);
Linus Torvalds1da177e2005-04-16 15:20:36 -070079extern int acpi_parse_ioapic (acpi_table_entry_header *header);
Len Brown888ba6c2005-08-24 12:07:20 -040080#endif /*CONFIG_ACPI*/
Linus Torvalds1da177e2005-04-16 15:20:36 -070081
82u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
83
84
85/*
86 * Intel MP BIOS table parsing routines:
87 */
88
89/*
90 * Checksum an MP configuration block.
91 */
92
93static int __init mpf_checksum(unsigned char *mp, int len)
94{
95 int sum = 0;
96
97 while (len--)
98 sum += *mp++;
99
100 return sum & 0xFF;
101}
102
Ashok Raj51f62e12006-03-25 16:29:28 +0100103static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104{
Andi Kleen88931662005-11-05 17:25:54 +0100105 int cpu;
106 unsigned char ver;
Ashok Raj51f62e12006-03-25 16:29:28 +0100107 cpumask_t tmp_map;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
Andi Kleen420f8f62005-11-05 17:25:54 +0100109 if (!(m->mpc_cpuflag & CPU_ENABLED)) {
110 disabled_cpus++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 return;
Andi Kleen420f8f62005-11-05 17:25:54 +0100112 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113
114 printk(KERN_INFO "Processor #%d %d:%d APIC version %d\n",
115 m->mpc_apicid,
116 (m->mpc_cpufeature & CPU_FAMILY_MASK)>>8,
117 (m->mpc_cpufeature & CPU_MODEL_MASK)>>4,
118 m->mpc_apicver);
119
120 if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
121 Dprintk(" Bootup CPU\n");
122 boot_cpu_id = m->mpc_apicid;
123 }
124 if (num_processors >= NR_CPUS) {
125 printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
126 " Processor ignored.\n", NR_CPUS);
127 return;
128 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129
Ashok Raj51f62e12006-03-25 16:29:28 +0100130 num_processors++;
131 cpus_complement(tmp_map, cpu_present_map);
132 cpu = first_cpu(tmp_map);
133
Andi Kleen88931662005-11-05 17:25:54 +0100134#if MAX_APICS < 255
135 if ((int)m->mpc_apicid > MAX_APICS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n",
137 m->mpc_apicid, MAX_APICS);
138 return;
139 }
Andi Kleen88931662005-11-05 17:25:54 +0100140#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 ver = m->mpc_apicver;
142
143 physid_set(m->mpc_apicid, phys_cpu_present_map);
144 /*
145 * Validate version
146 */
147 if (ver == 0x0) {
148 printk(KERN_ERR "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
149 ver = 0x10;
150 }
151 apic_version[m->mpc_apicid] = ver;
Andi Kleen18a2b642005-05-16 21:53:35 -0700152 if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
153 /*
154 * bios_cpu_apicid is required to have processors listed
155 * in same order as logical cpu numbers. Hence the first
156 * entry is BSP, and so on.
157 */
Andi Kleen61b1b2d2005-07-28 21:15:27 -0700158 cpu = 0;
Ashok Raj51f62e12006-03-25 16:29:28 +0100159 }
Andi Kleen61b1b2d2005-07-28 21:15:27 -0700160 bios_cpu_apicid[cpu] = m->mpc_apicid;
161 x86_cpu_to_apicid[cpu] = m->mpc_apicid;
162
163 cpu_set(cpu, cpu_possible_map);
164 cpu_set(cpu, cpu_present_map);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165}
166
167static void __init MP_bus_info (struct mpc_config_bus *m)
168{
169 char str[7];
170
171 memcpy(str, m->mpc_bustype, 6);
172 str[6] = 0;
173 Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
174
175 if (strncmp(str, "ISA", 3) == 0) {
Andi Kleen55f05ff2006-09-26 10:52:30 +0200176 set_bit(m->mpc_busid, mp_bus_not_pci);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 } else if (strncmp(str, "PCI", 3) == 0) {
Andi Kleen55f05ff2006-09-26 10:52:30 +0200178 clear_bit(m->mpc_busid, mp_bus_not_pci);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
180 mp_current_pci_id++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 } else {
182 printk(KERN_ERR "Unknown bustype %s\n", str);
183 }
184}
185
186static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
187{
188 if (!(m->mpc_flags & MPC_APIC_USABLE))
189 return;
190
191 printk("I/O APIC #%d Version %d at 0x%X.\n",
192 m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
193 if (nr_ioapics >= MAX_IO_APICS) {
194 printk(KERN_ERR "Max # of I/O APICs (%d) exceeded (found %d).\n",
195 MAX_IO_APICS, nr_ioapics);
196 panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
197 }
198 if (!m->mpc_apicaddr) {
199 printk(KERN_ERR "WARNING: bogus zero I/O APIC address"
200 " found in MP table, skipping!\n");
201 return;
202 }
203 mp_ioapics[nr_ioapics] = *m;
204 nr_ioapics++;
205}
206
207static void __init MP_intsrc_info (struct mpc_config_intsrc *m)
208{
209 mp_irqs [mp_irq_entries] = *m;
210 Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
211 " IRQ %02x, APIC ID %x, APIC INT %02x\n",
212 m->mpc_irqtype, m->mpc_irqflag & 3,
213 (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
214 m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
James Cleverdon6004e1b2005-11-05 17:25:53 +0100215 if (++mp_irq_entries >= MAX_IRQ_SOURCES)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 panic("Max # of irq sources exceeded!!\n");
217}
218
219static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
220{
221 Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
222 " IRQ %02x, APIC ID %x, APIC LINT %02x\n",
223 m->mpc_irqtype, m->mpc_irqflag & 3,
224 (m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
225 m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226}
227
228/*
229 * Read/parse the MPC
230 */
231
232static int __init smp_read_mpc(struct mp_config_table *mpc)
233{
234 char str[16];
235 int count=sizeof(*mpc);
236 unsigned char *mpt=((unsigned char *)mpc)+count;
237
238 if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
239 printk("SMP mptable: bad signature [%c%c%c%c]!\n",
240 mpc->mpc_signature[0],
241 mpc->mpc_signature[1],
242 mpc->mpc_signature[2],
243 mpc->mpc_signature[3]);
244 return 0;
245 }
246 if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
247 printk("SMP mptable: checksum error!\n");
248 return 0;
249 }
250 if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
251 printk(KERN_ERR "SMP mptable: bad table version (%d)!!\n",
252 mpc->mpc_spec);
253 return 0;
254 }
255 if (!mpc->mpc_lapic) {
256 printk(KERN_ERR "SMP mptable: null local APIC address!\n");
257 return 0;
258 }
259 memcpy(str,mpc->mpc_oem,8);
260 str[8]=0;
261 printk(KERN_INFO "OEM ID: %s ",str);
262
263 memcpy(str,mpc->mpc_productid,12);
264 str[12]=0;
Tim Hockin9ff4ced2006-02-17 13:52:54 -0800265 printk("Product ID: %s ",str);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
Tim Hockin9ff4ced2006-02-17 13:52:54 -0800267 printk("APIC at: 0x%X\n",mpc->mpc_lapic);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
269 /* save the local APIC address, it might be non-default */
270 if (!acpi_lapic)
271 mp_lapic_addr = mpc->mpc_lapic;
272
273 /*
274 * Now process the configuration blocks.
275 */
276 while (count < mpc->mpc_length) {
277 switch(*mpt) {
278 case MP_PROCESSOR:
279 {
280 struct mpc_config_processor *m=
281 (struct mpc_config_processor *)mpt;
282 if (!acpi_lapic)
283 MP_processor_info(m);
284 mpt += sizeof(*m);
285 count += sizeof(*m);
286 break;
287 }
288 case MP_BUS:
289 {
290 struct mpc_config_bus *m=
291 (struct mpc_config_bus *)mpt;
292 MP_bus_info(m);
293 mpt += sizeof(*m);
294 count += sizeof(*m);
295 break;
296 }
297 case MP_IOAPIC:
298 {
299 struct mpc_config_ioapic *m=
300 (struct mpc_config_ioapic *)mpt;
301 MP_ioapic_info(m);
302 mpt+=sizeof(*m);
303 count+=sizeof(*m);
304 break;
305 }
306 case MP_INTSRC:
307 {
308 struct mpc_config_intsrc *m=
309 (struct mpc_config_intsrc *)mpt;
310
311 MP_intsrc_info(m);
312 mpt+=sizeof(*m);
313 count+=sizeof(*m);
314 break;
315 }
316 case MP_LINTSRC:
317 {
318 struct mpc_config_lintsrc *m=
319 (struct mpc_config_lintsrc *)mpt;
320 MP_lintsrc_info(m);
321 mpt+=sizeof(*m);
322 count+=sizeof(*m);
323 break;
324 }
325 }
326 }
327 clustered_apic_check();
328 if (!num_processors)
329 printk(KERN_ERR "SMP mptable: no processors registered!\n");
330 return num_processors;
331}
332
333static int __init ELCR_trigger(unsigned int irq)
334{
335 unsigned int port;
336
337 port = 0x4d0 + (irq >> 3);
338 return (inb(port) >> (irq & 7)) & 1;
339}
340
341static void __init construct_default_ioirq_mptable(int mpc_default_type)
342{
343 struct mpc_config_intsrc intsrc;
344 int i;
345 int ELCR_fallback = 0;
346
347 intsrc.mpc_type = MP_INTSRC;
348 intsrc.mpc_irqflag = 0; /* conforming */
349 intsrc.mpc_srcbus = 0;
350 intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
351
352 intsrc.mpc_irqtype = mp_INT;
353
354 /*
355 * If true, we have an ISA/PCI system with no IRQ entries
356 * in the MP table. To prevent the PCI interrupts from being set up
357 * incorrectly, we try to use the ELCR. The sanity check to see if
358 * there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
359 * never be level sensitive, so we simply see if the ELCR agrees.
360 * If it does, we assume it's valid.
361 */
362 if (mpc_default_type == 5) {
363 printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
364
365 if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))
366 printk(KERN_ERR "ELCR contains invalid data... not using ELCR\n");
367 else {
368 printk(KERN_INFO "Using ELCR to identify PCI interrupts\n");
369 ELCR_fallback = 1;
370 }
371 }
372
373 for (i = 0; i < 16; i++) {
374 switch (mpc_default_type) {
375 case 2:
376 if (i == 0 || i == 13)
377 continue; /* IRQ0 & IRQ13 not connected */
378 /* fall through */
379 default:
380 if (i == 2)
381 continue; /* IRQ2 is never connected */
382 }
383
384 if (ELCR_fallback) {
385 /*
386 * If the ELCR indicates a level-sensitive interrupt, we
387 * copy that information over to the MP table in the
388 * irqflag field (level sensitive, active high polarity).
389 */
390 if (ELCR_trigger(i))
391 intsrc.mpc_irqflag = 13;
392 else
393 intsrc.mpc_irqflag = 0;
394 }
395
396 intsrc.mpc_srcbusirq = i;
397 intsrc.mpc_dstirq = i ? i : 2; /* IRQ0 to INTIN2 */
398 MP_intsrc_info(&intsrc);
399 }
400
401 intsrc.mpc_irqtype = mp_ExtINT;
402 intsrc.mpc_srcbusirq = 0;
403 intsrc.mpc_dstirq = 0; /* 8259A to INTIN0 */
404 MP_intsrc_info(&intsrc);
405}
406
407static inline void __init construct_default_ISA_mptable(int mpc_default_type)
408{
409 struct mpc_config_processor processor;
410 struct mpc_config_bus bus;
411 struct mpc_config_ioapic ioapic;
412 struct mpc_config_lintsrc lintsrc;
413 int linttypes[2] = { mp_ExtINT, mp_NMI };
414 int i;
415
416 /*
417 * local APIC has default address
418 */
419 mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
420
421 /*
422 * 2 CPUs, numbered 0 & 1.
423 */
424 processor.mpc_type = MP_PROCESSOR;
425 /* Either an integrated APIC or a discrete 82489DX. */
426 processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
427 processor.mpc_cpuflag = CPU_ENABLED;
428 processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
429 (boot_cpu_data.x86_model << 4) |
430 boot_cpu_data.x86_mask;
431 processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
432 processor.mpc_reserved[0] = 0;
433 processor.mpc_reserved[1] = 0;
434 for (i = 0; i < 2; i++) {
435 processor.mpc_apicid = i;
436 MP_processor_info(&processor);
437 }
438
439 bus.mpc_type = MP_BUS;
440 bus.mpc_busid = 0;
441 switch (mpc_default_type) {
442 default:
443 printk(KERN_ERR "???\nUnknown standard configuration %d\n",
444 mpc_default_type);
445 /* fall through */
446 case 1:
447 case 5:
448 memcpy(bus.mpc_bustype, "ISA ", 6);
449 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 }
451 MP_bus_info(&bus);
452 if (mpc_default_type > 4) {
453 bus.mpc_busid = 1;
454 memcpy(bus.mpc_bustype, "PCI ", 6);
455 MP_bus_info(&bus);
456 }
457
458 ioapic.mpc_type = MP_IOAPIC;
459 ioapic.mpc_apicid = 2;
460 ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
461 ioapic.mpc_flags = MPC_APIC_USABLE;
462 ioapic.mpc_apicaddr = 0xFEC00000;
463 MP_ioapic_info(&ioapic);
464
465 /*
466 * We set up most of the low 16 IO-APIC pins according to MPS rules.
467 */
468 construct_default_ioirq_mptable(mpc_default_type);
469
470 lintsrc.mpc_type = MP_LINTSRC;
471 lintsrc.mpc_irqflag = 0; /* conforming */
472 lintsrc.mpc_srcbusid = 0;
473 lintsrc.mpc_srcbusirq = 0;
474 lintsrc.mpc_destapic = MP_APIC_ALL;
475 for (i = 0; i < 2; i++) {
476 lintsrc.mpc_irqtype = linttypes[i];
477 lintsrc.mpc_destapiclint = i;
478 MP_lintsrc_info(&lintsrc);
479 }
480}
481
482static struct intel_mp_floating *mpf_found;
483
484/*
485 * Scan the memory blocks for an SMP configuration block.
486 */
487void __init get_smp_config (void)
488{
489 struct intel_mp_floating *mpf = mpf_found;
490
491 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 * ACPI supports both logical (e.g. Hyper-Threading) and physical
493 * processors, where MPS only supports physical.
494 */
495 if (acpi_lapic && acpi_ioapic) {
496 printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n");
497 return;
498 }
499 else if (acpi_lapic)
500 printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");
501
502 printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503
504 /*
505 * Now see if we need to read further.
506 */
507 if (mpf->mpf_feature1 != 0) {
508
509 printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1);
510 construct_default_ISA_mptable(mpf->mpf_feature1);
511
512 } else if (mpf->mpf_physptr) {
513
514 /*
515 * Read the physical hardware table. Anything here will
516 * override the defaults.
517 */
Siddha, Suresh Bf6c2e332005-11-05 17:25:53 +0100518 if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 smp_found_config = 0;
520 printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
521 printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
522 return;
523 }
524 /*
525 * If there are no explicit MP IRQ entries, then we are
526 * broken. We set up most of the low 16 IO-APIC pins to
527 * ISA defaults and hope it will work.
528 */
529 if (!mp_irq_entries) {
530 struct mpc_config_bus bus;
531
532 printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
533
534 bus.mpc_type = MP_BUS;
535 bus.mpc_busid = 0;
536 memcpy(bus.mpc_bustype, "ISA ", 6);
537 MP_bus_info(&bus);
538
539 construct_default_ioirq_mptable(0);
540 }
541
542 } else
543 BUG();
544
545 printk(KERN_INFO "Processors: %d\n", num_processors);
546 /*
547 * Only use the first configuration found.
548 */
549}
550
551static int __init smp_scan_config (unsigned long base, unsigned long length)
552{
553 extern void __bad_mpf_size(void);
554 unsigned int *bp = phys_to_virt(base);
555 struct intel_mp_floating *mpf;
556
557 Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);
558 if (sizeof(*mpf) != 16)
559 __bad_mpf_size();
560
561 while (length > 0) {
562 mpf = (struct intel_mp_floating *)bp;
563 if ((*bp == SMP_MAGIC_IDENT) &&
564 (mpf->mpf_length == 1) &&
565 !mpf_checksum((unsigned char *)bp, 16) &&
566 ((mpf->mpf_specification == 1)
567 || (mpf->mpf_specification == 4)) ) {
568
569 smp_found_config = 1;
570 reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE);
571 if (mpf->mpf_physptr)
572 reserve_bootmem_generic(mpf->mpf_physptr, PAGE_SIZE);
573 mpf_found = mpf;
574 return 1;
575 }
576 bp += 4;
577 length -= 16;
578 }
579 return 0;
580}
581
582void __init find_intel_smp (void)
583{
584 unsigned int address;
585
586 /*
587 * FIXME: Linux assumes you have 640K of base ram..
588 * this continues the error...
589 *
590 * 1) Scan the bottom 1K for a signature
591 * 2) Scan the top 1K of base RAM
592 * 3) Scan the 64K of bios
593 */
594 if (smp_scan_config(0x0,0x400) ||
595 smp_scan_config(639*0x400,0x400) ||
596 smp_scan_config(0xF0000,0x10000))
597 return;
598 /*
Andi Kleene5099132006-09-26 10:52:29 +0200599 * If it is an SMP machine we should know now.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 *
601 * there is a real-mode segmented pointer pointing to the
602 * 4K EBDA area at 0x40E, calculate and scan it here.
603 *
604 * NOTE! There are Linux loaders that will corrupt the EBDA
605 * area, and as such this kind of SMP config may be less
606 * trustworthy, simply because the SMP table may have been
607 * stomped on during early boot. These loaders are buggy and
608 * should be fixed.
609 */
610
611 address = *(unsigned short *)phys_to_virt(0x40E);
612 address <<= 4;
613 if (smp_scan_config(address, 0x1000))
614 return;
615
616 /* If we have come this far, we did not find an MP table */
617 printk(KERN_INFO "No mptable found.\n");
618}
619
620/*
621 * - Intel MP Configuration Table
622 */
623void __init find_smp_config (void)
624{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 find_intel_smp();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626}
627
628
629/* --------------------------------------------------------------------------
630 ACPI-based MP Configuration
631 -------------------------------------------------------------------------- */
632
Len Brown888ba6c2005-08-24 12:07:20 -0400633#ifdef CONFIG_ACPI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634
635void __init mp_register_lapic_address (
636 u64 address)
637{
638 mp_lapic_addr = (unsigned long) address;
639
640 set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
641
642 if (boot_cpu_id == -1U)
643 boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
644
645 Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid);
646}
647
648
Ashok Raj51f62e12006-03-25 16:29:28 +0100649void __cpuinit mp_register_lapic (
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 u8 id,
651 u8 enabled)
652{
653 struct mpc_config_processor processor;
654 int boot_cpu = 0;
655
656 if (id >= MAX_APICS) {
657 printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
658 id, MAX_APICS);
659 return;
660 }
661
662 if (id == boot_cpu_physical_apicid)
663 boot_cpu = 1;
664
665 processor.mpc_type = MP_PROCESSOR;
666 processor.mpc_apicid = id;
Andi Kleen8675b1a2005-09-12 18:49:24 +0200667 processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
669 processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
670 processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
671 (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
672 processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
673 processor.mpc_reserved[0] = 0;
674 processor.mpc_reserved[1] = 0;
675
676 MP_processor_info(&processor);
677}
678
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679#define MP_ISA_BUS 0
680#define MP_MAX_IOAPIC_PIN 127
681
682static struct mp_ioapic_routing {
683 int apic_id;
684 int gsi_start;
685 int gsi_end;
686 u32 pin_programmed[4];
687} mp_ioapic_routing[MAX_IO_APICS];
688
689
690static int mp_find_ioapic (
691 int gsi)
692{
693 int i = 0;
694
695 /* Find the IOAPIC that manages this GSI. */
696 for (i = 0; i < nr_ioapics; i++) {
697 if ((gsi >= mp_ioapic_routing[i].gsi_start)
698 && (gsi <= mp_ioapic_routing[i].gsi_end))
699 return i;
700 }
701
702 printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
703
704 return -1;
705}
706
707
708void __init mp_register_ioapic (
709 u8 id,
710 u32 address,
711 u32 gsi_base)
712{
713 int idx = 0;
714
715 if (nr_ioapics >= MAX_IO_APICS) {
716 printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
717 "(found %d)\n", MAX_IO_APICS, nr_ioapics);
718 panic("Recompile kernel with bigger MAX_IO_APICS!\n");
719 }
720 if (!address) {
721 printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
722 " found in MADT table, skipping!\n");
723 return;
724 }
725
726 idx = nr_ioapics++;
727
728 mp_ioapics[idx].mpc_type = MP_IOAPIC;
729 mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
730 mp_ioapics[idx].mpc_apicaddr = address;
731
732 set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
Andi Kleen0af2be02005-05-16 21:53:27 -0700733 mp_ioapics[idx].mpc_apicid = id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
735
736 /*
737 * Build basic IRQ lookup table to facilitate gsi->io_apic lookups
738 * and to prevent reprogramming of IOAPIC pins (PCI IRQs).
739 */
740 mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
741 mp_ioapic_routing[idx].gsi_start = gsi_base;
742 mp_ioapic_routing[idx].gsi_end = gsi_base +
743 io_apic_get_redir_entries(idx);
744
745 printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
746 "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid,
747 mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
748 mp_ioapic_routing[idx].gsi_start,
749 mp_ioapic_routing[idx].gsi_end);
750
751 return;
752}
753
754
755void __init mp_override_legacy_irq (
756 u8 bus_irq,
757 u8 polarity,
758 u8 trigger,
759 u32 gsi)
760{
761 struct mpc_config_intsrc intsrc;
762 int ioapic = -1;
763 int pin = -1;
764
765 /*
766 * Convert 'gsi' to 'ioapic.pin'.
767 */
768 ioapic = mp_find_ioapic(gsi);
769 if (ioapic < 0)
770 return;
771 pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
772
773 /*
774 * TBD: This check is for faulty timer entries, where the override
775 * erroneously sets the trigger to level, resulting in a HUGE
776 * increase of timer interrupts!
777 */
778 if ((bus_irq == 0) && (trigger == 3))
779 trigger = 1;
780
781 intsrc.mpc_type = MP_INTSRC;
782 intsrc.mpc_irqtype = mp_INT;
783 intsrc.mpc_irqflag = (trigger << 2) | polarity;
784 intsrc.mpc_srcbus = MP_ISA_BUS;
785 intsrc.mpc_srcbusirq = bus_irq; /* IRQ */
786 intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; /* APIC ID */
787 intsrc.mpc_dstirq = pin; /* INTIN# */
788
789 Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n",
790 intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3,
791 (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus,
792 intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq);
793
794 mp_irqs[mp_irq_entries] = intsrc;
795 if (++mp_irq_entries == MAX_IRQ_SOURCES)
796 panic("Max # of irq sources exceeded!\n");
797
798 return;
799}
800
801
802void __init mp_config_acpi_legacy_irqs (void)
803{
804 struct mpc_config_intsrc intsrc;
805 int i = 0;
806 int ioapic = -1;
807
808 /*
809 * Fabricate the legacy ISA bus (bus #31).
810 */
Andi Kleen55f05ff2006-09-26 10:52:30 +0200811 set_bit(MP_ISA_BUS, mp_bus_not_pci);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812
813 /*
814 * Locate the IOAPIC that manages the ISA IRQs (0-15).
815 */
816 ioapic = mp_find_ioapic(0);
817 if (ioapic < 0)
818 return;
819
820 intsrc.mpc_type = MP_INTSRC;
821 intsrc.mpc_irqflag = 0; /* Conforming */
822 intsrc.mpc_srcbus = MP_ISA_BUS;
823 intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
824
825 /*
826 * Use the default configuration for the IRQs 0-15. Unless
827 * overridden by (MADT) interrupt source override entries.
828 */
829 for (i = 0; i < 16; i++) {
830 int idx;
831
832 for (idx = 0; idx < mp_irq_entries; idx++) {
833 struct mpc_config_intsrc *irq = mp_irqs + idx;
834
835 /* Do we already have a mapping for this ISA IRQ? */
836 if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i)
837 break;
838
839 /* Do we already have a mapping for this IOAPIC pin */
840 if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
841 (irq->mpc_dstirq == i))
842 break;
843 }
844
845 if (idx != mp_irq_entries) {
846 printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
847 continue; /* IRQ already used */
848 }
849
850 intsrc.mpc_irqtype = mp_INT;
851 intsrc.mpc_srcbusirq = i; /* Identity mapped */
852 intsrc.mpc_dstirq = i;
853
854 Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, "
855 "%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3,
856 (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus,
857 intsrc.mpc_srcbusirq, intsrc.mpc_dstapic,
858 intsrc.mpc_dstirq);
859
860 mp_irqs[mp_irq_entries] = intsrc;
861 if (++mp_irq_entries == MAX_IRQ_SOURCES)
862 panic("Max # of irq sources exceeded!\n");
863 }
864
865 return;
866}
867
Natalie Protasevich701067c2005-06-23 00:08:41 -0700868#define MAX_GSI_NUM 4096
869
Bob Moore50eca3e2005-09-30 19:03:00 -0400870int mp_register_gsi(u32 gsi, int triggering, int polarity)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871{
872 int ioapic = -1;
873 int ioapic_pin = 0;
874 int idx, bit = 0;
Natalie Protasevich701067c2005-06-23 00:08:41 -0700875 static int pci_irq = 16;
876 /*
877 * Mapping between Global System Interrupts, which
878 * represent all possible interrupts, to the IRQs
879 * assigned to actual devices.
880 */
881 static int gsi_to_irq[MAX_GSI_NUM];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882
883 if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
884 return gsi;
885
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 /* Don't set up the ACPI SCI because it's already set up */
887 if (acpi_fadt.sci_int == gsi)
888 return gsi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889
890 ioapic = mp_find_ioapic(gsi);
891 if (ioapic < 0) {
892 printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
893 return gsi;
894 }
895
896 ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
897
898 /*
899 * Avoid pin reprogramming. PRTs typically include entries
900 * with redundant pin->gsi mappings (but unique PCI devices);
901 * we only program the IOAPIC on the first.
902 */
903 bit = ioapic_pin % 32;
904 idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
905 if (idx > 3) {
906 printk(KERN_ERR "Invalid reference to IOAPIC pin "
907 "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
908 ioapic_pin);
909 return gsi;
910 }
911 if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
912 Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
913 mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
Natalie Protasevich701067c2005-06-23 00:08:41 -0700914 return gsi_to_irq[gsi];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 }
916
917 mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
918
Len Browncb654692005-12-28 02:43:51 -0500919 if (triggering == ACPI_LEVEL_SENSITIVE) {
Natalie Protasevich701067c2005-06-23 00:08:41 -0700920 /*
921 * For PCI devices assign IRQs in order, avoiding gaps
922 * due to unused I/O APIC pins.
923 */
924 int irq = gsi;
Natalie.Protasevich@unisys.com6a1caa22005-07-30 11:25:32 -0700925 if (gsi < MAX_GSI_NUM) {
Kimball Murraye0c1e9b2006-05-08 15:17:16 +0200926 /*
927 * Retain the VIA chipset work-around (gsi > 15), but
928 * avoid a problem where the 8254 timer (IRQ0) is setup
929 * via an override (so it's not on pin 0 of the ioapic),
930 * and at the same time, the pin 0 interrupt is a PCI
931 * type. The gsi > 15 test could cause these two pins
932 * to be shared as IRQ0, and they are not shareable.
933 * So test for this condition, and if necessary, avoid
934 * the pin collision.
935 */
936 if (gsi > 15 || (gsi == 0 && !timer_uses_ioapic_pin_0))
Natalie.Protasevich@unisys.com6a1caa22005-07-30 11:25:32 -0700937 gsi = pci_irq++;
Natalie.Protasevich@unisys.com6a1caa22005-07-30 11:25:32 -0700938 /*
939 * Don't assign IRQ used by ACPI SCI
940 */
941 if (gsi == acpi_fadt.sci_int)
942 gsi = pci_irq++;
Natalie.Protasevich@unisys.com6a1caa22005-07-30 11:25:32 -0700943 gsi_to_irq[irq] = gsi;
944 } else {
945 printk(KERN_ERR "GSI %u is too high\n", gsi);
946 return gsi;
947 }
Natalie Protasevich701067c2005-06-23 00:08:41 -0700948 }
949
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
Bob Moore50eca3e2005-09-30 19:03:00 -0400951 triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
952 polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 return gsi;
954}
955
Len Brown888ba6c2005-08-24 12:07:20 -0400956#endif /*CONFIG_ACPI*/