mpparse.c 23.9 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 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>
19
#include <linux/smp.h>
20
#include <linux/pci.h>
L
Linus Torvalds 已提交
21 22 23

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

137
static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
Y
Yinghai Lu 已提交
138
{
139
	apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
Y
Yinghai Lu 已提交
140
		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
141 142 143
		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 已提交
144 145
}

146
static void __init assign_to_mp_irq(struct mpc_intsrc *m,
147
				    struct mpc_intsrc *mp_irq)
Y
Yinghai Lu 已提交
148
{
149 150 151 152 153 154 155
	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 已提交
156 157
}

158
static void __init assign_to_mpc_intsrc(struct mpc_intsrc *mp_irq,
159
					struct mpc_intsrc *m)
Y
Yinghai Lu 已提交
160
{
161 162 163 164 165 166 167
	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 已提交
168 169
}

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

	return 0;
}

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

	print_MP_intsrc_info(m);

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

	assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
L
Linus Torvalds 已提交
203 204 205
	if (++mp_irq_entries == MAX_IRQ_SOURCES)
		panic("Max # of irq sources exceeded!!\n");
}
206 207 208 209 210
#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 已提交
211

212

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

/*
 * Read/parse the MPC
 */

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

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

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

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

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

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

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

267 268 269 270 271 272 273 274
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);
}

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

277 278 279 280 281 282 283 284 285 286 287 288
static void __init smp_register_lapic_address(unsigned long address)
{
	mp_lapic_addr = address;

	set_fixmap_nocache(FIX_APIC_BASE, address);
	if (boot_cpu_physical_apicid == -1U) {
		boot_cpu_physical_apicid  = read_apic_id();
		apic_version[boot_cpu_physical_apicid] =
			 GET_APIC_VERSION(apic_read(APIC_LVR));
	}
}

289
static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
Y
Yinghai Lu 已提交
290 291 292 293 294 295 296 297 298 299 300
{
	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
301
	generic_mps_oem_check(mpc, oem, str);
Y
Yinghai Lu 已提交
302
#endif
A
Alexey Starikovskiy 已提交
303
	/* save the local APIC address, it might be non-default */
L
Linus Torvalds 已提交
304
	if (!acpi_lapic)
305
		mp_lapic_addr = mpc->lapic;
L
Linus Torvalds 已提交
306

307 308 309
	if (early)
		return 1;

310 311 312 313
	/* Initialize the lapic mapping */
	if (!acpi_lapic)
		smp_register_lapic_address(mpc->lapic);

314 315
	if (mpc->oemptr)
		x86_init.mpparse.smp_read_mpc_oem(mpc);
316

L
Linus Torvalds 已提交
317
	/*
A
Alexey Starikovskiy 已提交
318
	 *      Now process the configuration blocks.
L
Linus Torvalds 已提交
319
	 */
320
	x86_init.mpparse.mpc_record(0);
321

322
	while (count < mpc->length) {
A
Alexey Starikovskiy 已提交
323 324
		switch (*mpt) {
		case MP_PROCESSOR:
325 326
			/* ACPI may have already provided this data */
			if (!acpi_lapic)
327
				MP_processor_info((struct mpc_cpu *)mpt);
328 329
			skip_entry(&mpt, &count, sizeof(struct mpc_cpu));
			break;
A
Alexey Starikovskiy 已提交
330
		case MP_BUS:
331
			MP_bus_info((struct mpc_bus *)mpt);
332 333
			skip_entry(&mpt, &count, sizeof(struct mpc_bus));
			break;
A
Alexey Starikovskiy 已提交
334
		case MP_IOAPIC:
335
			MP_ioapic_info((struct mpc_ioapic *)mpt);
336 337
			skip_entry(&mpt, &count, sizeof(struct mpc_ioapic));
			break;
A
Alexey Starikovskiy 已提交
338
		case MP_INTSRC:
339
			MP_intsrc_info((struct mpc_intsrc *)mpt);
340 341
			skip_entry(&mpt, &count, sizeof(struct mpc_intsrc));
			break;
A
Alexey Starikovskiy 已提交
342
		case MP_LINTSRC:
343
			MP_lintsrc_info((struct mpc_lintsrc *)mpt);
344 345
			skip_entry(&mpt, &count, sizeof(struct mpc_lintsrc));
			break;
A
Alexey Starikovskiy 已提交
346
		default:
Y
Yinghai Lu 已提交
347
			/* wrong mptable */
348
			smp_dump_mptable(mpc, mpt);
349
			count = mpc->length;
Y
Yinghai Lu 已提交
350
			break;
L
Linus Torvalds 已提交
351
		}
352
		x86_init.mpparse.mpc_record(1);
L
Linus Torvalds 已提交
353
	}
354

L
Linus Torvalds 已提交
355
	if (!num_processors)
A
Alexey Starikovskiy 已提交
356
		printk(KERN_ERR "MPTABLE: no processors registered!\n");
L
Linus Torvalds 已提交
357 358 359
	return num_processors;
}

