FreeBSD/sys/x86/xen/xen_intr.c
/**
 * Configure CPU affinity for interrupt source event delivery.
 *
 * \param isrc     The interrupt source to configure.
 * \param apic_id  The apic id of the CPU for handling future events.
 *
 * \returns  0 if successful, otherwise an errno.
 */
Configure CPU affinity for interrupt source event delivery.
\param isrc     The interrupt source to configure.
\param apic_id  The apic id of the CPU for handling future events.

\returns  0 if successful, otherwise an errno.
Configure CPU affinity for interrupt source event delivery . \ param isrc The interrupt source to configure . \ param apic_id The apic id of the CPU for handling future events . \ returns 0 if successful otherwise an errno .
static int
xen_intr_assign_cpu(struct intsrc *base_isrc, u_int apic_id)
{
#ifdef SMP
	struct evtchn_bind_vcpu bind_vcpu;
	struct xenisrc *isrc;
	u_int to_cpu, vcpu_id;
	int error, masked;
	if (xen_vector_callback_enabled == 0)
		return (EOPNOTSUPP);
	to_cpu = apic_cpuid(apic_id);
	vcpu_id = pcpu_find(to_cpu)->pc_vcpu_id;
	xen_intr_intrcnt_add(to_cpu);
	mtx_lock(&xen_intr_isrc_lock);
	isrc = (struct xenisrc *)base_isrc;
	if (!is_valid_evtchn(isrc->xi_port)) {
		mtx_unlock(&xen_intr_isrc_lock);
		return (EINVAL);
	}
	masked = evtchn_test_and_set_mask(isrc->xi_port);
	if ((isrc->xi_type == EVTCHN_TYPE_VIRQ) ||
		(isrc->xi_type == EVTCHN_TYPE_IPI)) {
		evtchn_cpu_mask_port(isrc->xi_cpu, isrc->xi_port);
		isrc->xi_cpu = to_cpu;
		evtchn_cpu_unmask_port(isrc->xi_cpu, isrc->xi_port);
		goto out;
	}
	bind_vcpu.port = isrc->xi_port;
	bind_vcpu.vcpu = vcpu_id;
	error = HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu);
	if (isrc->xi_cpu != to_cpu) {
		if (error == 0) {
			evtchn_cpu_mask_port(isrc->xi_cpu, isrc->xi_port);
			isrc->xi_cpu = to_cpu;
			evtchn_cpu_unmask_port(isrc->xi_cpu, isrc->xi_port);
		}
	}
out:
	if (masked == 0)
		evtchn_unmask_port(isrc->xi_port);
	mtx_unlock(&xen_intr_isrc_lock);
	return (0);
#else
	return (EOPNOTSUPP);
#endif
}
static int xen_intr_assign_cpu ( struct intsrc * base_isrc , u_int apic_id ) { #ifdef SMP struct evtchn_bind_vcpu bind_vcpu ; struct xenisrc * isrc ; u_int to_cpu , vcpu_id ; int error , masked ; if ( xen_vector_callback_enabled == 0 ) return ( EOPNOTSUPP ) ; to_cpu = apic_cpuid ( apic_id ) ; vcpu_id = pcpu_find ( to_cpu ) -> pc_vcpu_id ; xen_intr_intrcnt_add ( to_cpu ) ; mtx_lock ( & xen_intr_isrc_lock ) ; isrc = ( struct xenisrc * ) base_isrc ; if ( ! is_valid_evtchn ( isrc -> xi_port ) ) { mtx_unlock ( & xen_intr_isrc_lock ) ; return ( EINVAL ) ; } masked = evtchn_test_and_set_mask ( isrc -> xi_port ) ; if ( ( isrc -> xi_type == EVTCHN_TYPE_VIRQ ) || ( isrc -> xi_type == EVTCHN_TYPE_IPI ) ) { evtchn_cpu_mask_port ( isrc -> xi_cpu , isrc -> xi_port ) ; isrc -> xi_cpu = to_cpu ; evtchn_cpu_unmask_port ( isrc -> xi_cpu , isrc -> xi_port ) ; goto out ; } bind_vcpu . port = isrc -> xi_port ; bind_vcpu . vcpu = vcpu_id ; error = HYPERVISOR_event_channel_op ( EVTCHNOP_bind_vcpu , & bind_vcpu ) ; if ( isrc -> xi_cpu != to_cpu ) { if ( error == 0 ) { evtchn_cpu_mask_port ( isrc -> xi_cpu , isrc -> xi_port ) ; isrc -> xi_cpu = to_cpu ; evtchn_cpu_unmask_port ( isrc -> xi_cpu , isrc -> xi_port ) ; } } out : if ( masked == 0 ) evtchn_unmask_port ( isrc -> xi_port ) ; mtx_unlock ( & xen_intr_isrc_lock ) ; return ( 0 ) ; #else return ( EOPNOTSUPP ) ; #endif }
Configure CPU affinity for interrupt source event delivery.
Configure CPU affinity for interrupt source event delivery .
/*
	 * Mask the event channel while binding it to prevent interrupt
	 * delivery with an inconsistent state in isrc->xi_cpu.
	 */ /*
		 * Virtual IRQs are associated with a cpu by
		 * the Hypervisor at evtchn_bind_virq time, so
		 * all we need to do is update the per-CPU masks.
		 */ /* Commit to new binding by removing the old one. */