943 lines · 21.9 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* *	Intel Multiprocessor Specification 1.1 and 1.4 *	compliant MP-table parsing routines. * *	(c) 1995 Alan Cox, Building #3 <alan@lxorguk.ukuu.org.uk> *	(c) 1998, 1999, 2000, 2009 Ingo Molnar <mingo@redhat.com> *      (c) 2008 Alexey Starikovskiy <astarikovskiy@suse.de> */ #include <linux/mm.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/memblock.h>#include <linux/kernel_stat.h>#include <linux/mc146818rtc.h>#include <linux/bitops.h>#include <linux/acpi.h>#include <linux/smp.h>#include <linux/pci.h> #include <asm/i8259.h>#include <asm/io_apic.h>#include <asm/acpi.h>#include <asm/irqdomain.h>#include <asm/mtrr.h>#include <asm/mpspec.h>#include <asm/proto.h>#include <asm/bios_ebda.h>#include <asm/e820/api.h>#include <asm/setup.h>#include <asm/smp.h> #include <asm/apic.h>/* * Checksum an MP configuration block. */ static unsigned int num_procs __initdata; static int __init mpf_checksum(unsigned char *mp, int len){	int sum = 0; 	while (len--)		sum += *mp++; 	return sum & 0xFF;} static void __init MP_processor_info(struct mpc_cpu *m){	char *bootup_cpu = ""; 	topology_register_apic(m->apicid, CPU_ACPIID_INVALID, m->cpuflag & CPU_ENABLED);	if (!(m->cpuflag & CPU_ENABLED))		return; 	if (m->cpuflag & CPU_BOOTPROCESSOR)		bootup_cpu = " (Bootup-CPU)"; 	pr_info("Processor #%d%s\n", m->apicid, bootup_cpu);	num_procs++;} #ifdef CONFIG_X86_IO_APICstatic void __init mpc_oem_bus_info(struct mpc_bus *m, char *str){	memcpy(str, m->bustype, 6);	str[6] = 0;	apic_pr_verbose("Bus #%d is %s\n", m->busid, str);} static void __init MP_bus_info(struct mpc_bus *m){	char str[7]; 	mpc_oem_bus_info(m, str); #if MAX_MP_BUSSES < 256	if (m->busid >= MAX_MP_BUSSES) {		pr_warn("MP table busid value (%d) for bustype %s is too large, max. supported is %d\n",			m->busid, str, MAX_MP_BUSSES - 1);		return;	}#endif 	set_bit(m->busid, mp_bus_not_pci);	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) {#ifdef CONFIG_EISA		mp_bus_id_to_type[m->busid] = MP_BUS_ISA;#endif	} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) {		clear_bit(m->busid, mp_bus_not_pci);#ifdef CONFIG_EISA		mp_bus_id_to_type[m->busid] = MP_BUS_PCI;	} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA) - 1) == 0) {		mp_bus_id_to_type[m->busid] = MP_BUS_EISA;#endif	} else		pr_warn("Unknown bustype %s - ignoring\n", str);} static void __init MP_ioapic_info(struct mpc_ioapic *m){	struct ioapic_domain_cfg cfg = {		.type = IOAPIC_DOMAIN_LEGACY,		.ops = &mp_ioapic_irqdomain_ops,	}; 	if (m->flags & MPC_APIC_USABLE)		mp_register_ioapic(m->apicid, m->apicaddr, gsi_top, &cfg);} static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq){	apic_printk(APIC_VERBOSE,		"Int: type %d, pol %d, trig %d, bus %02x, IRQ %02x, APIC ID %x, APIC INT %02x\n",		mp_irq->irqtype, mp_irq->irqflag & 3,		(mp_irq->irqflag >> 2) & 3, mp_irq->srcbus,		mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq);} #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) {}#endif /* CONFIG_X86_IO_APIC */ static void __init MP_lintsrc_info(struct mpc_lintsrc *m){	apic_printk(APIC_VERBOSE,		"Lint: type %d, pol %d, trig %d, bus %02x, IRQ %02x, APIC ID %x, APIC LINT %02x\n",		m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbusid,		m->srcbusirq, m->destapic, m->destapiclint);} /* * Read/parse the MPC */static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str){ 	if (memcmp(mpc->signature, MPC_SIGNATURE, 4)) {		pr_err("MPTABLE: bad signature [%c%c%c%c]!\n",		       mpc->signature[0], mpc->signature[1],		       mpc->signature[2], mpc->signature[3]);		return 0;	}	if (mpf_checksum((unsigned char *)mpc, mpc->length)) {		pr_err("MPTABLE: checksum error!\n");		return 0;	}	if (mpc->spec != 0x01 && mpc->spec != 0x04) {		pr_err("MPTABLE: bad table version (%d)!!\n", mpc->spec);		return 0;	}	if (!mpc->lapic) {		pr_err("MPTABLE: null local APIC address!\n");		return 0;	}	memcpy(oem, mpc->oem, 8);	oem[8] = 0;	pr_info("MPTABLE: OEM ID: %s\n", oem); 	memcpy(str, mpc->productid, 12);	str[12] = 0; 	pr_info("MPTABLE: Product ID: %s\n", str); 	pr_info("MPTABLE: APIC at: 0x%X\n", mpc->lapic); 	return 1;} static void skip_entry(unsigned char **ptr, int *count, int size){	*ptr += size;	*count += size;} static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt){	pr_err("Your mptable is wrong, contact your HW vendor!\n");	pr_cont("type %x\n", *mpt);	print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,			1, mpc, mpc->length, 1);} static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early){	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; 	if (early) {		/* Initialize the lapic mapping */		if (!acpi_lapic)			register_lapic_address(mpc->lapic);		return 1;	} 	/* Now process the configuration blocks. */	while (count < mpc->length) {		switch (*mpt) {		case MP_PROCESSOR:			/* ACPI may have already provided this data */			if (!acpi_lapic)				MP_processor_info((struct mpc_cpu *)mpt);			skip_entry(&mpt, &count, sizeof(struct mpc_cpu));			break;		case MP_BUS:			MP_bus_info((struct mpc_bus *)mpt);			skip_entry(&mpt, &count, sizeof(struct mpc_bus));			break;		case MP_IOAPIC:			MP_ioapic_info((struct mpc_ioapic *)mpt);			skip_entry(&mpt, &count, sizeof(struct mpc_ioapic));			break;		case MP_INTSRC:			mp_save_irq((struct mpc_intsrc *)mpt);			skip_entry(&mpt, &count, sizeof(struct mpc_intsrc));			break;		case MP_LINTSRC:			MP_lintsrc_info((struct mpc_lintsrc *)mpt);			skip_entry(&mpt, &count, sizeof(struct mpc_lintsrc));			break;		default:			/* wrong mptable */			smp_dump_mptable(mpc, mpt);			count = mpc->length;			break;		}	} 	if (!num_procs && !acpi_lapic)		pr_err("MPTABLE: no processors registered!\n");	return num_procs || acpi_lapic;} #ifdef CONFIG_X86_IO_APIC static int __init ELCR_trigger(unsigned int irq){	unsigned int port; 	port = PIC_ELCR1 + (irq >> 3);	return (inb(port) >> (irq & 7)) & 1;} static void __init construct_default_ioirq_mptable(int mpc_default_type){	struct mpc_intsrc intsrc;	int i;	int ELCR_fallback = 0; 	intsrc.type = MP_INTSRC;	intsrc.irqflag = MP_IRQTRIG_DEFAULT | MP_IRQPOL_DEFAULT;	intsrc.srcbus = 0;	intsrc.dstapic = mpc_ioapic_id(0); 	intsrc.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) {		pr_info("ISA/PCI bus type with no IRQ information... falling back to ELCR\n"); 		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) ||		    ELCR_trigger(13))			pr_err("ELCR contains invalid data... not using ELCR\n");		else {			pr_info("Using ELCR to identify PCI interrupts\n");			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 */			fallthrough;		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.irqflag = MP_IRQTRIG_LEVEL |						 MP_IRQPOL_ACTIVE_HIGH;			} else {				intsrc.irqflag = MP_IRQTRIG_DEFAULT |						 MP_IRQPOL_DEFAULT;			}		} 		intsrc.srcbusirq = i;		intsrc.dstirq = i ? i : 2;	/* IRQ0 to INTIN2 */		mp_save_irq(&intsrc);	} 	intsrc.irqtype = mp_ExtINT;	intsrc.srcbusirq = 0;	intsrc.dstirq = 0;	/* 8259A to INTIN0 */	mp_save_irq(&intsrc);}  static void __init construct_ioapic_table(int mpc_default_type){	struct mpc_ioapic ioapic;	struct mpc_bus bus; 	bus.type = MP_BUS;	bus.busid = 0;	switch (mpc_default_type) {	default:		pr_err("???\nUnknown standard configuration %d\n",		       mpc_default_type);		fallthrough;	case 1:	case 5:		memcpy(bus.bustype, "ISA   ", 6);		break;	case 2:	case 6:	case 3:		memcpy(bus.bustype, "EISA  ", 6);		break;	}	MP_bus_info(&bus);	if (mpc_default_type > 4) {		bus.busid = 1;		memcpy(bus.bustype, "PCI   ", 6);		MP_bus_info(&bus);	} 	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;	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);}#elsestatic inline void __init construct_ioapic_table(int mpc_default_type) { }#endif static inline void __init construct_default_ISA_mptable(int mpc_default_type){	struct mpc_cpu processor;	struct mpc_lintsrc lintsrc;	int linttypes[2] = { mp_ExtINT, mp_NMI };	int i; 	/*	 * 2 CPUs, numbered 0 & 1.	 */	processor.type = MP_PROCESSOR;	/* Either an integrated APIC or a discrete 82489DX. */	processor.apicver = mpc_default_type > 4 ? 0x10 : 0x01;	processor.cpuflag = CPU_ENABLED;	processor.cpufeature = (boot_cpu_data.x86 << 8) |	    (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_stepping;	processor.featureflag = boot_cpu_data.x86_capability[CPUID_1_EDX];	processor.reserved[0] = 0;	processor.reserved[1] = 0;	for (i = 0; i < 2; i++) {		processor.apicid = i;		MP_processor_info(&processor);	} 	construct_ioapic_table(mpc_default_type); 	lintsrc.type = MP_LINTSRC;	lintsrc.irqflag = MP_IRQTRIG_DEFAULT | MP_IRQPOL_DEFAULT;	lintsrc.srcbusid = 0;	lintsrc.srcbusirq = 0;	lintsrc.destapic = MP_APIC_ALL;	for (i = 0; i < 2; i++) {		lintsrc.irqtype = linttypes[i];		lintsrc.destapiclint = i;		MP_lintsrc_info(&lintsrc);	}} static unsigned long mpf_base;static bool mpf_found; static unsigned long __init get_mpc_size(unsigned long physptr){	struct mpc_table *mpc;	unsigned long size; 	mpc = early_memremap(physptr, PAGE_SIZE);	size = mpc->length;	early_memunmap(mpc, PAGE_SIZE);	apic_pr_verbose("  mpc: %lx-%lx\n", physptr, physptr + size); 	return size;} 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_memremap(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		pr_err("BIOS bug, MP table errors detected!...\n");		pr_cont("... disabling SMP support. (tell your hw vendor)\n");		early_memunmap(mpc, size);		return -1;	}	early_memunmap(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; 		pr_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;} /* * Scan the memory blocks for an SMP configuration block. */static __init void mpparse_get_smp_config(unsigned int early){	struct mpf_intel *mpf; 	if (!smp_found_config)		return; 	if (!mpf_found)		return; 	if (acpi_lapic && early)		return; 	/*	 * MPS doesn't support hyperthreading, aka only have	 * thread 0 apic id in MPS table	 */	if (acpi_lapic && acpi_ioapic)		return; 	mpf = early_memremap(mpf_base, sizeof(*mpf));	if (!mpf) {		pr_err("MPTABLE: error mapping MP table\n");		return;

Lines 1–500 of 943.