360 361
#ifdef CONFIG_X86_IO_APIC

L
Linus Torvalds 已提交
362 363 364 365 366 367 368 369 370 371
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)
{
372
	struct mpc_intsrc intsrc;
L
Linus Torvalds 已提交
373 374 375
	int i;
	int ELCR_fallback = 0;

376 377 378
	intsrc.type = MP_INTSRC;
	intsrc.irqflag = 0;	/* conforming */
	intsrc.srcbus = 0;
379
	intsrc.dstapic = mp_ioapics[0].apicid;
L
Linus Torvalds 已提交
380

381
	intsrc.irqtype = mp_INT;
L
Linus Torvalds 已提交
382 383 384 385 386 387 388 389 390 391

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

395 396 397 398
		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 已提交
399
		else {
A
Alexey Starikovskiy 已提交
400 401
			printk(KERN_INFO
			       "Using ELCR to identify PCI interrupts\n");
L
Linus Torvalds 已提交
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
			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))
424
				intsrc.irqflag = 13;
L
Linus Torvalds 已提交
425
			else
426
				intsrc.irqflag = 0;
L
Linus Torvalds 已提交
427 428
		}

429 430
		intsrc.srcbusirq = i;
		intsrc.dstirq = i ? i : 2;	/* IRQ0 to INTIN2 */
L
Linus Torvalds 已提交
431 432 433
		MP_intsrc_info(&intsrc);
	}

434 435 436
	intsrc.irqtype = mp_ExtINT;
	intsrc.srcbusirq = 0;
	intsrc.dstirq = 0;	/* 8259A to INTIN0 */
L
Linus Torvalds 已提交
437 438 439
	MP_intsrc_info(&intsrc);
}

440

441
static void __init construct_ioapic_table(int mpc_default_type)
L
Linus Torvalds 已提交
442
{
443
	struct mpc_ioapic ioapic;
444
	struct mpc_bus bus;
L
Linus Torvalds 已提交
445

446 447
	bus.type = MP_BUS;
	bus.busid = 0;
L
Linus Torvalds 已提交
448
	switch (mpc_default_type) {
A
Alexey Starikovskiy 已提交
449
	default:
450
		printk(KERN_ERR "???\nUnknown standard configuration %d\n",
A
Alexey Starikovskiy 已提交
451 452 453 454
		       mpc_default_type);
		/* fall through */
	case 1:
	case 5:
455
		memcpy(bus.bustype, "ISA   ", 6);
A
Alexey Starikovskiy 已提交
456 457 458 459
		break;
	case 2:
	case 6:
	case 3:
460
		memcpy(bus.bustype, "EISA  ", 6);
A
Alexey Starikovskiy 已提交
461 462 463
		break;
	case 4:
	case 7:
464
		memcpy(bus.bustype, "MCA   ", 6);
L
Linus Torvalds 已提交
465 466 467
	}
	MP_bus_info(&bus);
	if (mpc_default_type > 4) {
468 469
		bus.busid = 1;
		memcpy(bus.bustype, "PCI   ", 6);
L
Linus Torvalds 已提交
470 471 472
		MP_bus_info(&bus);
	}

473 474 475 476 477
	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 已提交
478 479 480 481 482 483
	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 已提交
484 485
}
#else
486
static inline void __init construct_ioapic_table(int mpc_default_type) { }
487
#endif
T
Thomas Gleixner 已提交
488 489 490

static inline void __init construct_default_ISA_mptable(int mpc_default_type)
{
491
	struct mpc_cpu processor;
492
	struct mpc_lintsrc lintsrc;
T
Thomas Gleixner 已提交
493 494 495 496 497 498 499 500 501 502 503
	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.
	 */
504
	processor.type = MP_PROCESSOR;
T
Thomas Gleixner 已提交
505
	/* Either an integrated APIC or a discrete 82489DX. */
506 507 508
	processor.apicver = mpc_default_type > 4 ? 0x10 : 0x01;
	processor.cpuflag = CPU_ENABLED;
	processor.cpufeature = (boot_cpu_data.x86 << 8) |
T
Thomas Gleixner 已提交
509
	    (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
510 511 512
	processor.featureflag = boot_cpu_data.x86_capability[0];
	processor.reserved[0] = 0;
	processor.reserved[1] = 0;
T
Thomas Gleixner 已提交
513
	for (i = 0; i < 2; i++) {
514
		processor.apicid = i;
T
Thomas Gleixner 已提交
515 516 517 518 519
		MP_processor_info(&processor);
	}

	construct_ioapic_table(mpc_default_type);

520 521 522 523 524
	lintsrc.type = MP_LINTSRC;
	lintsrc.irqflag = 0;		/* conforming */
	lintsrc.srcbusid = 0;
	lintsrc.srcbusirq = 0;
	lintsrc.destapic = MP_APIC_ALL;
L
Linus Torvalds 已提交
525
	for (i = 0; i < 2; i++) {
526 527
		lintsrc.irqtype = linttypes[i];
		lintsrc.destapiclint = i;
L
Linus Torvalds 已提交
528 529 530 531
		MP_lintsrc_info(&lintsrc);
	}
}

532
static struct mpf_intel *mpf_found;
L
Linus Torvalds 已提交
533

Y
Yinghai Lu 已提交
534 535 536 537 538 539 540 541 542 543 544 545 546
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;
}

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 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
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 已提交
596 597 598
/*
 * Scan the memory blocks for an SMP configuration block.
 */
599
void __init default_get_smp_config(unsigned int early)
L
Linus Torvalds 已提交
600
{
601
	struct mpf_intel *mpf = mpf_found;
L
Linus Torvalds 已提交
602

Y
Yinghai Lu 已提交
603 604 605
	if (!mpf)
		return;

606 607
	if (acpi_lapic && early)
		return;
Y
Yinghai Lu 已提交
608

L
Linus Torvalds 已提交
609
	/*
Y
Yinghai Lu 已提交
610 611
	 * MPS doesn't support hyperthreading, aka only have
	 * thread 0 apic id in MPS table
L
Linus Torvalds 已提交
612
	 */
Y
Yinghai Lu 已提交
613
	if (acpi_lapic && acpi_ioapic)
L
Linus Torvalds 已提交
614 615
		return;

A
Alexey Starikovskiy 已提交
616
	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
617
	       mpf->specification);
618
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32)
619
	if (mpf->feature2 & (1 << 7)) {
L
Linus Torvalds 已提交
620 621 622 623 624 625
		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 已提交
626
#endif
L
Linus Torvalds 已提交
627 628 629
	/*
	 * Now see if we need to read further.
	 */
630
	if (mpf->feature1 != 0) {
631 632 633 634 635 636 637
		if (early) {
			/*
			 * local APIC has default address
			 */
			mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
			return;
		}
L
Linus Torvalds 已提交
638

A
Alexey Starikovskiy 已提交
639
		printk(KERN_INFO "Default MP configuration #%d\n",
640 641
		       mpf->feature1);
		construct_default_ISA_mptable(mpf->feature1);
L
Linus Torvalds 已提交
642

643
	} else if (mpf->physptr) {
644
		if (check_physptr(mpf, early))
L
Linus Torvalds 已提交
645 646 647 648
			return;
	} else
		BUG();

649 650
	if (!early)
		printk(KERN_INFO "Processors: %d\n", num_processors);
L
Linus Torvalds 已提交
651 652 653 654 655
	/*
	 * Only use the first configuration found.
	 */
}

656
static void __init smp_reserve_memory(struct mpf_intel *mpf)
657 658 659
{
	unsigned long size = get_mpc_size(mpf->physptr);

A
Andi Kleen 已提交
660
	reserve_early_overlap_ok(mpf->physptr, mpf->physptr+size, "MP-table mpc");
661 662
}

