mpparse.c 19.6 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2
 *	Intel Multiprocessor Specification 1.1 and 1.4
L
Linus Torvalds 已提交
3 4 5 6
 *	compliant MP-table parsing routines.
 *
 *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
 *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
7
 *      (c) 2008 Alexey Starikovskiy <astarikovskiy@suse.de>
L
Linus Torvalds 已提交
8 9 10 11 12 13 14 15 16
 */

#include <linux/mm.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/bootmem.h>
#include <linux/kernel_stat.h>
#include <linux/mc146818rtc.h>
#include <linux/bitops.h>
17 18
#include <linux/acpi.h>
#include <linux/module.h>
L
Linus Torvalds 已提交
19 20 21 22

#include <asm/smp.h>
#include <asm/mtrr.h>
#include <asm/mpspec.h>
23
#include <asm/pgalloc.h>
L
Linus Torvalds 已提交
24
#include <asm/io_apic.h>
25 26
#include <asm/proto.h>
#include <asm/acpi.h>
27
#include <asm/bios_ebda.h>
L
Linus Torvalds 已提交
28 29

#include <mach_apic.h>
30
#ifdef CONFIG_X86_32
31
#include <mach_apicdef.h>
L
Linus Torvalds 已提交
32
#include <mach_mpparse.h>
33
#endif
L
Linus Torvalds 已提交
34 35 36 37 38 39 40 41

/* Have we found an MP table */
int smp_found_config;

/*
 * Various Linux-internal data structures created from the
 * MP-table.
 */
42
#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
A
Alexey Starikovskiy 已提交
43
int mp_bus_id_to_type[MAX_MP_BUSSES];
44
#endif
45

46
DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
A
Alexey Starikovskiy 已提交
47
int mp_bus_id_to_pci_bus[MAX_MP_BUSSES] = {[0 ... MAX_MP_BUSSES - 1] = -1 };
48

L
Linus Torvalds 已提交
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
static int mp_current_pci_id;

int pic_mode;

/*
 * Intel MP BIOS table parsing routines:
 */

/*
 * Checksum an MP configuration block.
 */

static int __init mpf_checksum(unsigned char *mp, int len)
{
	int sum = 0;

	while (len--)
		sum += *mp++;

	return sum & 0xFF;
}

71
#ifdef CONFIG_X86_NUMAQ
L
Linus Torvalds 已提交
72 73 74 75 76 77
/*
 * Have to match translation table entries to main table entries by counter
 * hence the mpc_record variable .... can't see a less disgusting way of
 * doing this ....
 */

A
Alexey Starikovskiy 已提交
78 79 80
static int mpc_record;
static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY]
    __cpuinitdata;
81
#endif
L
Linus Torvalds 已提交
82

83 84 85
static void __cpuinit MP_processor_info(struct mpc_config_processor *m)
{
	int apicid;
86
	char *bootup_cpu = "";
87

G
Glauber Costa 已提交
88 89
	if (!(m->mpc_cpuflag & CPU_ENABLED)) {
		disabled_cpus++;
L
Linus Torvalds 已提交
90
		return;
G
Glauber Costa 已提交
91
	}
A
Alexey Starikovskiy 已提交
92
#ifdef CONFIG_X86_NUMAQ
L
Linus Torvalds 已提交
93
	apicid = mpc_apic_id(m, translation_table[mpc_record]);
A
Alexey Starikovskiy 已提交
94 95 96
#else
	apicid = m->mpc_apicid;
#endif
L
Linus Torvalds 已提交
97
	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
98
		bootup_cpu = " (Bootup-CPU)";
L
Linus Torvalds 已提交
99 100 101
		boot_cpu_physical_apicid = m->mpc_apicid;
	}

102
	printk(KERN_INFO "Processor #%d%s\n", m->mpc_apicid, bootup_cpu);
103
	generic_processor_info(apicid, m->mpc_apicver);
L
Linus Torvalds 已提交
104 105
}

A
Alexey Starikovskiy 已提交
106
static void __init MP_bus_info(struct mpc_config_bus *m)
L
Linus Torvalds 已提交
107 108 109 110 111 112
{
	char str[7];

	memcpy(str, m->mpc_bustype, 6);
	str[6] = 0;

113
#ifdef CONFIG_X86_NUMAQ
L
Linus Torvalds 已提交
114
	mpc_oem_bus_info(m, str, translation_table[mpc_record]);
115
#else
Y
Yinghai Lu 已提交
116
	printk(KERN_INFO "Bus #%d is %s\n", m->mpc_busid, str);
117
#endif
L
Linus Torvalds 已提交
118

119
#if MAX_MP_BUSSES < 256
120 121
	if (m->mpc_busid >= MAX_MP_BUSSES) {
		printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
A
Alexey Starikovskiy 已提交
122 123
		       " is too large, max. supported is %d\n",
		       m->mpc_busid, str, MAX_MP_BUSSES - 1);
124 125
		return;
	}
126
#endif
127

A
Alexey Starikovskiy 已提交
128 129 130 131 132 133
	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) {
		 set_bit(m->mpc_busid, mp_bus_not_pci);
#if defined(CONFIG_EISA) || defined (CONFIG_MCA)
		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
#endif
	} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) {
134
#ifdef CONFIG_X86_NUMAQ
L
Linus Torvalds 已提交
135
		mpc_oem_pci_bus(m, translation_table[mpc_record]);
136
#endif
137
		clear_bit(m->mpc_busid, mp_bus_not_pci);
L
Linus Torvalds 已提交
138 139
		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
		mp_current_pci_id++;
140 141
#if defined(CONFIG_EISA) || defined (CONFIG_MCA)
		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
A
Alexey Starikovskiy 已提交
142
	} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA) - 1) == 0) {
143
		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
A
Alexey Starikovskiy 已提交
144
	} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA) - 1) == 0) {
L
Linus Torvalds 已提交
145
		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
146
#endif
A
Alexey Starikovskiy 已提交
147 148
	} else
		printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
L
Linus Torvalds 已提交
149 150
}

151 152
#ifdef CONFIG_X86_IO_APIC

153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
static int bad_ioapic(unsigned long address)
{
	if (nr_ioapics >= MAX_IO_APICS) {
		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
		       "(found %d)\n", MAX_IO_APICS, nr_ioapics);
		panic("Recompile kernel with bigger MAX_IO_APICS!\n");
	}
	if (!address) {
		printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
		       " found in table, skipping!\n");
		return 1;
	}
	return 0;
}

A
Alexey Starikovskiy 已提交
168
static void __init MP_ioapic_info(struct mpc_config_ioapic *m)
L
Linus Torvalds 已提交
169 170 171 172
{
	if (!(m->mpc_flags & MPC_APIC_USABLE))
		return;

T
Thomas Gleixner 已提交
173
	printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
A
Alexey Starikovskiy 已提交
174
	       m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
175 176

	if (bad_ioapic(m->mpc_apicaddr))
L
Linus Torvalds 已提交
177
		return;
178

L
Linus Torvalds 已提交
179 180 181 182
	mp_ioapics[nr_ioapics] = *m;
	nr_ioapics++;
}

