void ioapic_init() {
    // TODO: multiple ioapics, etc.
    if(!pmem_reserve(IOAPIC_BASE, IOAPIC_VSZ))
        fatal("failed to reserve physical I/O APIC memory!\n");

    if(!vmem_map(spc_current(), IOAPIC_BASE, (void*)IOAPIC_VIRTUAL,
            PG_WRITABLE | PG_NONCACHABLE | PG_WRITETHROUGH | PG_GLOBAL))
        fatal("failed to map I/O APIC memory!\n");

    _the_ioapic = (ioapic_t*)IOAPIC_VIRTUAL;

    uint32_t idreg = ioapic_read(_the_ioapic, IOAPIC_REG_ID);
    uint32_t vreg = ioapic_read(_the_ioapic, IOAPIC_REG_VER);

    /* initially clear all redirection entries. resets all
     * entries to edge-triggered, active high, disabled, and
     * not routed to any cpu */
    for(uint32_t i = 0; i <= IOAPIC_MAX_REDIR(vreg); ++i) {
        ioapic_write(_the_ioapic, IOAPIC_REG_TABLE + (2 * i), IOAPIC_INT_MASKED | (IRQ_NUM(i)));
        ioapic_write(_the_ioapic, IOAPIC_REG_TABLE + ((2 * i) + 1), 0);
    }

    info("i/o apic %d version: 0x%x, max irq redirections: %d\n",
        IOAPIC_ID(idreg), IOAPIC_VER(vreg), IOAPIC_MAX_REDIR(vreg));
}
Exemple #2
0
void
ioapic_print_redir(struct ioapic_softc *sc, char *why, int pin)
{
	u_int32_t redirlo = ioapic_read(sc, IOAPIC_REDLO(pin));
	u_int32_t redirhi = ioapic_read(sc, IOAPIC_REDHI(pin));

	apic_format_redir(sc->sc_pic.pic_name, why, pin, redirhi, redirlo);
}
Exemple #3
0
/* Reprogram the APIC ID, and check that it actually got set. */
void
ioapic_set_id(struct ioapic_softc *sc) {
	u_int8_t apic_id;

	ioapic_write(sc, IOAPIC_ID,
	    (ioapic_read(sc, IOAPIC_ID) & ~IOAPIC_ID_MASK) |
	    (sc->sc_apicid << IOAPIC_ID_SHIFT));

	apic_id = (ioapic_read(sc, IOAPIC_ID) & IOAPIC_ID_MASK) >>
	    IOAPIC_ID_SHIFT;

	if (apic_id != sc->sc_apicid)
		printf(", can't remap to apid %d\n", sc->sc_apicid);
	else
		printf(", remapped to apid %d\n", sc->sc_apicid);
}
Exemple #4
0
void ioapic_enable_irq(int irq)
{
    struct apic_irq_to_pin pin_record = irq_map[irq];
    int pin = pin_record.pin;
    int chip = pin_record.chip;
    
    if (pin != -1 && chip != -1) {
        int addr = APIC_IO_REDTBL + pin * 2;
        struct io_redirection_register reg;
        
        reg.low = ioapic_read(chip, addr);
        reg.masked = 0;
        ioapic_write(chip, addr, reg.low);
        
//         kprintf("IRQ enabled, vector: %x, IRQ: %d\n", reg.vector, irq);
    }
/*    
    int i;
    for (i = 0; i < 32; i++) {
        int addr = APIC_IO_REDTBL + i * 2;
        struct io_redirection_register reg;
        
        reg.low = ioapic_read(chip, addr);
        
        kprintf("IRQ query, vector: %x, IRQ: %d\n", reg.vector, irq);
    }
    
    panic("here");*/
}
Exemple #5
0
static void ioapic_unmask_irq(int irq, unsigned flags)
{
	struct ioapic_info *ioa = &global_ioapics[irq / 24];
	int vec = irq % 24;

	/* transfer the act-low/level-trig pattern into the APIC setting word
	 * directly.
	 */
	assert(IHF_ACT_LOW == (1 << 0));
	assert(IHF_LEVEL_TRIG == (1 << 2));
	int trig_pol = (flags & (IHF_ACT_LOW | IHF_LEVEL_TRIG)) << 13;

	assert(CHECK_FLAG(trig_pol, 1 << 13)
		== CHECK_FLAG(flags, IHF_ACT_LOW));
	assert(CHECK_FLAG(trig_pol, 1 << 15)
		== CHECK_FLAG(flags, IHF_LEVEL_TRIG));

	/* bit 16 = interrupt mask bit.
	 *     15 = trigger mode (0 = edge, 1 = level)
	 *     13 = pin polarity (0 = active high, 1 = active low)
	 *     7..0 = interrupt vector (0x10..0xff)
	 *
	 * other fields select fixed (regular) delivery to a physical LAPIC (CPU
	 * 0, since mung is still not a SMP kernel).
	 */
	uint32_t ctl = ioapic_read(ioa, IOREDTBL(vec) + 0);
	ctl &= ~((1 << 16) | (1 << 13) | (1 << 15) | 0xff);
	ctl |= trig_pol | (0x20 + irq);
	ioapic_write(ioa, IOREDTBL(vec) + 0, ctl);
}
Exemple #6
0
void gsi_disable(unsigned gsi)
{
	uint32_t lo;

	assert(gsi < gsis_no);
	lo = ioapic_read(gsis[gsi].ioapic, IO_RED_LO(gsis[gsi].pin));
	lo |= 0x10000L;		/* MASK */
	ioapic_write(gsis[gsi].ioapic, IO_RED_LO(gsis[gsi].pin), lo);;
}
Exemple #7
0
static void ioapic_mask_irq(int irq)
{
	assert(!x86_irq_is_enabled());
	struct ioapic_info *ioa = &global_ioapics[irq / 24];
	int vec = irq % 24;

	uint32_t ctl = ioapic_read(ioa, IOREDTBL(vec) + 0);
	ctl |= 1 << 16;
	ioapic_write(ioa, IOREDTBL(vec) + 0, ctl);
}
Exemple #8
0
void gsi_register(unsigned gsi, unsigned vect)
{
	uint32_t lo;

	assert(gsi < gsis_no);
	assert(vect < 256);

	lo = ioapic_read(gsis[gsi].ioapic, IO_RED_LO(gsis[gsi].pin));
	ioapic_write(gsis[gsi].ioapic, IO_RED_LO(gsis[gsi].pin),
		     lo | vect);
}
Exemple #9
0
void ioapic_init_redirection_table(int chip, int pin, int vector, int trigger, int polarity)
{
    int addr = APIC_IO_REDTBL + pin * 2;
//     kprintf("Init redirection table, pin: %d, addr: %x, vector: %d\n", pin, addr, vector);
//     
    struct io_redirection_register reg;
    reg.low = ioapic_read(chip, addr);
    reg.high = ioapic_read(chip, addr + 1);
    
    reg.destmod = APIC_DESTMOD_PHYS;
    reg.delmod = APIC_DELMOD_FIXED;
    reg.trigger_mode = trigger;
    reg.intpol = polarity;
    reg.vector = vector;
    reg.masked = 1;
    
    reg.dest = 0; //0xff;
    
    ioapic_write(chip, addr, reg.low);
    ioapic_write(chip, addr + 1, reg.high);
}
Exemple #10
0
static void single_ioapic_init(word_t ioapic, cpu_id_t delivery_cpu)
{
    uint32_t i;

    /* Mask all the IRQs. In doing so we happen to set
     * the vector to 0, which we can assert against in
     * mask_interrupt to ensure a vector is assigned
     * before we unmask */
    for (i = 0; i < IOAPIC_IRQ_LINES; i++) {
        /* Send to desired cpu */
        ioapic_write(ioapic, IOAPIC_REGSEL, IOREDTBL_HIGH(i));
        ioapic_write(ioapic, IOAPIC_WINDOW, (ioapic_read(ioapic,
                                                         IOAPIC_WINDOW) & MASK(IOREDTBL_HIGH_RESERVED_BITS)) | (delivery_cpu << IOREDTBL_HIGH_RESERVED_BITS));
        /* mask and set 0 vector */
        ioredtbl_state[i] = IOREDTBL_LOW_INTERRUPT_MASK;
        ioapic_write(ioapic, IOAPIC_REGSEL, IOREDTBL_LOW(i));
        /* The upper 16 bits are reserved, so we make sure to preserve them */
        ioredtbl_state[i] |= ioapic_read(ioapic, IOAPIC_WINDOW) & ~MASK(16);
        ioapic_write(ioapic, IOAPIC_WINDOW, ioredtbl_state[i]);
    }
}
Exemple #11
0
static void
ioapic_abi_intr_teardown(int intr)
{
	const struct ioapic_irqmap *map;
	int vector, select;
	uint32_t value;
	register_t ef;

	KASSERT(intr >= 0 && intr < IOAPIC_HWI_VECTORS,
	    ("ioapic teardown, invalid irq %d\n", intr));

	map = &ioapic_irqmaps[mycpuid][intr];
	KASSERT(IOAPIC_IMT_ISHWI(map),
	    ("ioapic teardown, not hwi irq %d, type %d, cpu%d",
	     intr, map->im_type, mycpuid));
	if (map->im_type != IOAPIC_IMT_LEGACY)
		return;

	KASSERT(ioapic_irqs[intr].io_addr != NULL,
	    ("ioapic teardown, no GSI information, irq %d\n", intr));

	ef = read_rflags();
	cpu_disable_intr();

	/*
	 * Teardown an interrupt vector.  The vector should already be
	 * installed in the cpu's IDT, but make sure.
	 */
	IOAPIC_INTRDIS(intr);

	vector = IDT_OFFSET + intr;

	/*
	 * In order to avoid losing an EOI for a level interrupt, which
	 * is vector based, make sure that the IO APIC is programmed for
	 * edge-triggering first, then reprogrammed with the new vector.
	 * This should clear the IRR bit.
	 */
	imen_lock();

	select = ioapic_irqs[intr].io_idx;
	value = ioapic_read(ioapic_irqs[intr].io_addr, select);

	ioapic_write(ioapic_irqs[intr].io_addr, select,
	    (value & ~APIC_TRIGMOD_MASK));
	ioapic_write(ioapic_irqs[intr].io_addr, select,
	    (value & ~IOART_INTVEC) | vector);

	imen_unlock();

	write_rflags(ef);
}
Exemple #12
0
void ioapic_map_pin_to_vector(word_t ioapic, word_t pin, word_t level,
                              word_t polarity, word_t vector)
{
    uint32_t ioredtbl_high = 0;
    uint32_t index = 0;

    index = ioapic * IOAPIC_IRQ_LINES + pin;
    ioapic_write(ioapic, IOAPIC_REGSEL, IOREDTBL_HIGH(pin));
    ioredtbl_high = ioapic_read(ioapic, IOAPIC_WINDOW) & MASK(IOREDTBL_HIGH_RESERVED_BITS);
    /* delivery mode: physical mode only, using APIC ID */
    ioredtbl_high |= (ioapic_target_cpu << IOREDTBL_HIGH_RESERVED_BITS);
    ioapic_write(ioapic, IOAPIC_WINDOW, ioredtbl_high);
    /* we do not need to add IRQ_INT_OFFSET to the vector here */
    ioredtbl_state[index] = IOREDTBL_LOW_INTERRUPT_MASK |
                            (level << IOREDTBL_LOW_TRIGGER_MODE_SHIFT) |
                            (polarity << IOREDTBL_LOW_POLARITY_SHIFT) |
                            vector;

    ioapic_write(ioapic, IOAPIC_REGSEL, IOREDTBL_LOW(pin));
    /* the upper 16 bits are reserved */
    ioredtbl_state[index] |= ioapic_read(ioapic, IOAPIC_WINDOW) & ~MASK(16);
    ioapic_write(ioapic, IOAPIC_WINDOW, ioredtbl_state[index]);
}
Exemple #13
0
void ioapic_disable_irq(int irq)
{
    struct apic_irq_to_pin pin_record = irq_map[irq];
    int pin = pin_record.pin;
    int chip = pin_record.chip;
    
    if (pin != -1 && chip != -1) {
        volatile struct io_redirection_register reg;
        
        reg.low = ioapic_read(chip, APIC_IO_REDTBL + pin * 2);
        reg.masked = 1;
        ioapic_write(chip, APIC_IO_REDTBL + pin * 2, reg.low);
    }
}
Exemple #14
0
static void
ioapic_abi_intr_setup(int intr, int flags)
{
	const struct ioapic_irqmap *map;
	int vector, select;
	uint32_t value;
	register_t ef;

	KASSERT(intr >= 0 && intr < IOAPIC_HWI_VECTORS,
	    ("ioapic setup, invalid irq %d", intr));

	map = &ioapic_irqmaps[mycpuid][intr];
	KASSERT(IOAPIC_IMT_ISHWI(map),
	    ("ioapic setup, not hwi irq %d, type %d, cpu%d",
	     intr, map->im_type, mycpuid));
	if (map->im_type != IOAPIC_IMT_LEGACY)
		return;

	KASSERT(ioapic_irqs[intr].io_addr != NULL,
	    ("ioapic setup, no GSI information, irq %d", intr));

	ef = read_rflags();
	cpu_disable_intr();

	vector = IDT_OFFSET + intr;

	/*
	 * Now reprogram the vector in the IO APIC.  In order to avoid
	 * losing an EOI for a level interrupt, which is vector based,
	 * make sure that the IO APIC is programmed for edge-triggering
	 * first, then reprogrammed with the new vector.  This should
	 * clear the IRR bit.
	 */
	imen_lock();

	select = ioapic_irqs[intr].io_idx;
	value = ioapic_read(ioapic_irqs[intr].io_addr, select);
	value |= IOART_INTMSET;

	ioapic_write(ioapic_irqs[intr].io_addr, select,
	    (value & ~APIC_TRIGMOD_MASK));
	ioapic_write(ioapic_irqs[intr].io_addr, select,
	    (value & ~IOART_INTVEC) | vector);

	imen_unlock();

	IOAPIC_INTREN(intr);

	write_rflags(ef);
}
Exemple #15
0
void IOAPIC::SetupIDsFromMPC() {
	union IO_APIC_reg_00 reg_00;

	if(system->cpuid->vendor_code != VENDOR_INTEL || APIC_XAPIC(system->smp->apic_version[system->smp->boot_cpu_physical_apicid])) {
		printk("xAPIC detected, skipping setting IO-APIC IDs\n");
		return;
	}

	for (int apic = 0; apic < system->smp->nr_ioapics; apic++) {
		reg_00.raw = ioapic_read(apic, 0);

		int old_id = system->smp->mp_ioapics[apic].mpc_apicid;

		if (old_id >= parent->GetPhysicalBroadcast()) {
			printk("BIOS bug, IO-APIC#%d ID is %d in the MPC table, fixing up to %d\n",
				apic, old_id, reg_00.bits.ID);
			system->smp->mp_ioapics[apic].mpc_apicid = reg_00.bits.ID;
		}

		if (old_id != system->smp->mp_ioapics[apic].mpc_apicid)
			for (int i = 0; i < system->smp->mp_irq_entries; i++)
				if (system->smp->mp_irqs[i].mpc_dstapic == old_id)
					system->smp->mp_irqs[i].mpc_dstapic = system->smp->mp_ioapics[apic].mpc_apicid;

		printk(	"Changing IO-APIC physical APIC ID to %d ...", system->smp->mp_ioapics[apic].mpc_apicid);

		reg_00.bits.ID = system->smp->mp_ioapics[apic].mpc_apicid;
		ioapic_write(apic, 0, reg_00.raw);

		reg_00.raw = ioapic_read(apic, 0);

		if (reg_00.bits.ID != system->smp->mp_ioapics[apic].mpc_apicid)
			printk("could not set ID!\n");
		else
			printk(" ok.\n");
	}
}
Exemple #16
0
int
ioapic_activate(struct device *self, int act)
{
	struct ioapic_softc *sc = (struct ioapic_softc *)self;

	switch (act) {
	case DVACT_RESUME:
		/* On resume, reset the APIC id, like we do on boot */
		ioapic_write(sc, IOAPIC_ID,
		    (ioapic_read(sc, IOAPIC_ID) & ~IOAPIC_ID_MASK) |
		    (sc->sc_apicid << IOAPIC_ID_SHIFT));
	}

	return (0);
}
Exemple #17
0
void ioapic_change_io_redirection_table(int chip, int pin, int dest, int vec, u32 flags)
{
    u32 dlvr;
    
    if (flags & APIC_LOPRI) {
        dlvr = APIC_DELMOD_LOWPRI;
    } else {
        dlvr = APIC_DELMOD_FIXED;
    }
    
    struct io_redirection_register reg;
    reg.low = ioapic_read(chip, APIC_IO_REDTBL + pin * 2);
    reg.high = ioapic_read(chip, APIC_IO_REDTBL + pin * 2 + 1);
    
    reg.dest = dest;
    reg.destmod = APIC_DESTMOD_PHYS;
    reg.trigger_mode = APIC_TRIGMOD_EDGE;
    reg.intpol = APIC_POLARITY_HIGH;
    reg.delmod = dlvr;
    reg.vector = vec;
    
    ioapic_write(chip, APIC_IO_REDTBL + pin * 2, reg.low);
    ioapic_write(chip, APIC_IO_REDTBL + pin * 2 + 1, reg.high);
}
Exemple #18
0
void IOAPIC::EnableIOAPIC () {
	union IO_APIC_reg_01 reg_01;

	for(int i = 0; i < PIN_MAP_SIZE; i++) {
		irq_2_pin[i].pin = -1;
		irq_2_pin[i].next = 0;
	}

	for(int i = 0; i < MAX_PIRQS; i++)
		pirq_entries[i] = -1;

	for(int apic = 0; apic < system->smp->nr_ioapics; apic++) {
		reg_01.raw = ioapic_read(apic, 1);
		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
	}
	for(int apic = 0; apic < system->smp->nr_ioapics; apic++) {
		for (int pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
			struct IO_APIC_route_entry entry;
			entry = ReadEntry(apic, pin);

			if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
				ioapic_i8259.apic = apic;
				ioapic_i8259.pin  = pin;
				goto found_i8259;
			}
		}
	}
found_i8259:

	int i8259_pin  = system->smp->FindISAIRQPin(0, mp_ExtINT);
	int i8259_apic = system->smp->FindISAIRQAPIC(0, mp_ExtINT);
	/* Trust the MP table if nothing is setup in the hardware */
	if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) {
		printk("IOAPIC: ExtINT not setup in hardware but reported by MP table\n");
		ioapic_i8259.pin  = i8259_pin;
		ioapic_i8259.apic = i8259_apic;
	}

	if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin)) &&
		(i8259_pin >= 0) && (ioapic_i8259.pin >= 0))
	{
		printk("IOAPIC: ExtINT in hardware and MP table differ\n");
	}

	ClearIOAPIC();
}
Exemple #19
0
int do_ioapic(struct guest_thread *vm_thread, uint64_t gpa, int destreg,
              uint64_t *regp, int store)
{
	// TODO: compute an index for the ioapic array. 
	int ix = 0;
	uint32_t offset = gpa & 0xfffff;
	/* basic sanity tests. */
	DPRINTF("%s: %p 0x%x %p %s\n", __func__, (void *)gpa, destreg, regp, store ? "write" : "read");

	if ((offset != 0) && (offset != 0x10)) {
		DPRINTF("Bad register offset: 0x%x and has to be 0x0 or 0x10\n", offset);
		return -1;
	}

	if (store) {
		ioapic_write(ix, offset, *regp);
	} else {
		*regp = ioapic_read(ix, offset);
	}

}
Exemple #20
0
static void apic_setup(void)
{
    /*
     * This would the The Right Thing To Do (tm), if only qemu negotiated
     * with Xen where the IO-APIC actually sits (which is currently hard
     * coded in Xen and can't be controlled externally). Uncomment this code
     * once that changed.
    ioapic_base_address |= (pci_readb(PCI_ISA_DEVFN, 0x80) & 0x3f) << 10;
     */
    ioapic_version = ioapic_read(0x01) & 0xff;

    /* Set the IOAPIC ID to the static value used in the MP/ACPI tables. */
    ioapic_write(0x00, IOAPIC_ID);

    /* NMIs are delivered direct to the BSP. */
    lapic_write(APIC_SPIV, APIC_SPIV_APIC_ENABLED | 0xFF);
    lapic_write(APIC_LVT0, (APIC_MODE_EXTINT << 8) | APIC_LVT_MASKED);
    lapic_write(APIC_LVT1, APIC_MODE_NMI << 8);

    /* 8259A ExtInts are delivered through IOAPIC pin 0 (Virtual Wire Mode). */
    ioapic_write(0x10, APIC_DM_EXTINT);
    ioapic_write(0x11, SET_APIC_ID(LAPIC_ID(0)));
}
Exemple #21
0
struct IO_APIC_route_entry IOAPIC::ReadEntry(int apic, int pin) {
	union entry_union eu;
	eu.w1 = ioapic_read(apic, 0x10 + 2 * pin);
	eu.w2 = ioapic_read(apic, 0x11 + 2 * pin);
	return eu.entry;
}
Exemple #22
0
/*
 * can't use bus_space_xxx as we don't have a bus handle ...
 */
void 
ioapic_attach(struct device *parent, struct device *self, void *aux)
{
	struct ioapic_softc *sc = (struct ioapic_softc *)self;  
	struct apic_attach_args  *aaa = (struct apic_attach_args  *) aux;
	int apic_id;
	bus_space_handle_t bh;
	u_int32_t ver_sz;
	int i;
	
	sc->sc_flags = aaa->flags;
	sc->sc_apicid = aaa->apic_id;

	printf(" apid %d", aaa->apic_id);

	if (ioapic_find(aaa->apic_id) != NULL) {
		printf(", duplicate apic id (ignored)\n");
		return;
	}

	ioapic_add(sc);

	printf(" pa 0x%lx", aaa->apic_address);

	if (x86_mem_add_mapping(aaa->apic_address, PAGE_SIZE, 0, &bh) != 0) {
		printf(", map failed\n");
		return;
	}
	sc->sc_reg = (volatile u_int32_t *)(bh + IOAPIC_REG);
	sc->sc_data = (volatile u_int32_t *)(bh + IOAPIC_DATA);	

	sc->sc_pic.pic_type = PIC_IOAPIC;
	mtx_init(&sc->sc_pic.pic_mutex, IPL_NONE);
	sc->sc_pic.pic_hwmask = ioapic_hwmask;
	sc->sc_pic.pic_hwunmask = ioapic_hwunmask;
	sc->sc_pic.pic_addroute = ioapic_addroute;
	sc->sc_pic.pic_delroute = ioapic_delroute;
	sc->sc_pic.pic_edge_stubs = ioapic_edge_stubs;
	sc->sc_pic.pic_level_stubs = ioapic_level_stubs;

	ver_sz = ioapic_read(sc, IOAPIC_VER);
	sc->sc_apic_vers = (ver_sz & IOAPIC_VER_MASK) >> IOAPIC_VER_SHIFT;
	sc->sc_apic_sz = (ver_sz & IOAPIC_MAX_MASK) >> IOAPIC_MAX_SHIFT;
	sc->sc_apic_sz++;

	if (aaa->apic_vecbase != -1)
		sc->sc_apic_vecbase = aaa->apic_vecbase;
	else {
		/*
		 * XXX this assumes ordering of ioapics in the table.
		 * Only needed for broken BIOS workaround (see mpbios.c)
		 */
		sc->sc_apic_vecbase = ioapic_vecbase;
		ioapic_vecbase += sc->sc_apic_sz;
	}

	if (mp_verbose) {
		printf(", %s mode",
		    aaa->flags & IOAPIC_PICMODE ? "PIC" : "virtual wire");
	}

	printf(", version %x, %d pins\n", sc->sc_apic_vers, sc->sc_apic_sz);

	apic_id = (ioapic_read(sc, IOAPIC_ID) & IOAPIC_ID_MASK) >>
	    IOAPIC_ID_SHIFT;

	sc->sc_pins = malloc(sizeof(struct ioapic_pin) * sc->sc_apic_sz,
	    M_DEVBUF, M_WAITOK);

	for (i=0; i<sc->sc_apic_sz; i++) {
		sc->sc_pins[i].ip_next = NULL;
		sc->sc_pins[i].ip_map = NULL;
		sc->sc_pins[i].ip_vector = 0;
		sc->sc_pins[i].ip_type = IST_NONE;
	}

	/*
	 * In case the APIC is not initialized to the correct ID
	 * do it now.
	 * Maybe we should record the original ID for interrupt
	 * mapping later ...
	 */
	if (apic_id != sc->sc_apicid) {
		printf("%s: misconfigured as apic %d",
		    sc->sc_pic.pic_dev.dv_xname, apic_id);
		ioapic_set_id(sc);
	}
#if 0
	/* output of this was boring. */
	if (mp_verbose)
		for (i=0; i<sc->sc_apic_sz; i++)
			ioapic_print_redir(sc, "boot", i);
#endif
}