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

#include <linux/mm.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/bootmem.h>
14
#include <linux/memblock.h>
L
Linus Torvalds 已提交
15 16 17
#include <linux/kernel_stat.h>
#include <linux/mc146818rtc.h>
#include <linux/bitops.h>
18 19
#include <linux/acpi.h>
#include <linux/module.h>
20
#include <linux/smp.h>
21
#include <linux/pci.h>
L
Linus Torvalds 已提交
22 23 24

#include <asm/mtrr.h>
#include <asm/mpspec.h>
25
#include <asm/pgalloc.h>
L
Linus Torvalds 已提交
26
#include <asm/io_apic.h>
27
#include <asm/proto.h>
28
#include <asm/bios_ebda.h>
Y
Yinghai Lu 已提交
29 30
#include <asm/e820.h>
#include <asm/trampoline.h>
Y
Yinghai Lu 已提交
31
#include <asm/setup.h>
32
#include <asm/smp.h>
L
Linus Torvalds 已提交
33

I
Ingo Molnar 已提交
34
#include <asm/apic.h>
L
Linus Torvalds 已提交
35 36 37 38 39 40 41 42 43 44 45 46 47 48
/*
 * 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;
}

49 50 51 52 53
int __init default_mpc_apic_id(struct mpc_cpu *m)
{
	return m->apicid;
}

54
static void __init MP_processor_info(struct mpc_cpu *m)
55 56
{
	int apicid;
57
	char *bootup_cpu = "";
58

59
	if (!(m->cpuflag & CPU_ENABLED)) {
G
Glauber Costa 已提交
60
		disabled_cpus++;
L
Linus Torvalds 已提交
61
		return;
G
Glauber Costa 已提交
62
	}
63

64
	apicid = x86_init.mpparse.mpc_apic_id(m);
65

66
	if (m->cpuflag & CPU_BOOTPROCESSOR) {
67
		bootup_cpu = " (Bootup-CPU)";
68
		boot_cpu_physical_apicid = m->apicid;
L
Linus Torvalds 已提交
69 70
	}

71 72
	printk(KERN_INFO "Processor #%d%s\n", m->apicid, bootup_cpu);
	generic_processor_info(apicid, m->apicver);
L
Linus Torvalds 已提交
73 74
}

T
Thomas Gleixner 已提交
75
#ifdef CONFIG_X86_IO_APIC
76
void __init default_mpc_oem_bus_info(struct mpc_bus *m, char *str)
L
Linus Torvalds 已提交
77
{
78
	memcpy(str, m->bustype, 6);
L
Linus Torvalds 已提交
79
	str[6] = 0;
80 81
	apic_printk(APIC_VERBOSE, "Bus #%d is %s\n", m->busid, str);
}
L
Linus Torvalds 已提交
82

83 84 85
static void __init MP_bus_info(struct mpc_bus *m)
{
	char str[7];
L
Linus Torvalds 已提交
86

87
	x86_init.mpparse.mpc_oem_bus_info(m, str);
L
Linus Torvalds 已提交
88

89
#if MAX_MP_BUSSES < 256
90
	if (m->busid >= MAX_MP_BUSSES) {
91
		printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
A
Alexey Starikovskiy 已提交
92
		       " is too large, max. supported is %d\n",
93
		       m->busid, str, MAX_MP_BUSSES - 1);
94 95
		return;
	}
96
#endif
97

A
Alexey Starikovskiy 已提交
98
	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) {
99
		set_bit(m->busid, mp_bus_not_pci);
100
#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
101
		mp_bus_id_to_type[m->busid] = MP_BUS_ISA;
A
Alexey Starikovskiy 已提交
102 103
#endif
	} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) {
104 105
		if (x86_init.mpparse.mpc_oem_pci_bus)
			x86_init.mpparse.mpc_oem_pci_bus(m);
106

107
		clear_bit(m->busid, mp_bus_not_pci);
108
#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
109
		mp_bus_id_to_type[m->busid] = MP_BUS_PCI;
A
Alexey Starikovskiy 已提交
110
	} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA) - 1) == 0) {
111
		mp_bus_id_to_type[m->busid] = MP_BUS_EISA;
A
Alexey Starikovskiy 已提交
112
	} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA) - 1) == 0) {
113
		mp_bus_id_to_type[m->busid] = MP_BUS_MCA;
114
#endif
A
Alexey Starikovskiy 已提交
115 116
	} else
		printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
L
Linus Torvalds 已提交
117
}
118

119
static void __init MP_ioapic_info(struct mpc_ioapic *m)
L
Linus Torvalds 已提交
120
{
121
	if (!(m->flags & MPC_APIC_USABLE))
L
Linus Torvalds 已提交
122 123
		return;

T
Thomas Gleixner 已提交
124
	printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
125
	       m->apicid, m->apicver, m->apicaddr);
126

127
	mp_register_ioapic(m->apicid, m->apicaddr, gsi_top);
L
Linus Torvalds 已提交
128 129
}

130
static void print_MP_intsrc_info(struct mpc_intsrc *m)
L
Linus Torvalds 已提交
131
{
132
	apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
L
Linus Torvalds 已提交
133
		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
134 135
		m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbus,
		m->srcbusirq, m->dstapic, m->dstirq);
Y
Yinghai Lu 已提交
136 137
}

138
static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
Y
Yinghai Lu 已提交
139
{
140
	apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
Y
Yinghai Lu 已提交
141
		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
142 143 144
		mp_irq->irqtype, mp_irq->irqflag & 3,
		(mp_irq->irqflag >> 2) & 3, mp_irq->srcbus,
		mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq);
Y
Yinghai Lu 已提交
145 146
}

147
static void __init assign_to_mp_irq(struct mpc_intsrc *m,
148
				    struct mpc_intsrc *mp_irq)
Y
Yinghai Lu 已提交
149
{
150 151 152 153 154 155 156
	mp_irq->dstapic = m->dstapic;
	mp_irq->type = m->type;
	mp_irq->irqtype = m->irqtype;
	mp_irq->irqflag = m->irqflag;
	mp_irq->srcbus = m->srcbus;
	mp_irq->srcbusirq = m->srcbusirq;
	mp_irq->dstirq = m->dstirq;
Y
Yinghai Lu 已提交
157 158
}

159
static void __init assign_to_mpc_intsrc(struct mpc_intsrc *mp_irq,
160
					struct mpc_intsrc *m)
Y
Yinghai Lu 已提交
161
{
162 163 164 165 166 167 168
	m->dstapic = mp_irq->dstapic;
	m->type = mp_irq->type;
	m->irqtype = mp_irq->irqtype;
	m->irqflag = mp_irq->irqflag;
	m->srcbus = mp_irq->srcbus;
	m->srcbusirq = mp_irq->srcbusirq;
	m->dstirq = mp_irq->dstirq;
Y
Yinghai Lu 已提交
169 170
}

171
static int __init mp_irq_mpc_intsrc_cmp(struct mpc_intsrc *mp_irq,
172
					struct mpc_intsrc *m)
Y
Yinghai Lu 已提交
173
{
174
	if (mp_irq->dstapic != m->dstapic)
Y
Yinghai Lu 已提交
175
		return 1;
176
	if (mp_irq->type != m->type)
Y
Yinghai Lu 已提交
177
		return 2;
178
	if (mp_irq->irqtype != m->irqtype)
Y
Yinghai Lu 已提交
179
		return 3;
180
	if (mp_irq->irqflag != m->irqflag)
Y
Yinghai Lu 已提交
181
		return 4;
182
	if (mp_irq->srcbus != m->srcbus)
Y
Yinghai Lu 已提交
183
		return 5;
184
	if (mp_irq->srcbusirq != m->srcbusirq)
Y
Yinghai Lu 已提交
185
		return 6;
186
	if (mp_irq->dstirq != m->dstirq)
Y
Yinghai Lu 已提交
187 188 189 190 191
		return 7;

	return 0;
}

192
static void __init MP_intsrc_info(struct mpc_intsrc *m)
Y
Yinghai Lu 已提交
193 194 195 196 197
{
	int i;

	print_MP_intsrc_info(m);

198 199 200 201
	for (i = 0; i < mp_irq_entries; i++) {
		if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m))
			return;
	}
Y
Yinghai Lu 已提交
202 203

	assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
L
Linus Torvalds 已提交
204 205 206
	if (++mp_irq_entries == MAX_IRQ_SOURCES)
		panic("Max # of irq sources exceeded!!\n");
}
207 208 209 210 211
#else /* CONFIG_X86_IO_APIC */
static inline void __init MP_bus_info(struct mpc_bus *m) {}
static inline void __init MP_ioapic_info(struct mpc_ioapic *m) {}
static inline void __init MP_intsrc_info(struct mpc_intsrc *m) {}
#endif /* CONFIG_X86_IO_APIC */
L
Linus Torvalds 已提交
212

213

214
static void __init MP_lintsrc_info(struct mpc_lintsrc *m)
L
Linus Torvalds 已提交
215
{
216
	apic_printk(APIC_VERBOSE, "Lint: type %d, pol %d, trig %d, bus %02x,"
L
Linus Torvalds 已提交
217
		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
218 219
		m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbusid,
		m->srcbusirq, m->destapic, m->destapiclint);
L
Linus Torvalds 已提交
220 221 222 223 224 225
}

/*
 * Read/parse the MPC
 */

226
static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str)
L
Linus Torvalds 已提交
227 228
{

229
	if (memcmp(mpc->signature, MPC_SIGNATURE, 4)) {
A
Alexey Starikovskiy 已提交
230
		printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
231 232
		       mpc->signature[0], mpc->signature[1],
		       mpc->signature[2], mpc->signature[3]);
L
Linus Torvalds 已提交
233 234
		return 0;
	}
235
	if (mpf_checksum((unsigned char *)mpc, mpc->length)) {
A
Alexey Starikovskiy 已提交
236
		printk(KERN_ERR "MPTABLE: checksum error!\n");
L
Linus Torvalds 已提交
237 238
		return 0;
	}
239
	if (mpc->spec != 0x01 && mpc->spec != 0x04) {
A
Alexey Starikovskiy 已提交
240
		printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
241
		       mpc->spec);
L
Linus Torvalds 已提交
242 243
		return 0;
	}
244
	if (!mpc->lapic) {
A
Alexey Starikovskiy 已提交
245
		printk(KERN_ERR "MPTABLE: null local APIC address!\n");
L
Linus Torvalds 已提交
246 247
		return 0;
	}
248
	memcpy(oem, mpc->oem, 8);
A
Alexey Starikovskiy 已提交
249
	oem[8] = 0;
Y
Yinghai Lu 已提交
250
	printk(KERN_INFO "MPTABLE: OEM ID: %s\n", oem);
L
Linus Torvalds 已提交
251

252
	memcpy(str, mpc->productid, 12);
A
Alexey Starikovskiy 已提交
253
	str[12] = 0;
L
Linus Torvalds 已提交
254

Y
Yinghai Lu 已提交
255
	printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
L
Linus Torvalds 已提交
256

257
	printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->lapic);
L
Linus Torvalds 已提交
258

Y
Yinghai Lu 已提交
259 260 261
	return 1;
}

262 263 264 265 266 267
static void skip_entry(unsigned char **ptr, int *count, int size)
{
	*ptr += size;
	*count += size;
}

268 269 270 271 272 273 274 275
static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt)
{
	printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n"
		"type %x\n", *mpt);
	print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
			1, mpc, mpc->length, 1);
}

276 277
void __init default_smp_read_mpc_oem(struct mpc_table *mpc) { }

278
static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
Y
Yinghai Lu 已提交
279 280 281 282 283 284 285 286 287 288 289
{
	char str[16];
	char oem[10];

	int count = sizeof(*mpc);
	unsigned char *mpt = ((unsigned char *)mpc) + count;

	if (!smp_check_mpc(mpc, oem, str))
		return 0;

#ifdef CONFIG_X86_32
290
	generic_mps_oem_check(mpc, oem, str);
Y
Yinghai Lu 已提交
291
#endif
292
	/* Initialize the lapic mapping */
L
Linus Torvalds 已提交
293
	if (!acpi_lapic)
294
		register_lapic_address(mpc->lapic);
L
Linus Torvalds 已提交
295

296 297 298
	if (early)
		return 1;

299 300
	if (mpc->oemptr)
		x86_init.mpparse.smp_read_mpc_oem(mpc);
301

L
Linus Torvalds 已提交
302
	/*
A
Alexey Starikovskiy 已提交
303
	 *      Now process the configuration blocks.
L
Linus Torvalds 已提交
304
	 */
305
	x86_init.mpparse.mpc_record(0);
306

307
	while (count < mpc->length) {
A
Alexey Starikovskiy 已提交
308 309
		switch (*mpt) {
		case MP_PROCESSOR:
310 311
			/* ACPI may have already provided this data */
			if (!acpi_lapic)
312
				MP_processor_info((struct mpc_cpu *)mpt);
313 314
			skip_entry(&mpt, &count, sizeof(struct mpc_cpu));
			break;
A
Alexey Starikovskiy 已提交
315
		case MP_BUS:
316
			MP_bus_info((struct mpc_bus *)mpt);
317 318
			skip_entry(&mpt, &count, sizeof(struct mpc_bus));
			break;
A
Alexey Starikovskiy 已提交
319
		case MP_IOAPIC:
320
			MP_ioapic_info((struct mpc_ioapic *)mpt);
321 322
			skip_entry(&mpt, &count, sizeof(struct mpc_ioapic));
			break;
A
Alexey Starikovskiy 已提交
323
		case MP_INTSRC:
324
			MP_intsrc_info((struct mpc_intsrc *)mpt);
325 326
			skip_entry(&mpt, &count, sizeof(struct mpc_intsrc));
			break;
A
Alexey Starikovskiy 已提交
327
		case MP_LINTSRC:
328
			MP_lintsrc_info((struct mpc_lintsrc *)mpt);
329 330
			skip_entry(&mpt, &count, sizeof(struct mpc_lintsrc));
			break;
A
Alexey Starikovskiy 已提交
331
		default:
Y
Yinghai Lu 已提交
332
			/* wrong mptable */
333
			smp_dump_mptable(mpc, mpt);
334
			count = mpc->length;
Y
Yinghai Lu 已提交
335
			break;
L
Linus Torvalds 已提交
336
		}
337
		x86_init.mpparse.mpc_record(1);
L
Linus Torvalds 已提交
338
	}
339

L
Linus Torvalds 已提交
340
	if (!num_processors)
A
Alexey Starikovskiy 已提交
341
		printk(KERN_ERR "MPTABLE: no processors registered!\n");
L
Linus Torvalds 已提交
342 343 344
	return num_processors;
}

345 346
#ifdef CONFIG_X86_IO_APIC

L
Linus Torvalds 已提交
347 348 349 350 351 352 353 354 355 356
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)
{
357
	struct mpc_intsrc intsrc;
L
Linus Torvalds 已提交
358 359 360
	int i;
	int ELCR_fallback = 0;

361 362 363
	intsrc.type = MP_INTSRC;
	intsrc.irqflag = 0;	/* conforming */
	intsrc.srcbus = 0;
364
	intsrc.dstapic = mp_ioapics[0].apicid;
L
Linus Torvalds 已提交
365

366
	intsrc.irqtype = mp_INT;
L
Linus Torvalds 已提交
367 368 369 370 371 372 373 374 375 376

	/*
	 *  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) {
377 378
		printk(KERN_INFO "ISA/PCI bus type with no IRQ information... "
		       "falling back to ELCR\n");
L
Linus Torvalds 已提交
379

380 381 382 383
		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 已提交
384
		else {
A
Alexey Starikovskiy 已提交
385 386
			printk(KERN_INFO
			       "Using ELCR to identify PCI interrupts\n");
L
Linus Torvalds 已提交
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
			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))
409
				intsrc.irqflag = 13;
L
Linus Torvalds 已提交
410
			else
411
				intsrc.irqflag = 0;
L
Linus Torvalds 已提交
412 413
		}

414 415
		intsrc.srcbusirq = i;
		intsrc.dstirq = i ? i : 2;	/* IRQ0 to INTIN2 */
L
Linus Torvalds 已提交
416 417 418
		MP_intsrc_info(&intsrc);
	}

419 420 421
	intsrc.irqtype = mp_ExtINT;
	intsrc.srcbusirq = 0;
	intsrc.dstirq = 0;	/* 8259A to INTIN0 */
L
Linus Torvalds 已提交
422 423 424
	MP_intsrc_info(&intsrc);
}

425

426
static void __init construct_ioapic_table(int mpc_default_type)
L
Linus Torvalds 已提交
427
{
428
	struct mpc_ioapic ioapic;
429
	struct mpc_bus bus;
L
Linus Torvalds 已提交
430

431 432
	bus.type = MP_BUS;
	bus.busid = 0;
L
Linus Torvalds 已提交
433
	switch (mpc_default_type) {
A
Alexey Starikovskiy 已提交
434
	default:
435
		printk(KERN_ERR "???\nUnknown standard configuration %d\n",
A
Alexey Starikovskiy 已提交
436 437 438 439
		       mpc_default_type);
		/* fall through */
	case 1:
	case 5:
440
		memcpy(bus.bustype, "ISA   ", 6);
A
Alexey Starikovskiy 已提交
441 442 443 444
		break;
	case 2:
	case 6:
	case 3:
445
		memcpy(bus.bustype, "EISA  ", 6);
A
Alexey Starikovskiy 已提交
446 447 448
		break;
	case 4:
	case 7:
449
		memcpy(bus.bustype, "MCA   ", 6);
L
Linus Torvalds 已提交
450 451 452
	}
	MP_bus_info(&bus);
	if (mpc_default_type > 4) {
453 454
		bus.busid = 1;
		memcpy(bus.bustype, "PCI   ", 6);
L
Linus Torvalds 已提交
455 456 457
		MP_bus_info(&bus);
	}

458 459 460 461 462
	ioapic.type	= MP_IOAPIC;
	ioapic.apicid	= 2;
	ioapic.apicver	= mpc_default_type > 4 ? 0x10 : 0x01;
	ioapic.flags	= MPC_APIC_USABLE;
	ioapic.apicaddr	= IO_APIC_DEFAULT_PHYS_BASE;
L
Linus Torvalds 已提交
463 464 465 466 467 468
	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);
T
Thomas Gleixner 已提交
469 470
}
#else
471
static inline void __init construct_ioapic_table(int mpc_default_type) { }
472
#endif
T
Thomas Gleixner 已提交
473 474 475

