⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpparse.c

📁 MIZI Research, Inc.发布的嵌入式Linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *	Intel Multiprocessor Specificiation 1.1 and 1.4 *	compliant MP-table parsing routines. * *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com> *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com> * *	Fixes *		Erich Boleyn	:	MP v1.4 and additional changes. *		Alan Cox	:	Added EBDA scanning *		Ingo Molnar	:	various cleanups and rewrites *	Maciej W. Rozycki	:	Bits for default MP configurations */#include <linux/mm.h>#include <linux/irq.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/config.h>#include <linux/bootmem.h>#include <linux/smp_lock.h>#include <linux/kernel_stat.h>#include <linux/mc146818rtc.h>#include <asm/smp.h>#include <asm/mtrr.h>#include <asm/mpspec.h>#include <asm/pgalloc.h>/* Have we found an MP table */int smp_found_config;/* * Various Linux-internal data structures created from the * MP-table. */int apic_version [MAX_APICS];int mp_bus_id_to_type [MAX_MP_BUSSES];int mp_bus_id_to_node [MAX_MP_BUSSES];int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };int mp_current_pci_id;/* I/O APIC entries */struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];/* # of MP IRQ source entries */struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];/* MP IRQ source entries */int mp_irq_entries;int nr_ioapics;int pic_mode;unsigned long mp_lapic_addr;/* Processor that is doing the boot up */unsigned int boot_cpu_physical_apicid = -1U;unsigned int boot_cpu_logical_apicid = -1U;/* Internal processor count */static unsigned int num_processors;/* Bitmask of physically existing CPUs */unsigned long phys_cpu_present_map;/* * Intel MP BIOS table parsing routines: */#ifndef CONFIG_X86_VISWS_APIC/* * 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;}/* * Processor encoding in an MP configuration block */static char __init *mpc_family(int family,int model){	static char n[32];	static char *model_defs[]=	{		"80486DX","80486DX",		"80486SX","80486DX/2 or 80487",		"80486SL","80486SX/2",		"Unknown","80486DX/2-WB",		"80486DX/4","80486DX/4-WB"	};	switch (family) {		case 0x04:			if (model < 10)				return model_defs[model];			break;		case 0x05:			return("Pentium(tm)");		case 0x06:			return("Pentium(tm) Pro");		case 0x0F:			if (model == 0x00)				return("Pentium 4(tm)");			if (model == 0x0F)				return("Special controller");	}	sprintf(n,"Unknown CPU [%d:%d]",family, model);	return n;}#ifdef CONFIG_X86_IO_APICextern int have_acpi_tables;	/* set by acpitable.c */#else#define have_acpi_tables (0)#endif/*  * 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 .... */static int mpc_record; static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;void __init MP_processor_info (struct mpc_config_processor *m){ 	int ver, quad, logical_apicid; 		if (!(m->mpc_cpuflag & CPU_ENABLED))		return;	logical_apicid = m->mpc_apicid;	if (clustered_apic_mode) {		quad = translation_table[mpc_record]->trans_quad;		logical_apicid = (quad << 4) + 			(m->mpc_apicid ? m->mpc_apicid << 1 : 1);		printk("Processor #%d %s APIC version %d (quad %d, apic %d)\n",			m->mpc_apicid,			mpc_family((m->mpc_cpufeature & CPU_FAMILY_MASK)>>8 ,				   (m->mpc_cpufeature & CPU_MODEL_MASK)>>4),			m->mpc_apicver, quad, logical_apicid);	} else {		printk("Processor #%d %s APIC version %d\n",			m->mpc_apicid,			mpc_family((m->mpc_cpufeature & CPU_FAMILY_MASK)>>8 ,				   (m->mpc_cpufeature & CPU_MODEL_MASK)>>4),			m->mpc_apicver);	}	if (m->mpc_featureflag&(1<<0))		Dprintk("    Floating point unit present.\n");	if (m->mpc_featureflag&(1<<7))		Dprintk("    Machine Exception supported.\n");	if (m->mpc_featureflag&(1<<8))		Dprintk("    64 bit compare & exchange supported.\n");	if (m->mpc_featureflag&(1<<9))		Dprintk("    Internal APIC present.\n");	if (m->mpc_featureflag&(1<<11))		Dprintk("    SEP present.\n");	if (m->mpc_featureflag&(1<<12))		Dprintk("    MTRR  present.\n");	if (m->mpc_featureflag&(1<<13))		Dprintk("    PGE  present.\n");	if (m->mpc_featureflag&(1<<14))		Dprintk("    MCA  present.\n");	if (m->mpc_featureflag&(1<<15))		Dprintk("    CMOV  present.\n");	if (m->mpc_featureflag&(1<<16))		Dprintk("    PAT  present.\n");	if (m->mpc_featureflag&(1<<17))		Dprintk("    PSE  present.\n");	if (m->mpc_featureflag&(1<<18))		Dprintk("    PSN  present.\n");	if (m->mpc_featureflag&(1<<19))		Dprintk("    Cache Line Flush Instruction present.\n");	/* 20 Reserved */	if (m->mpc_featureflag&(1<<21))		Dprintk("    Debug Trace and EMON Store present.\n");	if (m->mpc_featureflag&(1<<22))		Dprintk("    ACPI Thermal Throttle Registers  present.\n");	if (m->mpc_featureflag&(1<<23))		Dprintk("    MMX  present.\n");	if (m->mpc_featureflag&(1<<24))		Dprintk("    FXSR  present.\n");	if (m->mpc_featureflag&(1<<25))		Dprintk("    XMM  present.\n");	if (m->mpc_featureflag&(1<<26))		Dprintk("    Willamette New Instructions  present.\n");	if (m->mpc_featureflag&(1<<27))		Dprintk("    Self Snoop  present.\n");	if (m->mpc_featureflag&(1<<28))		Dprintk("    HT  present.\n");	if (m->mpc_featureflag&(1<<29))		Dprintk("    Thermal Monitor present.\n");	/* 30, 31 Reserved */	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {		Dprintk("    Bootup CPU\n");		boot_cpu_physical_apicid = m->mpc_apicid;		boot_cpu_logical_apicid = logical_apicid;	}	num_processors++;	if (m->mpc_apicid > MAX_APICS) {		printk("Processor #%d INVALID. (Max ID: %d).\n",			m->mpc_apicid, MAX_APICS);		return;	}	ver = m->mpc_apicver;	if (clustered_apic_mode) {		phys_cpu_present_map |= (logical_apicid&0xf) << (4*quad);	} else {		phys_cpu_present_map |= 1 << m->mpc_apicid;	}	/*	 * Validate version	 */	if (ver == 0x0) {		printk("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);		ver = 0x10;	}	apic_version[m->mpc_apicid] = ver;}static void __init MP_bus_info (struct mpc_config_bus *m){	char str[7];	memcpy(str, m->mpc_bustype, 6);	str[6] = 0;		if (clustered_apic_mode) {		mp_bus_id_to_node[m->mpc_busid] = translation_table[mpc_record]->trans_quad;		printk("Bus #%d is %s (node %d)\n", m->mpc_busid, str, mp_bus_id_to_node[m->mpc_busid]);	} else {		Dprintk("Bus #%d is %s\n", m->mpc_busid, str);	}	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;	} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) {		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;	} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) {		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;		mp_current_pci_id++;	} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) {		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;	} else {		printk("Unknown bustype %s - ignoring\n", str);	}}static void __init MP_ioapic_info (struct mpc_config_ioapic *m){	if (!(m->mpc_flags & MPC_APIC_USABLE))		return;	printk("I/O APIC #%d Version %d at 0x%lX.\n",		m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);	if (nr_ioapics >= MAX_IO_APICS) {		printk("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 (!m->mpc_apicaddr) {		printk(KERN_ERR "WARNING: bogus zero I/O APIC address"			" found in MP table, skipping!\n");		return;	}	mp_ioapics[nr_ioapics] = *m;	nr_ioapics++;}static void __init MP_intsrc_info (struct mpc_config_intsrc *m){	mp_irqs [mp_irq_entries] = *m;	Dprintk("Int: type %d, pol %d, trig %d, bus %d,"		" IRQ %02x, APIC ID %x, APIC INT %02x\n",			m->mpc_irqtype, m->mpc_irqflag & 3,			(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,			m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);	if (++mp_irq_entries == MAX_IRQ_SOURCES)		panic("Max # of irq sources exceeded!!\n");}static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m){	Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",			m->mpc_irqtype, m->mpc_irqflag & 3,			(m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,			m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);	/*	 * Well it seems all SMP boards in existence	 * use ExtINT/LVT1 == LINT0 and	 * NMI/LVT2 == LINT1 - the following check	 * will show us if this assumptions is false.	 * Until then we do not have to add baggage.	 */	if ((m->mpc_irqtype == mp_ExtINT) &&		(m->mpc_destapiclint != 0))			BUG();	if ((m->mpc_irqtype == mp_NMI) &&		(m->mpc_destapiclint != 1))			BUG();}static void __init MP_translation_info (struct mpc_config_translation *m){	printk("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);	if (mpc_record >= MAX_MPC_ENTRY) 		printk("MAX_MPC_ENTRY exceeded!\n");	else		translation_table[mpc_record] = m; /* stash this for later */}/* * Read/parse the MPC oem tables */static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \	unsigned short oemsize){	int count = sizeof (*oemtable); /* the header size */	unsigned char *oemptr = ((unsigned char *)oemtable)+count;		printk("Found an OEM MPC table at %8p - parsing it ... \n", oemtable);	if (memcmp(oemtable->oem_signature,MPC_OEM_SIGNATURE,4))	{		printk("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]);		return;	}	if (mpf_checksum((unsigned char *)oemtable,oemtable->oem_length))	{		printk("SMP oem mptable: checksum error!\n");		return;	}	while (count < oemtable->oem_length) {		switch (*oemptr) {			case MP_TRANSLATION:			{				struct mpc_config_translation *m=					(struct mpc_config_translation *)oemptr;				MP_translation_info(m);				oemptr += sizeof(*m);				count += sizeof(*m);				++mpc_record;				break;			}			default:			{				printk("Unrecognised OEM table entry type! - %d\n", (int) *oemptr);				return;			}		}       }}/* * Read/parse the MPC */static int __init smp_read_mpc(struct mp_config_table *mpc){	char str[16];	int count=sizeof(*mpc);	unsigned char *mpt=((unsigned char *)mpc)+count;	if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {		panic("SMP mptable: bad signature [%c%c%c%c]!\n",			mpc->mpc_signature[0],			mpc->mpc_signature[1],			mpc->mpc_signature[2],			mpc->mpc_signature[3]);		return 0;	}	if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {		panic("SMP mptable: checksum error!\n");		return 0;	}	if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {		printk(KERN_ERR "SMP mptable: bad table version (%d)!!\n",			mpc->mpc_spec);		return 0;	}	if (!mpc->mpc_lapic) {		printk(KERN_ERR "SMP mptable: null local APIC address!\n");		return 0;	}	memcpy(str,mpc->mpc_oem,8);	str[8]=0;	printk("OEM ID: %s ",str);	memcpy(str,mpc->mpc_productid,12);	str[12]=0;	printk("Product ID: %s ",str);	printk("APIC at: 0x%lX\n",mpc->mpc_lapic);	/* save the local APIC address, it might be non-default,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -