FreeBSD/sys/x86/xen/xen_intr.c
/**
 * Interrupt handler for processing all Xen event channel events.
 * 
 * \param trap_frame  The trap frame context for the current interrupt.
 */
Interrupt handler for processing all Xen event channel events.

\param trap_frame  The trap frame context for the current interrupt.
Interrupt handler for processing all Xen event channel events . \ param trap_frame The trap frame context for the current interrupt .
void
xen_intr_handle_upcall(struct trapframe *trap_frame)
{
	u_int l1i, l2i, port, cpu;
	u_long masked_l1, masked_l2;
	struct xenisrc *isrc;
	shared_info_t *s;
	vcpu_info_t *v;
	struct xen_intr_pcpu_data *pc;
	u_long l1, l2;
	critical_enter();
	cpu = PCPU_GET(cpuid);
	pc  = DPCPU_PTR(xen_intr_pcpu);
	s   = HYPERVISOR_shared_info;
	v   = DPCPU_GET(vcpu_info);
	if (xen_hvm_domain() && !xen_vector_callback_enabled) {
		KASSERT((cpu == 0), ("Fired PCI event callback on wrong CPU"));
	}
	v->evtchn_upcall_pending = 0;
#if 0
#ifndef CONFIG_X86 
	wmb();
#endif
#endif
	l1 = atomic_readandclear_long(&v->evtchn_pending_sel);
	l1i = pc->last_processed_l1i;
	l2i = pc->last_processed_l2i;
	(*pc->evtchn_intrcnt)++;
	while (l1 != 0) {
		l1i = (l1i + 1) % LONG_BIT;
		masked_l1 = l1 & ((~0UL) << l1i);
		if (masked_l1 == 0) {
			l1i = LONG_BIT - 1;
			l2i = LONG_BIT - 1;
			continue;
		}
		l1i = ffsl(masked_l1) - 1;
		do {
			l2 = xen_intr_active_ports(pc, s, l1i);
			l2i = (l2i + 1) % LONG_BIT;
			masked_l2 = l2 & ((~0UL) << l2i);
			if (masked_l2 == 0) {
				l2i = LONG_BIT - 1;
				break;
			}
			l2i = ffsl(masked_l2) - 1;
			port = (l1i * LONG_BIT) + l2i;
			synch_clear_bit(port, &s->evtchn_pending[0]);
			isrc = xen_intr_port_to_isrc[port];
			if (__predict_false(isrc == NULL))
				continue;
			KASSERT((isrc->xi_cpu == PCPU_GET(cpuid)),
				("Received unexpected event on vCPU#%d, event bound to vCPU#%d",
				PCPU_GET(cpuid), isrc->xi_cpu));
			intr_execute_handlers(&isrc->xi_intsrc, trap_frame);
			pc->last_processed_l1i = l1i;
			pc->last_processed_l2i = l2i;
		} while (l2i != LONG_BIT - 1);
		l2 = xen_intr_active_ports(pc, s, l1i);
		if (l2 == 0) {
			l1 &= ~(1UL << l1i);
		}
	}
	critical_exit();
}
void xen_intr_handle_upcall ( struct trapframe * trap_frame ) { u_int l1i , l2i , port , cpu ; u_long masked_l1 , masked_l2 ; struct xenisrc * isrc ; shared_info_t * s ; vcpu_info_t * v ; struct xen_intr_pcpu_data * pc ; u_long l1 , l2 ; critical_enter ( ) ; cpu = PCPU_GET ( cpuid ) ; pc = DPCPU_PTR ( xen_intr_pcpu ) ; s = HYPERVISOR_shared_info ; v = DPCPU_GET ( vcpu_info ) ; if ( xen_hvm_domain ( ) && ! xen_vector_callback_enabled ) { KASSERT ( ( cpu == 0 ) , ( " " ) ) ; } v -> evtchn_upcall_pending = 0 ; #if 0 #ifndef CONFIG_X86 wmb ( ) ; #endif #endif l1 = atomic_readandclear_long ( & v -> evtchn_pending_sel ) ; l1i = pc -> last_processed_l1i ; l2i = pc -> last_processed_l2i ; ( * pc -> evtchn_intrcnt ) ++ ; while ( l1 != 0 ) { l1i = ( l1i + 1 ) % LONG_BIT ; masked_l1 = l1 & ( ( ~ 0UL ) << l1i ) ; if ( masked_l1 == 0 ) { l1i = LONG_BIT - 1 ; l2i = LONG_BIT - 1 ; continue ; } l1i = ffsl ( masked_l1 ) - 1 ; do { l2 = xen_intr_active_ports ( pc , s , l1i ) ; l2i = ( l2i + 1 ) % LONG_BIT ; masked_l2 = l2 & ( ( ~ 0UL ) << l2i ) ; if ( masked_l2 == 0 ) { l2i = LONG_BIT - 1 ; break ; } l2i = ffsl ( masked_l2 ) - 1 ; port = ( l1i * LONG_BIT ) + l2i ; synch_clear_bit ( port , & s -> evtchn_pending [ 0 ] ) ; isrc = xen_intr_port_to_isrc [ port ] ; if ( __predict_false ( isrc == NULL ) ) continue ; KASSERT ( ( isrc -> xi_cpu == PCPU_GET ( cpuid ) ) , ( " " , PCPU_GET ( cpuid ) , isrc -> xi_cpu ) ) ; intr_execute_handlers ( & isrc -> xi_intsrc , trap_frame ) ; pc -> last_processed_l1i = l1i ; pc -> last_processed_l2i = l2i ; } while ( l2i != LONG_BIT - 1 ) ; l2 = xen_intr_active_ports ( pc , s , l1i ) ; if ( l2 == 0 ) { l1 &= ~ ( 1UL << l1i ) ; } } critical_exit ( ) ; }
Interrupt handler for processing all Xen event channel events.
Interrupt handler for processing all Xen event channel events .
/*
	 * Disable preemption in order to always check and fire events
	 * on the right vCPU
	 */ /* No need for a barrier -- XCHG is a barrier on x86. */ /* Clear master flag /before/ clearing selector flag. */ /*
			 * if we masked out all events, wrap around
			 * to the beginning.
			 */ /* if we masked out all events, move on */ /* process port */ /* Make sure we are firing on the right vCPU */ /*
			 * If this is the final port processed,
			 * we'll pick up here+1 next time.
			 */ /*
			 * We handled all ports, so we can clear the
			 * selector bit.
			 */