static inline void __init construct_default_ISA_mptable(int mpc_default_type)
{
476
	struct mpc_cpu processor;
477
	struct mpc_lintsrc lintsrc;
T
Thomas Gleixner 已提交
478 479 480 481 482 483 484 485 486 487 488
	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.
	 */
489
	processor.type = MP_PROCESSOR;
T
Thomas Gleixner 已提交
490
	/* Either an integrated APIC or a discrete 82489DX. */
491 492 493
	processor.apicver = mpc_default_type > 4 ? 0x10 : 0x01;
	processor.cpuflag = CPU_ENABLED;
	processor.cpufeature = (boot_cpu_data.x86 << 8) |
T
Thomas Gleixner 已提交
494
	    (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
495 496 497
	processor.featureflag = boot_cpu_data.x86_capability[0];
	processor.reserved[0] = 0;
	processor.reserved[1] = 0;
T
Thomas Gleixner 已提交
498
	for (i = 0; i < 2; i++) {
499
		processor.apicid = i;
T
Thomas Gleixner 已提交
500 501 502 503 504
		MP_processor_info(&processor);
	}

	construct_ioapic_table(mpc_default_type);

505 506 507 508 509
	lintsrc.type = MP_LINTSRC;
	lintsrc.irqflag = 0;		/* conforming */
	lintsrc.srcbusid = 0;
	lintsrc.srcbusirq = 0;
	lintsrc.destapic = MP_APIC_ALL;
L
Linus Torvalds 已提交
510
	for (i = 0; i < 2; i++) {
511 512
		lintsrc.irqtype = linttypes[i];
		lintsrc.destapiclint = i;
L
Linus Torvalds 已提交
513 514 515 516
		MP_lintsrc_info(&lintsrc);
	}
}

517
static struct mpf_intel *mpf_found;
L
Linus Torvalds 已提交
518

Y
Yinghai Lu 已提交
519 520 521 522 523 524 525 526 527 528 529 530 531
static unsigned long __init get_mpc_size(unsigned long physptr)
{
	struct mpc_table *mpc;
	unsigned long size;

	mpc = early_ioremap(physptr, PAGE_SIZE);
	size = mpc->length;
	early_iounmap(mpc, PAGE_SIZE);
	apic_printk(APIC_VERBOSE, "  mpc: %lx-%lx\n", physptr, physptr + size);

	return size;
}

532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580
static int __init check_physptr(struct mpf_intel *mpf, unsigned int early)
{
	struct mpc_table *mpc;
	unsigned long size;

	size = get_mpc_size(mpf->physptr);
	mpc = early_ioremap(mpf->physptr, size);
	/*
	 * Read the physical hardware table.  Anything here will
	 * override the defaults.
	 */
	if (!smp_read_mpc(mpc, early)) {
#ifdef CONFIG_X86_LOCAL_APIC
		smp_found_config = 0;
#endif
		printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"
			"... disabling SMP support. (tell your hw vendor)\n");
		early_iounmap(mpc, size);
		return -1;
	}
	early_iounmap(mpc, size);

	if (early)
		return -1;

#ifdef CONFIG_X86_IO_APIC
	/*
	 * 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_bus bus;

		printk(KERN_ERR "BIOS bug, no explicit IRQ entries, "
		       "using default mptable. (tell your hw vendor)\n");

		bus.type = MP_BUS;
		bus.busid = 0;
		memcpy(bus.bustype, "ISA   ", 6);
		MP_bus_info(&bus);

		construct_default_ioirq_mptable(0);
	}
#endif

	return 0;
}

L
Linus Torvalds 已提交
581 582 583
/*
 * Scan the memory blocks for an SMP configuration block.
 */
584
void __init default_get_smp_config(unsigned int early)
L
Linus Torvalds 已提交
585
{
586
	struct mpf_intel *mpf = mpf_found;
L
Linus Torvalds 已提交
587

Y
Yinghai Lu 已提交
588 589 590
	if (!mpf)
		return;

591 592
	if (acpi_lapic && early)
		return;
Y
Yinghai Lu 已提交
593

L
Linus Torvalds 已提交
594
	/*
Y
Yinghai Lu 已提交
595 596
	 * MPS doesn't support hyperthreading, aka only have
	 * thread 0 apic id in MPS table
L
Linus Torvalds 已提交
597
	 */
Y
Yinghai Lu 已提交
598
	if (acpi_lapic && acpi_ioapic)
L
Linus Torvalds 已提交
599 600
		return;

A
Alexey Starikovskiy 已提交
601
	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
602
	       mpf->specification);
603
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32)
604
	if (mpf->feature2 & (1 << 7)) {
L
Linus Torvalds 已提交
605 606 607 608 609 610
		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 已提交
611
#endif
L
Linus Torvalds 已提交
612 613 614
	/*
	 * Now see if we need to read further.
	 */
615
	if (mpf->feature1 != 0) {
616 617 618 619 620 621 622
		if (early) {
			/*
			 * local APIC has default address
			 */
			mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
			return;
		}
L
Linus Torvalds 已提交
623

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

628
	} else if (mpf->physptr) {
629
		if (check_physptr(mpf, early))
L
Linus Torvalds 已提交
630 631 632 633
			return;
	} else
		BUG();

634 635
	if (!early)
		printk(KERN_INFO "Processors: %d\n", num_processors);
L
Linus Torvalds 已提交
636 637 638 639 640
	/*
	 * Only use the first configuration found.
	 */
}

