Changeset View
Changeset View
Standalone View
Standalone View
sys/x86/xen/xen_intr.c
Show First 20 Lines • Show All 672 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[isrc->xi_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; | ||||
isrc->xi_cpu = 0; | } | ||||
static void | |||||
xen_intr_rebind_isrc(struct xenisrc *isrc) | |||||
{ | |||||
#ifdef SMP | |||||
int cpu = isrc->xi_cpu; | |||||
const char *errfmt; | |||||
int error; | |||||
#endif | |||||
switch (isrc->xi_type) { | |||||
case EVTCHN_TYPE_IPI: | |||||
xen_rebind_ipi(isrc); | |||||
#ifdef SMP | |||||
errfmt = "%s: unable to bind xen IPI to CPU#%d: %d"; | |||||
#endif | |||||
break; | |||||
case EVTCHN_TYPE_VIRQ: | |||||
xen_rebind_virq(isrc); | |||||
#ifdef SMP | |||||
errfmt = "%1$s: unable to bind xen VIRQ#%4$d to CPU#%2$d: %3$d"; | |||||
#endif | |||||
break; | |||||
default: | |||||
return; | |||||
} | |||||
xen_intr_port_to_isrc[isrc->xi_port] = isrc; | xen_intr_port_to_isrc[isrc->xi_port] = isrc; | ||||
#ifdef SMP | #ifdef SMP | ||||
isrc->xi_cpu = 0; | |||||
error = xen_intr_assign_cpu(&isrc->xi_intsrc, | error = xen_intr_assign_cpu(&isrc->xi_intsrc, | ||||
cpu_apic_ids[cpu]); | cpu_apic_ids[cpu]); | ||||
ehem_freebsd_m5p.com: Based on what I saw in D32866, I //suspect// there //should// be a `intr_event_bind()` here. | |||||
if (error) | if (error) | ||||
panic("unable to bind xen VIRQ#%d to CPU#%d: %d", | panic(errfmt, __func__, cpu, error, isrc->xi_virq); | ||||
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 24 Lines | xen_intr_resume(struct pic *unused, bool suspend_cancelled) | ||||
/* 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; | isrc->xi_port = ~0; | ||||
switch (isrc->xi_type) { | xen_intr_rebind_isrc(isrc); | ||||
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 588 Lines • Show Last 20 Lines |
Based on what I saw in D32866, I suspect there should be a intr_event_bind() here.