663
static int __init smp_scan_config(unsigned long base, unsigned long length)
L
Linus Torvalds 已提交
664
{
A
Alexey Starikovskiy 已提交
665
	unsigned int *bp = phys_to_virt(base);
666
	struct mpf_intel *mpf;
667
	unsigned long mem;
L
Linus Torvalds 已提交
668

669 670
	apic_printk(APIC_VERBOSE, "Scan SMP from %p for %ld bytes.\n",
			bp, length);
671
	BUILD_BUG_ON(sizeof(*mpf) != 16);
L
Linus Torvalds 已提交
672 673

	while (length > 0) {
674
		mpf = (struct mpf_intel *)bp;
L
Linus Torvalds 已提交
675
		if ((*bp == SMP_MAGIC_IDENT) &&
676
		    (mpf->length == 1) &&
A
Alexey Starikovskiy 已提交
677
		    !mpf_checksum((unsigned char *)bp, 16) &&
678 679
		    ((mpf->specification == 1)
		     || (mpf->specification == 4))) {
A
Alexey Starikovskiy 已提交
680
#ifdef CONFIG_X86_LOCAL_APIC
L
Linus Torvalds 已提交
681
			smp_found_config = 1;
A
Alexey Starikovskiy 已提交
682
#endif
A
Alexey Starikovskiy 已提交
683
			mpf_found = mpf;
684

685 686
			printk(KERN_INFO "found SMP MP-table at [%p] %llx\n",
			       mpf, (u64)virt_to_phys(mpf));
687

688
			mem = virt_to_phys(mpf);
A
Andi Kleen 已提交
689
			reserve_early_overlap_ok(mem, mem + sizeof(*mpf), "MP-table mpf");
690
			if (mpf->physptr)
691
				smp_reserve_memory(mpf);
L
Linus Torvalds 已提交
692

693
			return 1;
L
Linus Torvalds 已提交
694 695 696 697 698 699 700
		}
		bp += 4;
		length -= 16;
	}
	return 0;
}

701
void __init default_find_smp_config(void)
L
Linus Torvalds 已提交
702 703 704 705 706 707 708 709 710 711 712
{
	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
	 */
713 714 715
	if (smp_scan_config(0x0, 0x400) ||
	    smp_scan_config(639 * 0x400, 0x400) ||
	    smp_scan_config(0xF0000, 0x10000))
L
Linus Torvalds 已提交
716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735
		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)
736
		smp_scan_config(address, 0x400);
737 738
}

Y
Yinghai Lu 已提交
739 740 741
#ifdef CONFIG_X86_IO_APIC
static u8 __initdata irq_used[MAX_IRQ_SOURCES];

742
static int  __init get_MP_intsrc_index(struct mpc_intsrc *m)
Y
Yinghai Lu 已提交
743 744 745
{
	int i;

746
	if (m->irqtype != mp_INT)
Y
Yinghai Lu 已提交
747 748
		return 0;

749
	if (m->irqflag != 0x0f)
Y
Yinghai Lu 已提交
750 751 752 753 754
		return 0;

	/* not legacy */

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

758
		if (mp_irqs[i].irqflag != 0x0f)
Y
Yinghai Lu 已提交
759 760
			continue;

761
		if (mp_irqs[i].srcbus != m->srcbus)
Y
Yinghai Lu 已提交
762
			continue;
763
		if (mp_irqs[i].srcbusirq != m->srcbusirq)
Y
Yinghai Lu 已提交
764 765 766 767 768 769 770 771 772 773 774 775 776 777 778
			continue;
		if (irq_used[i]) {
			/* already claimed */
			return -2;
		}
		irq_used[i] = 1;
		return i;
	}

	/* not found */
	return -1;
}

#define SPARE_SLOT_NUM 20

779
static struct mpc_intsrc __initdata *m_spare[SPARE_SLOT_NUM];
780

781
static void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare)
782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808
{
	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 */
809 810
static
inline void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {}
811 812
#endif /* CONFIG_X86_IO_APIC */

Y
Yinghai Lu 已提交
813 814
static int
check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length, int count)
815
{
Y
Yinghai Lu 已提交
816 817 818 819 820
	int ret = 0;

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

Y
Yinghai Lu 已提交
823
	return ret;
824
}
Y
Yinghai Lu 已提交
825