641
static void __init smp_reserve_memory(struct mpf_intel *mpf)
642 643 644
{
	unsigned long size = get_mpc_size(mpf->physptr);

645
	memblock_x86_reserve_range(mpf->physptr, mpf->physptr+size, "* MP-table mpc");
646 647
}

648
static int __init smp_scan_config(unsigned long base, unsigned long length)
L
Linus Torvalds 已提交
649
{
A
Alexey Starikovskiy 已提交
650
	unsigned int *bp = phys_to_virt(base);
651
	struct mpf_intel *mpf;
652
	unsigned long mem;
L
Linus Torvalds 已提交
653

654 655
	apic_printk(APIC_VERBOSE, "Scan SMP from %p for %ld bytes.\n",
			bp, length);
656
	BUILD_BUG_ON(sizeof(*mpf) != 16);
L
Linus Torvalds 已提交
657 658

	while (length > 0) {
659
		mpf = (struct mpf_intel *)bp;
L
Linus Torvalds 已提交
660
		if ((*bp == SMP_MAGIC_IDENT) &&
661
		    (mpf->length == 1) &&
A
Alexey Starikovskiy 已提交
662
		    !mpf_checksum((unsigned char *)bp, 16) &&
663 664
		    ((mpf->specification == 1)
		     || (mpf->specification == 4))) {
A
Alexey Starikovskiy 已提交
665
#ifdef CONFIG_X86_LOCAL_APIC
L
Linus Torvalds 已提交
666
			smp_found_config = 1;
A
Alexey Starikovskiy 已提交
667
#endif
A
Alexey Starikovskiy 已提交
668
			mpf_found = mpf;
669

670 671
			printk(KERN_INFO "found SMP MP-table at [%p] %llx\n",
			       mpf, (u64)virt_to_phys(mpf));
672

673
			mem = virt_to_phys(mpf);
674
			memblock_x86_reserve_range(mem, mem + sizeof(*mpf), "* MP-table mpf");
675
			if (mpf->physptr)
676
				smp_reserve_memory(mpf);
L
Linus Torvalds 已提交
677

678
			return 1;
L
Linus Torvalds 已提交
679 680 681 682 683 684 685
		}
		bp += 4;
		length -= 16;
	}
	return 0;
}

686
void __init default_find_smp_config(void)
L
Linus Torvalds 已提交
687 688 689 690 691 692 693 694 695 696 697
{
	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
	 */
698 699 700
	if (smp_scan_config(0x0, 0x400) ||
	    smp_scan_config(639 * 0x400, 0x400) ||
	    smp_scan_config(0xF0000, 0x10000))
L
Linus Torvalds 已提交
701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720
		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)
721
		smp_scan_config(address, 0x400);
722 723
}

Y
Yinghai Lu 已提交
724 725 726
#ifdef CONFIG_X86_IO_APIC
static u8 __initdata irq_used[MAX_IRQ_SOURCES];

727
static int  __init get_MP_intsrc_index(struct mpc_intsrc *m)
Y
Yinghai Lu 已提交
728 729 730
{
	int i;

731
	if (m->irqtype != mp_INT)
Y
Yinghai Lu 已提交
732 733
		return 0;

734
	if (m->irqflag != 0x0f)
Y
Yinghai Lu 已提交
735 736 737 738 739
		return 0;

	/* not legacy */

	for (i = 0; i < mp_irq_entries; i++) {
740
		if (mp_irqs[i].irqtype != mp_INT)
Y
Yinghai Lu 已提交
741 742
			continue;

743
		if (mp_irqs[i].irqflag != 0x0f)
Y
Yinghai Lu 已提交
744 745
			continue;

746
		if (mp_irqs[i].srcbus != m->srcbus)
Y
Yinghai Lu 已提交
747
			continue;
748
		if (mp_irqs[i].srcbusirq != m->srcbusirq)
Y
Yinghai Lu 已提交
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
			continue;
		if (irq_used[i]) {
			/* already claimed */
			return -2;
		}
		irq_used[i] = 1;
		return i;
	}

	/* not found */
	return -1;
}

#define SPARE_SLOT_NUM 20

