📄 mpparse.c
字号:
/* * 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_pci_bus [MAX_MP_BUSSES] = { -1, };int mp_current_pci_id;int pic_mode;unsigned long mp_lapic_addr;/* Processor that is doing the boot up */unsigned int boot_cpu_id = -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;}static void __init MP_processor_info (struct mpc_config_processor *m){ int ver; if (!(m->mpc_cpuflag & CPU_ENABLED)) return; 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"); /* 28 Reserved */ 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_id = m->mpc_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; 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; 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"); } 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();}/* * 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 1; } if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) { panic("SMP mptable: checksum error!\n"); return 1; } if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) { printk("Bad Config Table version (%d)!!\n",mpc->mpc_spec); return 1; } 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 */ mp_lapic_addr = mpc->mpc_lapic; /* * Now process the configuration blocks. */ while (count < mpc->mpc_length) { switch(*mpt) { case MP_PROCESSOR: { struct mpc_config_processor *m= (struct mpc_config_processor *)mpt; MP_processor_info(m); mpt += sizeof(*m); count += sizeof(*m); break; } case MP_BUS:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -