예제 #1
0
/*
 * 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
}
예제 #2
0
파일: mpbios.c 프로젝트: bluhm/sys
/*
 * 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
}