void idt_vec_reserve(int vec) { int result; KASSERT(mutex_owned(&cpu_lock) || !mp_online); result = idt_vec_alloc(vec, vec); if (result != vec) { panic("%s: failed to reserve vec %d", __func__, vec); } }
/* * A simple round-robin allocator to assign interrupts to CPUs. */ int intr_allocate_slot(struct pic *pic, int legacy_irq, int pin, int level, struct cpu_info **cip, int *index, int *idt_slot) { CPU_INFO_ITERATOR cii; struct cpu_info *ci; struct intrsource *isp; int slot, idtvec, error; /* * If a legacy IRQ is wanted, try to use a fixed slot pointing * at the primary CPU. In the case of IO APICs, multiple pins * may map to one legacy IRQ, but they should not be shared * in that case, so the first one gets the legacy slot, but * a subsequent allocation with a different pin will get * a different slot. */ if (legacy_irq != -1) { ci = &cpu_info_primary; /* must check for duplicate pic + pin first */ for (slot = 0 ; slot < MAX_INTR_SOURCES ; slot++) { isp = ci->ci_isources[slot]; if (isp != NULL && isp->is_pic == pic && isp->is_pin == pin ) { goto duplicate; } } slot = legacy_irq; isp = ci->ci_isources[slot]; if (isp == NULL) { isp = malloc(sizeof (struct intrsource), M_DEVBUF, M_NOWAIT|M_ZERO); if (isp == NULL) return ENOMEM; snprintf(isp->is_evname, sizeof (isp->is_evname), "pin %d", pin); ci->ci_isources[slot] = isp; } else { if (isp->is_pic != pic || isp->is_pin != pin) { if (pic == &i8259_pic) return EINVAL; goto other; } } duplicate: if (pic == &i8259_pic) idtvec = ICU_OFFSET + legacy_irq; else { #ifdef IOAPIC_HWMASK if (level > isp->is_maxlevel) { #else if (isp->is_minlevel == 0 || level < isp->is_minlevel) { #endif idtvec = idt_vec_alloc(APIC_LEVEL(level), IDT_INTR_HIGH); if (idtvec == 0) return EBUSY; } else idtvec = isp->is_idtvec; } } else {