826
static int  __init replace_intsrc_all(struct mpc_table *mpc,
Y
Yinghai Lu 已提交
827 828 829 830 831 832 833
					unsigned long mpc_new_phys,
					unsigned long mpc_new_length)
{
#ifdef CONFIG_X86_IO_APIC
	int i;
#endif
	int count = sizeof(*mpc);
834
	int nr_m_spare = 0;
Y
Yinghai Lu 已提交
835 836
	unsigned char *mpt = ((unsigned char *)mpc) + count;

837 838
	printk(KERN_INFO "mpc_length %x\n", mpc->length);
	while (count < mpc->length) {
Y
Yinghai Lu 已提交
839 840
		switch (*mpt) {
		case MP_PROCESSOR:
841 842
			skip_entry(&mpt, &count, sizeof(struct mpc_cpu));
			break;
Y
Yinghai Lu 已提交
843
		case MP_BUS:
844 845
			skip_entry(&mpt, &count, sizeof(struct mpc_bus));
			break;
Y
Yinghai Lu 已提交
846
		case MP_IOAPIC:
847 848
			skip_entry(&mpt, &count, sizeof(struct mpc_ioapic));
			break;
Y
Yinghai Lu 已提交
849
		case MP_INTSRC:
850
			check_irq_src((struct mpc_intsrc *)mpt, &nr_m_spare);
851 852
			skip_entry(&mpt, &count, sizeof(struct mpc_intsrc));
			break;
Y
Yinghai Lu 已提交
853
		case MP_LINTSRC:
854 855
			skip_entry(&mpt, &count, sizeof(struct mpc_lintsrc));
			break;
Y
Yinghai Lu 已提交
856 857
		default:
			/* wrong mptable */
858
			smp_dump_mptable(mpc, mpt);
Y
Yinghai Lu 已提交
859 860 861 862 863 864 865 866 867
			goto out;
		}
	}

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

868
		if (mp_irqs[i].irqtype != mp_INT)
Y
Yinghai Lu 已提交
869 870
			continue;

871
		if (mp_irqs[i].irqflag != 0x0f)
Y
Yinghai Lu 已提交
872 873 874
			continue;

		if (nr_m_spare > 0) {
875
			apic_printk(APIC_VERBOSE, "*NEW* found\n");
Y
Yinghai Lu 已提交
876 877 878 879
			nr_m_spare--;
			assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]);
			m_spare[nr_m_spare] = NULL;
		} else {
880 881
			struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
			count += sizeof(struct mpc_intsrc);
Y
Yinghai Lu 已提交
882
			if (check_slot(mpc_new_phys, mpc_new_length, count) < 0)
883
				goto out;
Y
Yinghai Lu 已提交
884
			assign_to_mpc_intsrc(&mp_irqs[i], m);
885
			mpc->length = count;
886
			mpt += sizeof(struct mpc_intsrc);
Y
Yinghai Lu 已提交
887 888 889 890 891 892
		}
		print_mp_irq_info(&mp_irqs[i]);
	}
#endif
out:
	/* update checksum */
893 894
	mpc->checksum = 0;
	mpc->checksum -= mpf_checksum((unsigned char *)mpc, mpc->length);
Y
Yinghai Lu 已提交
895 896 897 898

	return 0;
}

899
int enable_update_mptable;
900

Y
Yinghai Lu 已提交
901 902 903
static int __init update_mptable_setup(char *str)
{
	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
	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;
919 920 921
#ifdef CONFIG_PCI
	pci_routeirq = 1;
#endif
Y
Yinghai Lu 已提交
922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941
	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];
942
	struct mpf_intel *mpf;
943
	struct mpc_table *mpc, *mpc_new;
Y
Yinghai Lu 已提交
944 945 946 947 948 949 950 951 952 953 954

	if (!enable_update_mptable)
		return 0;

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

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

958
	if (!mpf->physptr)
Y
Yinghai Lu 已提交
959 960
		return 0;

961
	mpc = phys_to_virt(mpf->physptr);
Y
Yinghai Lu 已提交
962 963 964 965

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

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

969
	if (mpc_new_phys && mpc->length > mpc_new_length) {
Y
Yinghai Lu 已提交
970 971 972 973 974 975 976 977
		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 */
978 979 980 981
		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 已提交
982 983 984 985 986 987
		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 {
988
		mpf->physptr = mpc_new_phys;
Y
Yinghai Lu 已提交
989
		mpc_new = phys_to_virt(mpc_new_phys);
990
		memcpy(mpc_new, mpc, mpc->length);
Y
Yinghai Lu 已提交
991 992
		mpc = mpc_new;
		/* check if we can modify that */
993
		if (mpc_new_phys - mpf->physptr) {
994
			struct mpf_intel *mpf_new;
Y
Yinghai Lu 已提交
995 996 997 998 999
			/* 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;
1000
			mpf->physptr = mpc_new_phys;
Y
Yinghai Lu 已提交
1001
		}
1002 1003 1004
		mpf->checksum = 0;
		mpf->checksum -= mpf_checksum((unsigned char *)mpf, 16);
		printk(KERN_INFO "physptr new: %x\n", mpf->physptr);
Y
Yinghai Lu 已提交
1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018
	}

	/*
	 * 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);