764
static struct mpc_intsrc __initdata *m_spare[SPARE_SLOT_NUM];
765

766
static void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare)
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793
{
	int i;

	apic_printk(APIC_VERBOSE, "OLD ");
	print_MP_intsrc_info(m);

	i = get_MP_intsrc_index(m);
	if (i > 0) {
		assign_to_mpc_intsrc(&mp_irqs[i], m);
		apic_printk(APIC_VERBOSE, "NEW ");
		print_mp_irq_info(&mp_irqs[i]);
		return;
	}
	if (!i) {
		/* legacy, do nothing */
		return;
	}
	if (*nr_m_spare < SPARE_SLOT_NUM) {
		/*
		 * not found (-1), or duplicated (-2) are invalid entries,
		 * we need to use the slot later
		 */
		m_spare[*nr_m_spare] = m;
		*nr_m_spare += 1;
	}
}
#else /* CONFIG_X86_IO_APIC */
794 795
static
inline void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {}
796 797
#endif /* CONFIG_X86_IO_APIC */

Y
Yinghai Lu 已提交
798 799
static int
check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length, int count)
800
{
Y
Yinghai Lu 已提交
801 802 803 804 805
	int ret = 0;

	if (!mpc_new_phys || count <= mpc_new_length) {
		WARN(1, "update_mptable: No spare slots (length: %x)\n", count);
		return -1;
806 807
	}

Y
Yinghai Lu 已提交
808
	return ret;
809
}
Y
Yinghai Lu 已提交
810

811
static int  __init replace_intsrc_all(struct mpc_table *mpc,
Y
Yinghai Lu 已提交
812 813 814 815 816 817 818
					unsigned long mpc_new_phys,
					unsigned long mpc_new_length)
{
#ifdef CONFIG_X86_IO_APIC
	int i;
#endif
	int count = sizeof(*mpc);
819
	int nr_m_spare = 0;
Y
Yinghai Lu 已提交
820 821
	unsigned char *mpt = ((unsigned char *)mpc) + count;

822 823
	printk(KERN_INFO "mpc_length %x\n", mpc->length);
	while (count < mpc->length) {
Y
Yinghai Lu 已提交
824 825
		switch (*mpt) {
		case MP_PROCESSOR:
826 827
			skip_entry(&mpt, &count, sizeof(struct mpc_cpu));
			break;
Y
Yinghai Lu 已提交
828
		case MP_BUS:
829 830
			skip_entry(&mpt, &count, sizeof(struct mpc_bus));
			break;
Y
Yinghai Lu 已提交
831
		case MP_IOAPIC:
832 833
			skip_entry(&mpt, &count, sizeof(struct mpc_ioapic));
			break;
Y
Yinghai Lu 已提交
834
		case MP_INTSRC:
835
			check_irq_src((struct mpc_intsrc *)mpt, &nr_m_spare);
836 837
			skip_entry(&mpt, &count, sizeof(struct mpc_intsrc));
			break;
Y
Yinghai Lu 已提交
838
		case MP_LINTSRC:
839 840
			skip_entry(&mpt, &count, sizeof(struct mpc_lintsrc));
			break;
Y
Yinghai Lu 已提交
841 842
		default:
			/* wrong mptable */
843
			smp_dump_mptable(mpc, mpt);
Y
Yinghai Lu 已提交
844 845 846 847 848 849 850 851 852
			goto out;
		}
	}

#ifdef CONFIG_X86_IO_APIC
	for (i = 0; i < mp_irq_entries; i++) {
		if (irq_used[i])
			continue;

853
		if (mp_irqs[i].irqtype != mp_INT)
Y
Yinghai Lu 已提交
854 855
			continue;

856
		if (mp_irqs[i].irqflag != 0x0f)
Y
Yinghai Lu 已提交
857 858 859
			continue;

		if (nr_m_spare > 0) {
860
			apic_printk(APIC_VERBOSE, "*NEW* found\n");
Y
Yinghai Lu 已提交
861 862 863 864
			nr_m_spare--;
			assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]);
			m_spare[nr_m_spare] = NULL;
		} else {
865 866
			struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
			count += sizeof(struct mpc_intsrc);
Y
Yinghai Lu 已提交
867
			if (check_slot(mpc_new_phys, mpc_new_length, count) < 0)
868
				goto out;
Y
Yinghai Lu 已提交
869
			assign_to_mpc_intsrc(&mp_irqs[i], m);
870
			mpc->length = count;
871
			mpt += sizeof(struct mpc_intsrc);
Y
Yinghai Lu 已提交
872 873 874 875 876 877
		}
		print_mp_irq_info(&mp_irqs[i]);
	}
#endif
out:
	/* update checksum */
878 879
	mpc->checksum = 0;
	mpc->checksum -= mpf_checksum((unsigned char *)mpc, mpc->length);
