Changeset View
Changeset View
Standalone View
Standalone View
sys/xen/xen_intr.c
Show First 20 Lines • Show All 681 Lines • ▼ Show 20 Lines | #ifdef SMP | ||||
struct evtchn_bind_ipi bind_ipi = { .vcpu = vcpu_id }; | struct evtchn_bind_ipi bind_ipi = { .vcpu = vcpu_id }; | ||||
error = HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, | error = HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, | ||||
&bind_ipi); | &bind_ipi); | ||||
if (error != 0) | if (error != 0) | ||||
panic("unable to rebind xen IPI: %d", error); | panic("unable to rebind xen IPI: %d", error); | ||||
isrc->xi_port = bind_ipi.port; | isrc->xi_port = bind_ipi.port; | ||||
isrc->xi_cpu = 0; | |||||
xen_intr_port_to_isrc[bind_ipi.port] = isrc; | |||||
error = xen_intr_assign_cpu(&isrc->xi_intsrc, | |||||
cpu_apic_ids[cpu]); | |||||
if (error) | |||||
panic("unable to bind xen IPI to CPU#%d: %d", | |||||
cpu, error); | |||||
evtchn_unmask_port(bind_ipi.port); | |||||
#else | #else | ||||
panic("Resume IPI event channel on UP"); | panic("Resume IPI event channel on UP"); | ||||
#endif | #endif | ||||
} | } | ||||
static void | static void | ||||
xen_rebind_virq(struct xenisrc *isrc) | xen_rebind_virq(struct xenisrc *isrc) | ||||
{ | { | ||||
int cpu = isrc->xi_cpu; | int cpu = isrc->xi_cpu; | ||||
int vcpu_id = pcpu_find(cpu)->pc_vcpu_id; | int vcpu_id = pcpu_find(cpu)->pc_vcpu_id; | ||||
int error; | int error; | ||||
struct evtchn_bind_virq bind_virq = { .virq = isrc->xi_virq, | struct evtchn_bind_virq bind_virq = { .virq = isrc->xi_virq, | ||||
.vcpu = vcpu_id }; | .vcpu = vcpu_id }; | ||||
error = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, | error = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, | ||||
&bind_virq); | &bind_virq); | ||||
if (error != 0) | if (error != 0) | ||||
panic("unable to rebind xen VIRQ#%d: %d", isrc->xi_virq, error); | panic("unable to rebind xen VIRQ#%d: %d", isrc->xi_virq, error); | ||||
isrc->xi_port = bind_virq.port; | isrc->xi_port = bind_virq.port; | ||||
} | |||||
static void | |||||
xen_intr_rebind_isrc(struct xenisrc *isrc) | |||||
{ | |||||
int cpu = isrc->xi_cpu; | |||||
int error; | |||||
isrc->xi_port = 0; | |||||
switch (isrc->xi_type) { | |||||
case EVTCHN_TYPE_IPI: | |||||
xen_rebind_ipi(isrc); | |||||
break; | |||||
case EVTCHN_TYPE_VIRQ: | |||||
xen_rebind_virq(isrc); | |||||
break; | |||||
default: | |||||
return; | |||||
} | |||||
isrc->xi_cpu = 0; | isrc->xi_cpu = 0; | ||||
xen_intr_port_to_isrc[bind_virq.port] = isrc; | xen_intr_port_to_isrc[isrc->xi_port] = isrc; | ||||
#ifdef SMP | #ifdef SMP | ||||
error = xen_intr_assign_cpu(&isrc->xi_intsrc, | error = xen_intr_assign_cpu(&isrc->xi_intsrc, | ||||
cpu_apic_ids[cpu]); | cpu_apic_ids[cpu]); | ||||
if (error) | if (error) | ||||
panic("unable to bind xen VIRQ#%d to CPU#%d: %d", | panic("unable to bind xen intr#%d to CPU#%d: %d", | ||||
isrc->xi_virq, cpu, error); | isrc->xi_virq, cpu, error); | ||||
#endif | #endif | ||||
evtchn_unmask_port(bind_virq.port); | evtchn_unmask_port(isrc->xi_port); | ||||
} | } | ||||
/** | /** | ||||
* Return this PIC to service after being suspended. | * Return this PIC to service after being suspended. | ||||
*/ | */ | ||||
static void | static void | ||||
xen_intr_resume(struct pic *unused, bool suspend_cancelled) | xen_intr_resume(struct pic *unused, bool suspend_cancelled) | ||||
{ | { | ||||
Show All 22 Lines | xen_intr_resume(struct pic *unused, bool suspend_cancelled) | ||||
memset(xen_intr_port_to_isrc, 0, sizeof(xen_intr_port_to_isrc)); | memset(xen_intr_port_to_isrc, 0, sizeof(xen_intr_port_to_isrc)); | ||||
/* Free unused isrcs and rebind VIRQs and IPIs */ | /* Free unused isrcs and rebind VIRQs and IPIs */ | ||||
for (isrc_idx = 0; isrc_idx < xen_intr_auto_vector_count; isrc_idx++) { | for (isrc_idx = 0; isrc_idx < xen_intr_auto_vector_count; isrc_idx++) { | ||||
u_int vector; | u_int vector; | ||||
vector = first_evtchn_irq + isrc_idx; | vector = first_evtchn_irq + isrc_idx; | ||||
isrc = (struct xenisrc *)intr_lookup_source(vector); | isrc = (struct xenisrc *)intr_lookup_source(vector); | ||||
if (isrc != NULL) { | if (isrc != NULL) | ||||
isrc->xi_port = 0; | xen_intr_rebind_isrc(isrc); | ||||
switch (isrc->xi_type) { | |||||
case EVTCHN_TYPE_IPI: | |||||
xen_rebind_ipi(isrc); | |||||
break; | |||||
case EVTCHN_TYPE_VIRQ: | |||||
xen_rebind_virq(isrc); | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Disable a Xen interrupt source. | * Disable a Xen interrupt source. | ||||
* | * | ||||
* \param isrc The interrupt source to disable. | * \param isrc The interrupt source to disable. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 586 Lines • Show Last 20 Lines |