📄 mpparse.c
字号:
case MP_BUS: ++num_bus; mpt += sizeof(struct mpc_config_bus); count += sizeof(struct mpc_config_bus); break; case MP_INTSRC: ++num_irq; mpt += sizeof(struct mpc_config_intsrc); count += sizeof(struct mpc_config_intsrc); break; case MP_IOAPIC: mpt += sizeof(struct mpc_config_ioapic); count += sizeof(struct mpc_config_ioapic); break; case MP_LINTSRC: mpt += sizeof(struct mpc_config_lintsrc); count += sizeof(struct mpc_config_lintsrc); break; default: count = mpc->mpc_length; break; } } /* * Paranoia: Allocate one extra of both the number of busses and number * of irqs, and make sure that we have at least 4 interrupts per PCI * slot. But some machines do not report very many busses, so we need * to fall back on the older defaults. */ ++num_bus; max_mp_busses = max(num_bus, MAX_MP_BUSSES); if (num_irq < (4 * max_mp_busses)) num_irq = 4 * num_bus; /* 4 intr/PCI slot */ ++num_irq; max_irq_sources = max(num_irq, MAX_IRQ_SOURCES); count = (max_mp_busses * sizeof(int)) * 4; count += (max_irq_sources * sizeof(struct mpc_config_intsrc)); bus_data = alloc_bootmem(count); if (!bus_data) { printk(KERN_ERR "SMP mptable: out of memory!\n"); return 0; } mp_bus_id_to_type = (int *)&bus_data[0]; mp_bus_id_to_node = (int *)&bus_data[(max_mp_busses * sizeof(int))]; mp_bus_id_to_local = (int *)&bus_data[(max_mp_busses * sizeof(int)) * 2]; mp_bus_id_to_pci_bus = (int *)&bus_data[(max_mp_busses * sizeof(int)) * 3]; mp_irqs = (struct mpc_config_intsrc *)&bus_data[(max_mp_busses * sizeof(int)) * 4]; memset(mp_bus_id_to_pci_bus, -1, max_mp_busses); /* * Now process the configuration blocks. */ count = sizeof(*mpc); mpt = ((unsigned char *)mpc)+count; while (count < mpc->mpc_length) { switch(*mpt) { case MP_PROCESSOR: { struct mpc_config_processor *m= (struct mpc_config_processor *)mpt; /* ACPI may already have provided this one for us */ if (!have_acpi_tables) MP_processor_info(m); mpt += sizeof(*m); count += sizeof(*m); break; } case MP_BUS: { struct mpc_config_bus *m= (struct mpc_config_bus *)mpt; MP_bus_info(m); mpt += sizeof(*m); count += sizeof(*m); break; } case MP_IOAPIC: { struct mpc_config_ioapic *m= (struct mpc_config_ioapic *)mpt; MP_ioapic_info(m); mpt+=sizeof(*m); count+=sizeof(*m); break; } case MP_INTSRC: { struct mpc_config_intsrc *m= (struct mpc_config_intsrc *)mpt; MP_intsrc_info(m); mpt+=sizeof(*m); count+=sizeof(*m); break; } case MP_LINTSRC: { struct mpc_config_lintsrc *m= (struct mpc_config_lintsrc *)mpt; MP_lintsrc_info(m); mpt+=sizeof(*m); count+=sizeof(*m); break; } default: { count = mpc->mpc_length; break; } } ++mpc_record; } if (clustered_apic_mode){ phys_cpu_present_map = logical_cpu_present_map; } printk("Enabling APIC mode: "); if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ) printk("Clustered Logical. "); else if(clustered_apic_mode == CLUSTERED_APIC_XAPIC) printk("Physical. "); else printk("Flat. "); printk("Using %d I/O APICs\n",nr_ioapics); if (!num_processors) printk(KERN_ERR "SMP mptable: no processors registered!\n"); return num_processors;}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){ struct mpc_config_intsrc intsrc; int i; int ELCR_fallback = 0; intsrc.mpc_type = MP_INTSRC; intsrc.mpc_irqflag = 0; /* conforming */ intsrc.mpc_srcbus = 0; intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid; intsrc.mpc_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) { printk("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)) printk("ELCR contains invalid data... not using ELCR\n"); else { printk("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 */ /* 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)) intsrc.mpc_irqflag = 13; else intsrc.mpc_irqflag = 0; } intsrc.mpc_srcbusirq = i; intsrc.mpc_dstirq = i ? i : 2; /* IRQ0 to INTIN2 */ MP_intsrc_info(&intsrc); } intsrc.mpc_irqtype = mp_ExtINT; intsrc.mpc_srcbusirq = 0; intsrc.mpc_dstirq = 0; /* 8259A to INTIN0 */ MP_intsrc_info(&intsrc);}static inline void __init construct_default_ISA_mptable(int mpc_default_type){ struct mpc_config_processor processor; struct mpc_config_bus bus; struct mpc_config_ioapic ioapic; struct mpc_config_lintsrc lintsrc; 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. */ processor.mpc_type = MP_PROCESSOR; /* Either an integrated APIC or a discrete 82489DX. */ processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01; processor.mpc_cpuflag = CPU_ENABLED; processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask; processor.mpc_featureflag = boot_cpu_data.x86_capability[0]; processor.mpc_reserved[0] = 0; processor.mpc_reserved[1] = 0; for (i = 0; i < 2; i++) { processor.mpc_apicid = i; MP_processor_info(&processor); } bus.mpc_type = MP_BUS; bus.mpc_busid = 0; switch (mpc_default_type) { default: printk("???\nUnknown standard configuration %d\n", mpc_default_type); /* fall through */ case 1: case 5: memcpy(bus.mpc_bustype, "ISA ", 6); break; case 2: case 6: case 3: memcpy(bus.mpc_bustype, "EISA ", 6); break; case 4: case 7: memcpy(bus.mpc_bustype, "MCA ", 6); } MP_bus_info(&bus); if (mpc_default_type > 4) { bus.mpc_busid = 1; memcpy(bus.mpc_bustype, "PCI ", 6); MP_bus_info(&bus); } ioapic.mpc_type = MP_IOAPIC; ioapic.mpc_apicid = 2; ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01; ioapic.mpc_flags = MPC_APIC_USABLE; ioapic.mpc_apicaddr = 0xFEC00000; 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); lintsrc.mpc_type = MP_LINTSRC; lintsrc.mpc_irqflag = 0; /* conforming */ lintsrc.mpc_srcbusid = 0; lintsrc.mpc_srcbusirq = 0; lintsrc.mpc_destapic = MP_APIC_ALL; for (i = 0; i < 2; i++) { lintsrc.mpc_irqtype = linttypes[i]; lintsrc.mpc_destapiclint = i; MP_lintsrc_info(&lintsrc); }}static struct intel_mp_floating *mpf_found;extern void config_acpi_tables(void);/* * Scan the memory blocks for an SMP configuration block. */void __init get_smp_config (void){ struct intel_mp_floating *mpf = mpf_found;#ifdef CONFIG_X86_IO_APIC /* * Check if the ACPI tables are provided. Use them only to get * the processor information, mainly because it provides * the info on the logical processor(s), rather than the physical * processor(s) that are provided by the MPS. We attempt to * check only if the user provided a commandline override */ config_acpi_tables();#endif printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification); if (mpf->mpf_feature2 & (1<<7)) { printk(" IMCR and PIC compatibility mode.\n"); pic_mode = 1; } else { printk(" Virtual Wire compatibility mode.\n"); pic_mode = 0; } /* * Now see if we need to read further. */ if (mpf->mpf_feature1 != 0) { printk("Default MP configuration #%d\n", mpf->mpf_feature1); construct_default_ISA_mptable(mpf->mpf_feature1); } else if (mpf->mpf_physptr) { /* * Read the physical hardware table. Anything here will * override the defaults. */ if (!smp_read_mpc((void *)mpf->mpf_physptr)) { smp_found_config = 0; printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"); printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n"); return; } /* * 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_config_bus bus; printk("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n"); bus.mpc_type = MP_BUS; bus.mpc_busid = 0; memcpy(bus.mpc_bustype, "ISA ", 6); MP_bus_info(&bus); construct_default_ioirq_mptable(0); } } else BUG(); printk("Processors: %d\n", num_processors); /* * Only use the first configuration found. */}static int __init smp_scan_config (unsigned long base, unsigned long length){ unsigned long *bp = phys_to_virt(base); struct intel_mp_floating *mpf; Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length); if (sizeof(*mpf) != 16) printk("Error: MPF size\n"); while (length > 0) { mpf = (struct intel_mp_floating *)bp; if ((*bp == SMP_MAGIC_IDENT) && (mpf->mpf_length == 1) && !mpf_checksum((unsigned char *)bp, 16) && ((mpf->mpf_specification == 1) || (mpf->mpf_specification == 4)) ) { smp_found_config = 1; printk("found SMP MP-table at %08lx\n", virt_to_phys(mpf)); reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE); if (mpf->mpf_physptr) reserve_bootmem(mpf->mpf_physptr, PAGE_SIZE); mpf_found = mpf; return 1; } bp += 4; length -= 16; } return 0;}void __init find_intel_smp (void){ 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 */ if (smp_scan_config(0x0,0x400) || smp_scan_config(639*0x400,0x400) || smp_scan_config(0xF0000,0x10000)) 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 were 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. Thankfully the bootloaders * now honour the EBDA. */ address = *(unsigned short *)phys_to_virt(0x40E); address <<= 4; smp_scan_config(address, 0x1000);}#else/* * The Visual Workstation is Intel MP compliant in the hardware * sense, but it doesn't have a BIOS(-configuration table). * No problem for Linux. */void __init find_visws_smp(void){ smp_found_config = 1; phys_cpu_present_map |= 2; /* or in id 1 */ apic_version[1] |= 0x10; /* integrated APIC */ apic_version[0] |= 0x10; mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;}#endif/* * - Intel MP Configuration Table * - or SGI Visual Workstation configuration */void __init find_smp_config (void){#ifdef CONFIG_X86_LOCAL_APIC find_intel_smp();#endif#ifdef CONFIG_VISWS find_visws_smp();#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -