/* * 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);
}
/* * We set up most of the low 16 IO-APIC pins according to MPS rules.
*/
construct_default_ioirq_mptable(mpc_default_type);
} #else staticinlinevoid __init construct_ioapic_table(int mpc_default_type) { } #endif
staticinlinevoid __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);
}
/* * 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");
if (!early && !acpi_lapic)
pr_info("Processors: %d\n", num_procs); /* * Only use the first configuration found.
*/
out:
early_memunmap(mpf, sizeof(*mpf));
}
/* * 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 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)
smp_scan_config(address, 0x400);
}
staticvoid __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare)
{ int i;
apic_pr_verbose("OLD ");
print_mp_irq_info(m);
i = get_MP_intsrc_index(m); if (i > 0) {
memcpy(m, &mp_irqs[i], sizeof(*m));
apic_pr_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;
}
}
staticint __init
check_slot(unsignedlong mpc_new_phys, unsignedlong mpc_new_length, int count)
{ if (!mpc_new_phys || count <= mpc_new_length) {
WARN(1, "update_mptable: No spare slots (length: %x)\n", count); return -1;
}
if (mpc_new_phys && mpc->length > mpc_new_length) {
mpc_new_phys = 0;
pr_info("mpc_new_length is %ld, please use alloc_mptable=8k\n",
mpc_new_length);
}
if (!mpc_new_phys) { unsignedchar old, new; /* check if we can change the position */
mpc->checksum = 0;
old = mpf_checksum((unsignedchar *)mpc, mpc->length);
mpc->checksum = 0xff; new = mpf_checksum((unsignedchar *)mpc, mpc->length); if (old == new) {
pr_info("mpc is readonly, please try alloc_mptable instead\n"); goto do_unmap_mpc;
}
pr_info("use in-position replacing\n");
} else {
mpc_new = early_memremap(mpc_new_phys, mpc_new_length); if (!mpc_new) {
pr_err("MPTABLE: new mpc early_memremap() failed\n"); goto do_unmap_mpc;
}
mpf->physptr = mpc_new_phys;
memcpy(mpc_new, mpc, mpc->length);
early_memunmap(mpc, size);
mpc = mpc_new;
size = mpc_new_length; /* check if we can modify that */ if (mpc_new_phys - mpf->physptr) { struct mpf_intel *mpf_new; /* steal 16 bytes from [0, 1k) */
mpf_new = early_memremap(0x400 - 16, sizeof(*mpf_new)); if (!mpf_new) {
pr_err("MPTABLE: new mpf early_memremap() failed\n"); goto do_unmap_mpc;
}
pr_info("mpf new: %x\n", 0x400 - 16);
memcpy(mpf_new, mpf, 16);
early_memunmap(mpf, sizeof(*mpf));
mpf = mpf_new;
mpf->physptr = mpc_new_phys;
}
mpf->checksum = 0;
mpf->checksum -= mpf_checksum((unsignedchar *)mpf, 16);
pr_info("physptr new: %x\n", mpf->physptr);
}
/* * 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);
do_unmap_mpc:
early_memunmap(mpc, size);
do_unmap_mpf:
early_memunmap(mpf, sizeof(*mpf));
return 0;
}
late_initcall(update_mp_table);
Messung V0.5
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.