Y
Yinghai Lu 已提交
880 881 882 883

	return 0;
}

884
int enable_update_mptable;
885

Y
Yinghai Lu 已提交
886 887 888
static int __init update_mptable_setup(char *str)
{
	enable_update_mptable = 1;
889 890 891
#ifdef CONFIG_PCI
	pci_routeirq = 1;
#endif
Y
Yinghai Lu 已提交
892 893 894 895 896 897 898 899 900 901 902 903
	return 0;
}
early_param("update_mptable", update_mptable_setup);

static unsigned long __initdata mpc_new_phys;
static unsigned long mpc_new_length __initdata = 4096;

/* alloc_mptable or alloc_mptable=4k */
static int __initdata alloc_mptable;
static int __init parse_alloc_mptable_opt(char *p)
{
	enable_update_mptable = 1;
904 905 906
#ifdef CONFIG_PCI
	pci_routeirq = 1;
#endif
Y
Yinghai Lu 已提交
907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926
	alloc_mptable = 1;
	if (!p)
		return 0;
	mpc_new_length = memparse(p, &p);
	return 0;
}
early_param("alloc_mptable", parse_alloc_mptable_opt);

void __init early_reserve_e820_mpc_new(void)
{
	if (enable_update_mptable && alloc_mptable) {
		u64 startt = 0;
		mpc_new_phys = early_reserve_e820(startt, mpc_new_length, 4);
	}
}

static int __init update_mp_table(void)
{
	char str[16];
	char oem[10];
927
	struct mpf_intel *mpf;
928
	struct mpc_table *mpc, *mpc_new;
Y
Yinghai Lu 已提交
929 930 931 932 933 934 935 936 937 938 939

	if (!enable_update_mptable)
		return 0;

	mpf = mpf_found;
	if (!mpf)
		return 0;

	/*
	 * Now see if we need to go further.
	 */
940
	if (mpf->feature1 != 0)
Y
Yinghai Lu 已提交
941 942
		return 0;

943
	if (!mpf->physptr)
Y
Yinghai Lu 已提交
944 945
		return 0;

946
	mpc = phys_to_virt(mpf->physptr);
Y
Yinghai Lu 已提交
947 948 949 950

	if (!smp_check_mpc(mpc, oem, str))
		return 0;

951
	printk(KERN_INFO "mpf: %llx\n", (u64)virt_to_phys(mpf));
952
	printk(KERN_INFO "physptr: %x\n", mpf->physptr);
Y
Yinghai Lu 已提交
953

954
	if (mpc_new_phys && mpc->length > mpc_new_length) {
Y
Yinghai Lu 已提交
955 956 957 958 959 960 961 962
		mpc_new_phys = 0;
		printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n",
			 mpc_new_length);
	}

	if (!mpc_new_phys) {
		unsigned char old, new;
		/* check if we can change the postion */
963 964 965 966
		mpc->checksum = 0;
		old = mpf_checksum((unsigned char *)mpc, mpc->length);
		mpc->checksum = 0xff;
		new = mpf_checksum((unsigned char *)mpc, mpc->length);
Y
Yinghai Lu 已提交
967 968 969 970 971 972
		if (old == new) {
			printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
			return 0;
		}
		printk(KERN_INFO "use in-positon replacing\n");
	} else {
973
		mpf->physptr = mpc_new_phys;
Y
Yinghai Lu 已提交
974
		mpc_new = phys_to_virt(mpc_new_phys);
975
		memcpy(mpc_new, mpc, mpc->length);
Y
Yinghai Lu 已提交
976 977
		mpc = mpc_new;
		/* check if we can modify that */
978
		if (mpc_new_phys - mpf->physptr) {
979
			struct mpf_intel *mpf_new;
Y
Yinghai Lu 已提交
980 981 982 983 984
			/* steal 16 bytes from [0, 1k) */
			printk(KERN_INFO "mpf new: %x\n", 0x400 - 16);
			mpf_new = phys_to_virt(0x400 - 16);
			memcpy(mpf_new, mpf, 16);
			mpf = mpf_new;
985
			mpf->physptr = mpc_new_phys;
Y
Yinghai Lu 已提交
986
		}
987 988 989
		mpf->checksum = 0;
		mpf->checksum -= mpf_checksum((unsigned char *)mpf, 16);
		printk(KERN_INFO "physptr new: %x\n", mpf->physptr);
Y
Yinghai Lu 已提交
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
	}

	/*
	 * only replace the one with mp_INT and
	 *	 MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
	 * already in mp_irqs , stored by ... and mp_config_acpi_gsi,
	 * may need pci=routeirq for all coverage
	 */
	replace_intsrc_all(mpc, mpc_new_phys, mpc_new_length);

	return 0;
}

late_initcall(update_mp_table);