/* * 1st pass on BIOS's Intel MP specification table. * * initializes: * mp_ncpus = 1 * * determines: * cpu_apic_address (common to all CPUs) * ioapic_address[N] * mp_naps * mp_nbusses * mp_napics * nintrs */ void mpbios_scan(struct device *self) { const u_int8_t *position, *end; int count; int type; int intr_cnt, cur_intr; paddr_t lapic_base; const struct mpbios_int *iep; struct mpbios_int ie; struct ioapic_softc *sc; printf(": Intel MP Specification 1.%d\n", mp_fps->spec_rev); /* * looks like we've got a MP system. start setting up * infrastructure.. * XXX is this the right place?? */ lapic_base = LAPIC_BASE; if (mp_cth != NULL) lapic_base = (paddr_t)mp_cth->apic_address; lapic_boot_init(lapic_base); /* check for use of 'default' configuration */ if (mp_fps->mpfb1 != 0) { struct mpbios_proc pe; printf("%s: MP default configuration %d\n", self->dv_xname, mp_fps->mpfb1); /* use default addresses */ pe.apic_id = lapic_cpu_number(); pe.cpu_flags = PROCENTRY_FLAG_EN|PROCENTRY_FLAG_BP; pe.cpu_signature = cpu_info_primary.ci_signature; pe.feature_flags = cpu_info_primary.ci_feature_flags; mpbios_cpu((u_int8_t *)&pe, self); pe.apic_id = 1 - lapic_cpu_number(); pe.cpu_flags = PROCENTRY_FLAG_EN; mpbios_cpu((u_int8_t *)&pe, self); mpbios_ioapic((u_int8_t *)&default_ioapic, self); /* XXX */ printf("%s: WARNING: interrupts not configured\n", self->dv_xname); panic("lazy bum"); return; } else { /* * should not happen; mp_probe returns 0 in this case, * but.. */ if (mp_cth == NULL) panic("mpbios_scan: no config (can't happen?)"); /* * Walk the table once, counting items */ position = (const u_int8_t *)(mp_cth); end = position + mp_cth->base_len; position += sizeof(*mp_cth); count = mp_cth->entry_count; intr_cnt = 0; while ((count--) && (position < end)) { type = *position; if (type >= MPS_MCT_NTYPES) { printf("%s: unknown entry type %x" " in MP config table\n", self->dv_xname, type); break; } mp_conf[type].count++; if (type == MPS_MCT_BUS) { const struct mpbios_bus *bp = (const struct mpbios_bus *)position; if (bp->bus_id >= mp_nbusses) mp_nbusses = bp->bus_id + 1; } /* * Count actual interrupt instances. * dst_apic_id of MPS_ALL_APICS means "wired to all * apics of this type". */ if (type == MPS_MCT_IOINT) { iep = (const struct mpbios_int *)position; if (iep->dst_apic_id == MPS_ALL_APICS) intr_cnt += mp_conf[MPS_MCT_IOAPIC].count; else intr_cnt++; } else if (type == MPS_MCT_LINT) intr_cnt++; position += mp_conf[type].length; } mp_busses = malloc(sizeof(struct mp_bus) * mp_nbusses, M_DEVBUF, M_NOWAIT|M_ZERO); mp_intrs = malloc(sizeof(struct mp_intr_map) * intr_cnt, M_DEVBUF, M_NOWAIT); /* re-walk the table, recording info of interest */ position = (const u_int8_t *)mp_cth + sizeof(*mp_cth); count = mp_cth->entry_count; cur_intr = 0; while ((count--) && (position < end)) { switch (type = *(u_char *)position) { case MPS_MCT_CPU: mpbios_cpu(position, self); break; case MPS_MCT_BUS: mpbios_bus(position, self); break; case MPS_MCT_IOAPIC: mpbios_ioapic(position, self); break; case MPS_MCT_IOINT: iep = (const struct mpbios_int *)position; ie = *iep; if (iep->dst_apic_id == MPS_ALL_APICS) { for (sc = ioapics ; sc != NULL; sc = sc->sc_next) { ie.dst_apic_id = sc->sc_apicid; if (mpbios_int((char *)&ie, type, &mp_intrs[cur_intr]) == 0) cur_intr++; } } else { if (mpbios_int(position, type, &mp_intrs[cur_intr]) == 0) cur_intr++; } break; case MPS_MCT_LINT: if (mpbios_int(position, type, &mp_intrs[cur_intr]) == 0) cur_intr++; break; default: printf("%s: unknown entry type %x " "in MP config table\n", self->dv_xname, type); /* NOTREACHED */ return; } position += mp_conf[type].length; } mp_nintrs = cur_intr; if (mp_verbose && mp_cth->ext_len) printf("%s: MP WARNING: %d " "bytes of extended entries not examined\n", self->dv_xname, mp_cth->ext_len); } /* Clean up. */ mp_fps = NULL; mpbios_unmap(&mp_fp_map); if (mp_cth != NULL) { mp_cth = NULL; mpbios_unmap(&mp_cfg_table_map); } mpbios_scanned = 1; #if NPCI > 0 mpbios_intr_fixup(); #endif }
/* * 1st pass on BIOS's Intel MP specification table. * * initializes: * mp_ncpus = 1 * * determines: * cpu_apic_address (common to all CPUs) * ioapic_address[N] * mp_naps * mp_nbusses * mp_napics * nintrs */ void mpbios_scan(struct device *self) { const u_int8_t *position, *end; int count; int type; int intr_cnt; paddr_t lapic_base; printf(": Intel MP Specification 1.%d\n", mp_fps->spec_rev); /* * looks like we've got a MP system. start setting up * infrastructure.. * XXX is this the right place?? */ lapic_base = LAPIC_BASE; if (mp_cth != NULL) lapic_base = (paddr_t)mp_cth->apic_address; lapic_boot_init(lapic_base); /* * Walk the table once, counting items */ for (count = mp_cth->entry_count, position = (const u_int8_t *)mp_cth + sizeof(*mp_cth), end = position + mp_cth->base_len; count-- && position < end; position += mp_conf[type].length) { type = *position; if (type >= MPS_MCT_NTYPES) { printf("%s: unknown entry type %x" " in MP config table\n", self->dv_xname, type); end = position; break; } mp_conf[type].count++; } /* * Walk the table twice, counting int and bus entries */ for (count = mp_cth->entry_count, intr_cnt = 15, /* presume all isa irqs missing */ position = (const u_int8_t *)mp_cth + sizeof(*mp_cth); count-- && position < end; position += mp_conf[type].length) { type = *position; if (type == MPS_MCT_BUS) { const struct mpbios_bus *bp = (const struct mpbios_bus *)position; if (bp->bus_id >= mp_nbusses) mp_nbusses = bp->bus_id + 1; } /* * Count actual interrupt instances. * dst_apic_id of MPS_ALL_APICS means "wired to all * apics of this type". */ if ((type == MPS_MCT_IOINT) || (type == MPS_MCT_LINT)) { const struct mpbios_int *ie = (const struct mpbios_int *)position; if (ie->dst_apic_id != MPS_ALL_APICS) intr_cnt++; else if (type == MPS_MCT_IOINT) intr_cnt += mp_conf[MPS_MCT_IOAPIC].count; else intr_cnt += mp_conf[MPS_MCT_CPU].count; } } mp_busses = mallocarray(mp_nbusses, sizeof(struct mp_bus), M_DEVBUF, M_WAITOK|M_ZERO); mp_intrs = mallocarray(intr_cnt, sizeof(struct mp_intr_map), M_DEVBUF, M_WAITOK); /* re-walk the table, recording info of interest */ position = (const u_int8_t *)mp_cth + sizeof(*mp_cth); count = mp_cth->entry_count; mp_nintrs = 0; while ((count--) && (position < end)) { switch (type = *(u_char *)position) { case MPS_MCT_CPU: mpbios_cpu(position, self); break; case MPS_MCT_BUS: mpbios_bus(position, self); break; case MPS_MCT_IOAPIC: mpbios_ioapic(position, self); break; case MPS_MCT_IOINT: case MPS_MCT_LINT: if (mpbios_int(position, &mp_intrs[mp_nintrs]) == 0) mp_nintrs++; break; default: printf("%s: unknown entry type %x " "in MP config table\n", self->dv_xname, type); /* NOTREACHED */ return; } position += mp_conf[type].length; } if (mp_verbose && mp_cth->ext_len) printf("%s: MP WARNING: %d " "bytes of extended entries not examined\n", self->dv_xname, mp_cth->ext_len); /* Clean up. */ mp_fps = NULL; mpbios_unmap(&mp_fp_map); if (mp_cth != NULL) { mp_cth = NULL; mpbios_unmap(&mp_cfg_table_map); } #if NPCI > 0 if (pci_mode_detect() != 0) mpbios_intr_fixup(); #endif }