A
Alexey Starikovskiy 已提交
183
static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
L
Linus Torvalds 已提交
184
{
A
Alexey Starikovskiy 已提交
185
	mp_irqs[mp_irq_entries] = *m;
Y
Yinghai Lu 已提交
186
	printk(KERN_INFO "Int: type %d, pol %d, trig %d, bus %02x,"
L
Linus Torvalds 已提交
187
		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
A
Alexey Starikovskiy 已提交
188 189 190
		m->mpc_irqtype, m->mpc_irqflag & 3,
		(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
		m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
L
Linus Torvalds 已提交
191 192 193 194
	if (++mp_irq_entries == MAX_IRQ_SOURCES)
		panic("Max # of irq sources exceeded!!\n");
}

195 196
#endif

A
Alexey Starikovskiy 已提交
197
static void __init MP_lintsrc_info(struct mpc_config_lintsrc *m)
L
Linus Torvalds 已提交
198
{
Y
Yinghai Lu 已提交
199
	printk(KERN_INFO "Lint: type %d, pol %d, trig %d, bus %02x,"
L
Linus Torvalds 已提交
200
		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
A
Alexey Starikovskiy 已提交
201 202 203
		m->mpc_irqtype, m->mpc_irqflag & 3,
		(m->mpc_irqflag >> 2) & 3, m->mpc_srcbusid,
		m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
L
Linus Torvalds 已提交
204 205 206
}

#ifdef CONFIG_X86_NUMAQ
A
Alexey Starikovskiy 已提交
207
static void __init MP_translation_info(struct mpc_config_translation *m)
L
Linus Torvalds 已提交
208
{
A
Alexey Starikovskiy 已提交
209 210 211 212
	printk(KERN_INFO
	       "Translation: record %d, type %d, quad %d, global %d, local %d\n",
	       mpc_record, m->trans_type, m->trans_quad, m->trans_global,
	       m->trans_local);
L
Linus Torvalds 已提交
213

A
Alexey Starikovskiy 已提交
214
	if (mpc_record >= MAX_MPC_ENTRY)
L
Linus Torvalds 已提交
215 216
		printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
	else
A
Alexey Starikovskiy 已提交
217
		translation_table[mpc_record] = m;	/* stash this for later */
L
Linus Torvalds 已提交
218 219 220 221 222 223 224 225
	if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
		node_set_online(m->trans_quad);
}

/*
 * Read/parse the MPC oem tables
 */

A
Alexey Starikovskiy 已提交
226 227
static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable,
				    unsigned short oemsize)
L
Linus Torvalds 已提交
228
{
A
Alexey Starikovskiy 已提交
229 230 231
	int count = sizeof(*oemtable);	/* the header size */
	unsigned char *oemptr = ((unsigned char *)oemtable) + count;

L
Linus Torvalds 已提交
232
	mpc_record = 0;
A
Alexey Starikovskiy 已提交
233 234 235 236 237 238 239
	printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n",
	       oemtable);
	if (memcmp(oemtable->oem_signature, MPC_OEM_SIGNATURE, 4)) {
		printk(KERN_WARNING
		       "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
		       oemtable->oem_signature[0], oemtable->oem_signature[1],
		       oemtable->oem_signature[2], oemtable->oem_signature[3]);
L
Linus Torvalds 已提交
240 241
		return;
	}
A
Alexey Starikovskiy 已提交
242
	if (mpf_checksum((unsigned char *)oemtable, oemtable->oem_length)) {
L
Linus Torvalds 已提交
243 244 245 246 247
		printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
		return;
	}
	while (count < oemtable->oem_length) {
		switch (*oemptr) {
A
Alexey Starikovskiy 已提交
248
		case MP_TRANSLATION:
L
Linus Torvalds 已提交
249
			{
A
Alexey Starikovskiy 已提交
250 251
				struct mpc_config_translation *m =
				    (struct mpc_config_translation *)oemptr;
L
Linus Torvalds 已提交
252 253 254 255 256 257
				MP_translation_info(m);
				oemptr += sizeof(*m);
				count += sizeof(*m);
				++mpc_record;
				break;
			}
A
Alexey Starikovskiy 已提交
258
		default:
L
Linus Torvalds 已提交
259
			{
A
Alexey Starikovskiy 已提交
260 261 262
				printk(KERN_WARNING
				       "Unrecognised OEM table entry type! - %d\n",
				       (int)*oemptr);
L
Linus Torvalds 已提交
263 264 265
				return;
			}
		}
A
Alexey Starikovskiy 已提交
266
	}
L
Linus Torvalds 已提交
267 268 269
}

static inline void mps_oem_check(struct mp_config_table *mpc, char *oem,
A
Alexey Starikovskiy 已提交
270
				 char *productid)
L
Linus Torvalds 已提交
271 272 273 274
{
	if (strncmp(oem, "IBM NUMA", 8))
		printk("Warning!  May not be a NUMA-Q system!\n");
	if (mpc->mpc_oemptr)
A
Alexey Starikovskiy 已提交
275 276
		smp_read_mpc_oem((struct mp_config_oemtable *)mpc->mpc_oemptr,
				 mpc->mpc_oemsize);
L
Linus Torvalds 已提交
277
}
A
Alexey Starikovskiy 已提交
278
#endif /* CONFIG_X86_NUMAQ */
L
Linus Torvalds 已提交
279 280 281 282 283

/*
 * Read/parse the MPC
 */

284
static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
L
Linus Torvalds 已提交
285 286 287
{
	char str[16];
	char oem[10];
A
Alexey Starikovskiy 已提交
288 289
	int count = sizeof(*mpc);
	unsigned char *mpt = ((unsigned char *)mpc) + count;
L
Linus Torvalds 已提交
290

A
Alexey Starikovskiy 已提交
291
	if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) {
A
Alexey Starikovskiy 已提交
292 293 294
		printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
		       mpc->mpc_signature[0], mpc->mpc_signature[1],
		       mpc->mpc_signature[2], mpc->mpc_signature[3]);
L
Linus Torvalds 已提交
295 296
		return 0;
	}
A
Alexey Starikovskiy 已提交
297
	if (mpf_checksum((unsigned char *)mpc, mpc->mpc_length)) {
A
Alexey Starikovskiy 已提交
298
		printk(KERN_ERR "MPTABLE: checksum error!\n");
L
Linus Torvalds 已提交
299 300
		return 0;
	}
A
Alexey Starikovskiy 已提交
301
	if (mpc->mpc_spec != 0x01 && mpc->mpc_spec != 0x04) {
A
Alexey Starikovskiy 已提交
302
		printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
A
Alexey Starikovskiy 已提交
303
		       mpc->mpc_spec);
L
Linus Torvalds 已提交
304 305 306
		return 0;
	}
	if (!mpc->mpc_lapic) {
A
Alexey Starikovskiy 已提交
307
		printk(KERN_ERR "MPTABLE: null local APIC address!\n");
L
Linus Torvalds 已提交
308 309
		return 0;
	}
A
Alexey Starikovskiy 已提交
310 311
	memcpy(oem, mpc->mpc_oem, 8);
	oem[8] = 0;
Y
Yinghai Lu 已提交
312
	printk(KERN_INFO "MPTABLE: OEM ID: %s\n", oem);
L
Linus Torvalds 已提交
313

A
Alexey Starikovskiy 已提交
314 315
	memcpy(str, mpc->mpc_productid, 12);
	str[12] = 0;
L
Linus Torvalds 已提交
316

A
Alexey Starikovskiy 已提交
317
#ifdef CONFIG_X86_32
L
Linus Torvalds 已提交
318
	mps_oem_check(mpc, oem, str);
A
Alexey Starikovskiy 已提交
319
#endif
Y
Yinghai Lu 已提交
320
	printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
L
Linus Torvalds 已提交
321

A
Alexey Starikovskiy 已提交
322
	printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic);
L
Linus Torvalds 已提交
323

A
Alexey Starikovskiy 已提交
324
	/* save the local APIC address, it might be non-default */
L
Linus Torvalds 已提交
325 326 327
	if (!acpi_lapic)
		mp_lapic_addr = mpc->mpc_lapic;

328 329 330
	if (early)
		return 1;

L
Linus Torvalds 已提交
331
	/*
A
Alexey Starikovskiy 已提交
332
	 *      Now process the configuration blocks.
L
Linus Torvalds 已提交
333
	 */
334
#ifdef CONFIG_X86_NUMAQ
L
Linus Torvalds 已提交
335
	mpc_record = 0;
336
#endif
L
Linus Torvalds 已提交
337
	while (count < mpc->mpc_length) {
A
Alexey Starikovskiy 已提交
338 339
		switch (*mpt) {
		case MP_PROCESSOR:
L
Linus Torvalds 已提交
340
			{
A
Alexey Starikovskiy 已提交
341 342
				struct mpc_config_processor *m =
				    (struct mpc_config_processor *)mpt;
L
Linus Torvalds 已提交
343 344 345 346 347 348 349
				/* ACPI may have already provided this data */
				if (!acpi_lapic)
					MP_processor_info(m);
				mpt += sizeof(*m);
				count += sizeof(*m);
				break;
			}
A
Alexey Starikovskiy 已提交
350
		case MP_BUS:
L
Linus Torvalds 已提交
351
			{
A
Alexey Starikovskiy 已提交
352 353
				struct mpc_config_bus *m =
				    (struct mpc_config_bus *)mpt;
L
Linus Torvalds 已提交
354 355 356 357 358
				MP_bus_info(m);
				mpt += sizeof(*m);
				count += sizeof(*m);
				break;
			}
A
Alexey Starikovskiy 已提交
359
		case MP_IOAPIC:
L
Linus Torvalds 已提交
360
			{
361
#ifdef CONFIG_X86_IO_APIC
A
Alexey Starikovskiy 已提交
362 363
				struct mpc_config_ioapic *m =
				    (struct mpc_config_ioapic *)mpt;
L
Linus Torvalds 已提交
364
				MP_ioapic_info(m);
365
#endif
A
Alexey Starikovskiy 已提交
366 367
				mpt += sizeof(struct mpc_config_ioapic);
				count += sizeof(struct mpc_config_ioapic);
L
Linus Torvalds 已提交
368 369
				break;
			}
A
Alexey Starikovskiy 已提交
370
		case MP_INTSRC:
L
Linus Torvalds 已提交
371
			{
372
#ifdef CONFIG_X86_IO_APIC
A
Alexey Starikovskiy 已提交
373 374
				struct mpc_config_intsrc *m =
				    (struct mpc_config_intsrc *)mpt;
L
Linus Torvalds 已提交
375 376

				MP_intsrc_info(m);
377
#endif
A
Alexey Starikovskiy 已提交
378 379
				mpt += sizeof(struct mpc_config_intsrc);
				count += sizeof(struct mpc_config_intsrc);
L
Linus Torvalds 已提交
380 381
				break;
			}
A
Alexey Starikovskiy 已提交
382
		case MP_LINTSRC:
L
Linus Torvalds 已提交
383
			{
A
Alexey Starikovskiy 已提交
384 385
				struct mpc_config_lintsrc *m =
				    (struct mpc_config_lintsrc *)mpt;
L
Linus Torvalds 已提交
386
				MP_lintsrc_info(m);
A
Alexey Starikovskiy 已提交
387 388
				mpt += sizeof(*m);
				count += sizeof(*m);
L
Linus Torvalds 已提交
389 390
				break;
			}
A
Alexey Starikovskiy 已提交
391
		default:
Y
Yinghai Lu 已提交
392 393 394 395 396 397 398
			/* wrong mptable */
			printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
			printk(KERN_ERR "type %x\n", *mpt);
			print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
					1, mpc, mpc->mpc_length, 1);
			count = mpc->mpc_length;
			break;
L
Linus Torvalds 已提交
399
		}
400
#ifdef CONFIG_X86_NUMAQ
L
Linus Torvalds 已提交
401
		++mpc_record;
402
#endif
L
Linus Torvalds 已提交
403
	}
404
	setup_apic_routing();
L
Linus Torvalds 已提交
405
	if (!num_processors)
A
Alexey Starikovskiy 已提交
406
		printk(KERN_ERR "MPTABLE: no processors registered!\n");
L
Linus Torvalds 已提交
407 408 409
	return num_processors;
}

410 411
#ifdef CONFIG_X86_IO_APIC

L
Linus Torvalds 已提交
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
static int __init ELCR_trigger(unsigned int irq)
{
	unsigned int port;

	port = 0x4d0 + (irq >> 3);
	return (inb(port) >> (irq & 7)) & 1;
}

static void __init construct_default_ioirq_mptable(int mpc_default_type)
{
	struct mpc_config_intsrc intsrc;
	int i;
	int ELCR_fallback = 0;

	intsrc.mpc_type = MP_INTSRC;
A
Alexey Starikovskiy 已提交
427
	intsrc.mpc_irqflag = 0;	/* conforming */
L
Linus Torvalds 已提交
428 429 430 431 432 433 434 435 436 437 438 439 440 441
	intsrc.mpc_srcbus = 0;
	intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;

	intsrc.mpc_irqtype = mp_INT;

	/*
	 *  If true, we have an ISA/PCI system with no IRQ entries
	 *  in the MP table. To prevent the PCI interrupts from being set up
	 *  incorrectly, we try to use the ELCR. The sanity check to see if
	 *  there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
	 *  never be level sensitive, so we simply see if the ELCR agrees.
	 *  If it does, we assume it's valid.
	 */
	if (mpc_default_type == 5) {
442 443
		printk(KERN_INFO "ISA/PCI bus type with no IRQ information... "
		       "falling back to ELCR\n");
L
Linus Torvalds 已提交
444

445 446 447 448
		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) ||
		    ELCR_trigger(13))
			printk(KERN_ERR "ELCR contains invalid data... "
			       "not using ELCR\n");
L
Linus Torvalds 已提交
449
		else {
A
Alexey Starikovskiy 已提交
450 451
			printk(KERN_INFO
			       "Using ELCR to identify PCI interrupts\n");
L
Linus Torvalds 已提交
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
			ELCR_fallback = 1;
		}
	}

	for (i = 0; i < 16; i++) {
		switch (mpc_default_type) {
		case 2:
			if (i == 0 || i == 13)
				continue;	/* IRQ0 & IRQ13 not connected */
			/* fall through */
		default:
			if (i == 2)
				continue;	/* IRQ2 is never connected */
		}

		if (ELCR_fallback) {
			/*
			 *  If the ELCR indicates a level-sensitive interrupt, we
			 *  copy that information over to the MP table in the
			 *  irqflag field (level sensitive, active high polarity).
			 */
			if (ELCR_trigger(i))
				intsrc.mpc_irqflag = 13;
			else
				intsrc.mpc_irqflag = 0;
		}

		intsrc.mpc_srcbusirq = i;
A
Alexey Starikovskiy 已提交
480
		intsrc.mpc_dstirq = i ? i : 2;	/* IRQ0 to INTIN2 */
L
Linus Torvalds 已提交
481 482 483 484 485
		MP_intsrc_info(&intsrc);
	}

	intsrc.mpc_irqtype = mp_ExtINT;
	intsrc.mpc_srcbusirq = 0;
A
Alexey Starikovskiy 已提交
486
	intsrc.mpc_dstirq = 0;	/* 8259A to INTIN0 */
L
Linus Torvalds 已提交
487 488 489
	MP_intsrc_info(&intsrc);
}

490 491
#endif

L
Linus Torvalds 已提交
492 493 494 495
static inline void __init construct_default_ISA_mptable(int mpc_default_type)
{
	struct mpc_config_processor processor;
	struct mpc_config_bus bus;
496
#ifdef CONFIG_X86_IO_APIC
L
Linus Torvalds 已提交
497
	struct mpc_config_ioapic ioapic;
498
#endif
L
Linus Torvalds 已提交
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515
	struct mpc_config_lintsrc lintsrc;
	int linttypes[2] = { mp_ExtINT, mp_NMI };
	int i;

	/*
	 * local APIC has default address
	 */
	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;

	/*
	 * 2 CPUs, numbered 0 & 1.
	 */
	processor.mpc_type = MP_PROCESSOR;
	/* Either an integrated APIC or a discrete 82489DX. */
	processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
	processor.mpc_cpuflag = CPU_ENABLED;
	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
A
Alexey Starikovskiy 已提交
516
	    (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
L
Linus Torvalds 已提交
517 518 519 520 521 522 523 524 525 526 527
	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
	processor.mpc_reserved[0] = 0;
	processor.mpc_reserved[1] = 0;
	for (i = 0; i < 2; i++) {
		processor.mpc_apicid = i;
		MP_processor_info(&processor);
	}

	bus.mpc_type = MP_BUS;
	bus.mpc_busid = 0;
	switch (mpc_default_type) {
A
Alexey Starikovskiy 已提交
528
	default:
529
		printk(KERN_ERR "???\nUnknown standard configuration %d\n",
A
Alexey Starikovskiy 已提交
530 531 532 533 534 535 536 537 538 539 540 541 542 543
		       mpc_default_type);
		/* fall through */
	case 1:
	case 5:
		memcpy(bus.mpc_bustype, "ISA   ", 6);
		break;
	case 2:
	case 6:
	case 3:
		memcpy(bus.mpc_bustype, "EISA  ", 6);
		break;
	case 4:
	case 7:
		memcpy(bus.mpc_bustype, "MCA   ", 6);
L
Linus Torvalds 已提交
544 545 546 547 548 549 550 551
	}
	MP_bus_info(&bus);
	if (mpc_default_type > 4) {
		bus.mpc_busid = 1;
		memcpy(bus.mpc_bustype, "PCI   ", 6);
		MP_bus_info(&bus);
	}

552
#ifdef CONFIG_X86_IO_APIC
L
Linus Torvalds 已提交
553 554 555 556 557 558 559 560 561 562 563
	ioapic.mpc_type = MP_IOAPIC;
	ioapic.mpc_apicid = 2;
	ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
	ioapic.mpc_flags = MPC_APIC_USABLE;
	ioapic.mpc_apicaddr = 0xFEC00000;
	MP_ioapic_info(&ioapic);

	/*
	 * We set up most of the low 16 IO-APIC pins according to MPS rules.
	 */
	construct_default_ioirq_mptable(mpc_default_type);
564
#endif
L
Linus Torvalds 已提交
565
	lintsrc.mpc_type = MP_LINTSRC;
A
Alexey Starikovskiy 已提交
566
	lintsrc.mpc_irqflag = 0;	/* conforming */
L
Linus Torvalds 已提交
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581
	lintsrc.mpc_srcbusid = 0;
	lintsrc.mpc_srcbusirq = 0;
	lintsrc.mpc_destapic = MP_APIC_ALL;
	for (i = 0; i < 2; i++) {
		lintsrc.mpc_irqtype = linttypes[i];
		lintsrc.mpc_destapiclint = i;
		MP_lintsrc_info(&lintsrc);
	}
}

static struct intel_mp_floating *mpf_found;

/*
 * Scan the memory blocks for an SMP configuration block.
 */
582
static void __init __get_smp_config(unsigned early)
L
Linus Torvalds 已提交
583 584 585
{
	struct intel_mp_floating *mpf = mpf_found;

586 587
	if (acpi_lapic && early)
		return;
L
Linus Torvalds 已提交
588
	/*
A
Alexey Starikovskiy 已提交
589
	 * ACPI supports both logical (e.g. Hyper-Threading) and physical
L
Linus Torvalds 已提交
590 591 592
	 * processors, where MPS only supports physical.
	 */
	if (acpi_lapic && acpi_ioapic) {
A
Alexey Starikovskiy 已提交
593 594
		printk(KERN_INFO "Using ACPI (MADT) for SMP configuration "
		       "information\n");
L
Linus Torvalds 已提交
595
		return;
A
Alexey Starikovskiy 已提交
596
	} else if (acpi_lapic)
A
Alexey Starikovskiy 已提交
597 598
		printk(KERN_INFO "Using ACPI for processor (LAPIC) "
		       "configuration information\n");
L
Linus Torvalds 已提交
599

A
Alexey Starikovskiy 已提交
600 601
	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
	       mpf->mpf_specification);
A
Alexey Starikovskiy 已提交
602
#ifdef CONFIG_X86_32
A
Alexey Starikovskiy 已提交
603
	if (mpf->mpf_feature2 & (1 << 7)) {
L
Linus Torvalds 已提交
604 605 606 607 608 609
		printk(KERN_INFO "    IMCR and PIC compatibility mode.\n");
		pic_mode = 1;
	} else {
		printk(KERN_INFO "    Virtual Wire compatibility mode.\n");
		pic_mode = 0;
	}
A
Alexey Starikovskiy 已提交
610
#endif
L
Linus Torvalds 已提交
611 612 613 614
	/*
	 * Now see if we need to read further.
	 */
	if (mpf->mpf_feature1 != 0) {
615 616 617 618 619 620 621
		if (early) {
			/*
			 * local APIC has default address
			 */
			mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
			return;
		}
L
Linus Torvalds 已提交
622

A
Alexey Starikovskiy 已提交
623 624
		printk(KERN_INFO "Default MP configuration #%d\n",
		       mpf->mpf_feature1);
L
Linus Torvalds 已提交
625 626 627 628 629 630 631 632
		construct_default_ISA_mptable(mpf->mpf_feature1);

	} else if (mpf->mpf_physptr) {

		/*
		 * Read the physical hardware table.  Anything here will
		 * override the defaults.
		 */
633
		if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr), early)) {
L
Linus Torvalds 已提交
634
			smp_found_config = 0;
A
Alexey Starikovskiy 已提交
635 636
			printk(KERN_ERR
			       "BIOS bug, MP table errors detected!...\n");
A
Alexey Starikovskiy 已提交
637 638
			printk(KERN_ERR "... disabling SMP support. "
			       "(tell your hw vendor)\n");
L
Linus Torvalds 已提交
639 640
			return;
		}
641

642 643
		if (early)
			return;
644
#ifdef CONFIG_X86_IO_APIC
L
Linus Torvalds 已提交
645 646 647 648 649 650 651 652
		/*
		 * If there are no explicit MP IRQ entries, then we are
		 * broken.  We set up most of the low 16 IO-APIC pins to
		 * ISA defaults and hope it will work.
		 */
		if (!mp_irq_entries) {
			struct mpc_config_bus bus;

A
Alexey Starikovskiy 已提交
653 654 655
			printk(KERN_ERR "BIOS bug, no explicit IRQ entries, "
			       "using default mptable. "
			       "(tell your hw vendor)\n");
L
Linus Torvalds 已提交
656 657 658 659 660 661 662 663

			bus.mpc_type = MP_BUS;
			bus.mpc_busid = 0;
			memcpy(bus.mpc_bustype, "ISA   ", 6);
			MP_bus_info(&bus);

			construct_default_ioirq_mptable(0);
		}
664
#endif
L
Linus Torvalds 已提交
665 666 667
	} else
		BUG();

668 669
	if (!early)
		printk(KERN_INFO "Processors: %d\n", num_processors);
L
Linus Torvalds 已提交
670 671 672 673 674
	/*
	 * Only use the first configuration found.
	 */
}

675 676 677 678 679 680 681 682 683 684 685 686
void __init early_get_smp_config(void)
{
	__get_smp_config(1);
}

void __init get_smp_config(void)
{
	__get_smp_config(0);
}

static int __init smp_scan_config(unsigned long base, unsigned long length,
				  unsigned reserve)
L
Linus Torvalds 已提交
687
{
A
Alexey Starikovskiy 已提交
688
	unsigned int *bp = phys_to_virt(base);
L
Linus Torvalds 已提交
689 690
	struct intel_mp_floating *mpf;

Y
Yinghai Lu 已提交
691
	printk(KERN_DEBUG "Scan SMP from %p for %ld bytes.\n", bp, length);
692
	BUILD_BUG_ON(sizeof(*mpf) != 16);
L
Linus Torvalds 已提交
693 694 695 696

	while (length > 0) {
		mpf = (struct intel_mp_floating *)bp;
		if ((*bp == SMP_MAGIC_IDENT) &&
A
Alexey Starikovskiy 已提交
697 698 699 700
		    (mpf->mpf_length == 1) &&
		    !mpf_checksum((unsigned char *)bp, 16) &&
		    ((mpf->mpf_specification == 1)
		     || (mpf->mpf_specification == 4))) {
L
Linus Torvalds 已提交
701 702

			smp_found_config = 1;
A
Alexey Starikovskiy 已提交
703 704
			mpf_found = mpf;
#ifdef CONFIG_X86_32
705
			printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
A
Alexey Starikovskiy 已提交
706
			       mpf, virt_to_phys(mpf));
707 708
			reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE,
					BOOTMEM_DEFAULT);
L
Linus Torvalds 已提交
709 710 711 712 713 714 715 716 717 718 719 720 721 722
			if (mpf->mpf_physptr) {
				/*
				 * We cannot access to MPC table to compute
				 * table size yet, as only few megabytes from
				 * the bottom is mapped now.
				 * PC-9800's MPC table places on the very last
				 * of physical memory; so that simply reserving
				 * PAGE_SIZE from mpg->mpf_physptr yields BUG()
				 * in reserve_bootmem.
				 */
				unsigned long size = PAGE_SIZE;
				unsigned long end = max_low_pfn * PAGE_SIZE;
				if (mpf->mpf_physptr + size > end)
					size = end - mpf->mpf_physptr;
723 724
				reserve_bootmem(mpf->mpf_physptr, size,
						BOOTMEM_DEFAULT);
L
Linus Torvalds 已提交
725 726
			}

A
Alexey Starikovskiy 已提交
727 728 729 730 731 732 733 734 735 736
#else
			if (!reserve)
				return 1;

			reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE);
			if (mpf->mpf_physptr)
				reserve_bootmem_generic(mpf->mpf_physptr,
							PAGE_SIZE);
#endif
		return 1;
L
Linus Torvalds 已提交
737 738 739 740 741 742 743
		}
		bp += 4;
		length -= 16;
	}
	return 0;
}

744
static void __init __find_smp_config(unsigned reserve)
L
Linus Torvalds 已提交
745 746 747 748 749 750 751 752 753 754 755
{
	unsigned int address;

	/*
	 * FIXME: Linux assumes you have 640K of base ram..
	 * this continues the error...
	 *
	 * 1) Scan the bottom 1K for a signature
	 * 2) Scan the top 1K of base RAM
	 * 3) Scan the 64K of bios
	 */
756 757 758
	if (smp_scan_config(0x0, 0x400, reserve) ||
	    smp_scan_config(639 * 0x400, 0x400, reserve) ||
	    smp_scan_config(0xF0000, 0x10000, reserve))
L
Linus Torvalds 已提交
759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778
		return;
	/*
	 * If it is an SMP machine we should know now, unless the
	 * configuration is in an EISA/MCA bus machine with an
	 * extended bios data area.
	 *
	 * there is a real-mode segmented pointer pointing to the
	 * 4K EBDA area at 0x40E, calculate and scan it here.
	 *
	 * NOTE! There are Linux loaders that will corrupt the EBDA
	 * area, and as such this kind of SMP config may be less
	 * trustworthy, simply because the SMP table may have been
	 * stomped on during early boot. These loaders are buggy and
	 * should be fixed.
	 *
	 * MP1.4 SPEC states to only scan first 1K of 4K EBDA.
	 */

	address = get_bios_ebda();
	if (address)
779 780 781 782 783 784 785 786 787 788 789
		smp_scan_config(address, 0x400, reserve);
}

void __init early_find_smp_config(void)
{
	__find_smp_config(0);
}

void __init find_smp_config(void)
{
	__find_smp_config(1);
L
Linus Torvalds 已提交
790
}