Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/xen/bus/xen_intr.c
Show First 20 Lines • Show All 130 Lines • ▼ Show 20 Lines | |||||
static void xen_intr_disable_source(struct intsrc *isrc, int eoi); | static void xen_intr_disable_source(struct intsrc *isrc, int eoi); | ||||
static void xen_intr_eoi_source(struct intsrc *isrc); | static void xen_intr_eoi_source(struct intsrc *isrc); | ||||
static void xen_intr_enable_intr(struct intsrc *isrc); | static void xen_intr_enable_intr(struct intsrc *isrc); | ||||
static void xen_intr_disable_intr(struct intsrc *isrc); | static void xen_intr_disable_intr(struct intsrc *isrc); | ||||
static int xen_intr_vector(struct intsrc *isrc); | static int xen_intr_vector(struct intsrc *isrc); | ||||
static int xen_intr_source_pending(struct intsrc *isrc); | static int xen_intr_source_pending(struct intsrc *isrc); | ||||
static int xen_intr_config_intr(struct intsrc *isrc, | static int xen_intr_config_intr(struct intsrc *isrc, | ||||
enum intr_trigger trig, enum intr_polarity pol); | enum intr_trigger trig, enum intr_polarity pol); | ||||
static int xen_intr_assign_cpu(struct intsrc *isrc, u_int apic_id); | static int xen_intr_assign_cpu(struct intsrc *isrc, u_int to_cpu); | ||||
/** | /** | ||||
* PIC interface for all event channel port types except physical IRQs. | * PIC interface for all event channel port types except physical IRQs. | ||||
*/ | */ | ||||
struct pic xen_intr_pic = { | struct pic xen_intr_pic = { | ||||
.pic_enable_source = xen_intr_enable_source, | .pic_enable_source = xen_intr_enable_source, | ||||
.pic_disable_source = xen_intr_disable_source, | .pic_disable_source = xen_intr_disable_source, | ||||
.pic_eoi_source = xen_intr_eoi_source, | .pic_eoi_source = xen_intr_eoi_source, | ||||
▲ Show 20 Lines • Show All 533 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
} | } | ||||
static void | static void | ||||
xen_rebind_ipi(struct xenisrc *isrc) | xen_rebind_ipi(struct xenisrc *isrc) | ||||
{ | { | ||||
#ifdef SMP | #ifdef SMP | ||||
int cpu = isrc->xi_cpu; | int cpu = isrc->xi_cpu; | ||||
int vcpu_id = pcpu_find(cpu)->pc_vcpu_id; | u_int vcpu_id = XEN_CPUID_TO_VCPUID(cpu); | ||||
int error; | int error; | ||||
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; | ||||
#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; | u_int vcpu_id = XEN_CPUID_TO_VCPUID(cpu); | ||||
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); | ||||
Show All 21 Lines | default: | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
prev = xen_intr_port_to_isrc[isrc->xi_port]; | prev = xen_intr_port_to_isrc[isrc->xi_port]; | ||||
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; | isrc->xi_cpu = 0; | ||||
error = xen_intr_assign_cpu(&isrc->xi_intsrc, | error = xen_intr_assign_cpu(&isrc->xi_intsrc, cpu); | ||||
cpu_apic_ids[cpu]); | |||||
if (error) | if (error) | ||||
panic("%s(): unable to rebind Xen channel %u to vCPU%u: %d", | panic("%s(): unable to rebind Xen channel %u to vCPU%u: %d", | ||||
__func__, isrc->xi_port, cpu, error); | __func__, isrc->xi_port, cpu, error); | ||||
#endif | #endif | ||||
evtchn_unmask_port(isrc->xi_port); | evtchn_unmask_port(isrc->xi_port); | ||||
return (prev); | return (prev); | ||||
▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Lines | xen_intr_config_intr(struct intsrc *isrc, enum intr_trigger trig, | ||||
/* Configuration is only possible via the evtchn apis. */ | /* Configuration is only possible via the evtchn apis. */ | ||||
return (ENODEV); | return (ENODEV); | ||||
} | } | ||||
/** | /** | ||||
* Configure CPU affinity for interrupt source event delivery. | * Configure CPU affinity for interrupt source event delivery. | ||||
* | * | ||||
* \param isrc The interrupt source to configure. | * \param isrc The interrupt source to configure. | ||||
* \param apic_id The apic id of the CPU for handling future events. | * \param to_cpu The id of the CPU for handling future events. | ||||
* | * | ||||
* \returns 0 if successful, otherwise an errno. | * \returns 0 if successful, otherwise an errno. | ||||
*/ | */ | ||||
static int | static int | ||||
xen_intr_assign_cpu(struct intsrc *base_isrc, u_int apic_id) | xen_intr_assign_cpu(struct intsrc *base_isrc, u_int to_cpu) | ||||
royger: I'm afraid you cannot just change the parameter here from an apic_id into a cpuid, as this… | |||||
{ | { | ||||
#ifdef SMP | #ifdef SMP | ||||
struct evtchn_bind_vcpu bind_vcpu; | struct evtchn_bind_vcpu bind_vcpu; | ||||
struct xenisrc *isrc; | struct xenisrc *isrc; | ||||
u_int to_cpu, vcpu_id; | u_int vcpu_id = XEN_CPUID_TO_VCPUID(to_cpu); | ||||
int error, masked; | int error, masked; | ||||
if (!xen_has_percpu_evtchn()) | if (!xen_has_percpu_evtchn()) | ||||
return (EOPNOTSUPP); | return (EOPNOTSUPP); | ||||
to_cpu = apic_cpuid(apic_id); | |||||
vcpu_id = pcpu_find(to_cpu)->pc_vcpu_id; | |||||
mtx_lock(&xen_intr_isrc_lock); | mtx_lock(&xen_intr_isrc_lock); | ||||
isrc = (struct xenisrc *)base_isrc; | isrc = (struct xenisrc *)base_isrc; | ||||
if (!is_valid_evtchn(isrc->xi_port)) { | if (!is_valid_evtchn(isrc->xi_port)) { | ||||
mtx_unlock(&xen_intr_isrc_lock); | mtx_unlock(&xen_intr_isrc_lock); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 200 Lines • ▼ Show 20 Lines | xen_intr_bind_remote_port(device_t dev, u_int remote_domain, | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
xen_intr_bind_virq(device_t dev, u_int virq, u_int cpu, | xen_intr_bind_virq(device_t dev, u_int virq, u_int cpu, | ||||
driver_filter_t filter, driver_intr_t handler, void *arg, | driver_filter_t filter, driver_intr_t handler, void *arg, | ||||
enum intr_type flags, xen_intr_handle_t *port_handlep) | enum intr_type flags, xen_intr_handle_t *port_handlep) | ||||
{ | { | ||||
int vcpu_id = pcpu_find(cpu)->pc_vcpu_id; | u_int vcpu_id = XEN_CPUID_TO_VCPUID(cpu); | ||||
struct xenisrc *isrc; | struct xenisrc *isrc; | ||||
struct evtchn_bind_virq bind_virq = { .virq = virq, .vcpu = vcpu_id }; | struct evtchn_bind_virq bind_virq = { .virq = virq, .vcpu = vcpu_id }; | ||||
int error; | int error; | ||||
isrc = NULL; | isrc = NULL; | ||||
error = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &bind_virq); | error = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &bind_virq); | ||||
if (error != 0) { | if (error != 0) { | ||||
/* | /* | ||||
Show All 24 Lines | |||||
#ifdef SMP | #ifdef SMP | ||||
if (isrc->xi_cpu != cpu) { | if (isrc->xi_cpu != cpu) { | ||||
/* | /* | ||||
* Too early in the boot process for the generic interrupt | * Too early in the boot process for the generic interrupt | ||||
* code to perform the binding. Update our event channel | * code to perform the binding. Update our event channel | ||||
* masks manually so events can't fire on the wrong cpu | * masks manually so events can't fire on the wrong cpu | ||||
* during AP startup. | * during AP startup. | ||||
*/ | */ | ||||
xen_intr_assign_cpu(&isrc->xi_intsrc, cpu_apic_ids[cpu]); | xen_intr_assign_cpu(&isrc->xi_intsrc, cpu); | ||||
} | } | ||||
#endif | #endif | ||||
/* | /* | ||||
* The Event Channel API opened this port, so it is | * The Event Channel API opened this port, so it is | ||||
* responsible for closing it automatically on unbind. | * responsible for closing it automatically on unbind. | ||||
*/ | */ | ||||
isrc->xi_close = 1; | isrc->xi_close = 1; | ||||
isrc->xi_virq = virq; | isrc->xi_virq = virq; | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
xen_intr_alloc_and_bind_ipi(u_int cpu, driver_filter_t filter, | xen_intr_alloc_and_bind_ipi(u_int cpu, driver_filter_t filter, | ||||
enum intr_type flags, xen_intr_handle_t *port_handlep) | enum intr_type flags, xen_intr_handle_t *port_handlep) | ||||
{ | { | ||||
#ifdef SMP | #ifdef SMP | ||||
int vcpu_id = pcpu_find(cpu)->pc_vcpu_id; | u_int vcpu_id = XEN_CPUID_TO_VCPUID(cpu); | ||||
struct xenisrc *isrc; | struct xenisrc *isrc; | ||||
struct evtchn_bind_ipi bind_ipi = { .vcpu = vcpu_id }; | struct evtchn_bind_ipi bind_ipi = { .vcpu = vcpu_id }; | ||||
/* Same size as the one used by intr_handler->ih_name. */ | /* Same size as the one used by intr_handler->ih_name. */ | ||||
char name[MAXCOMLEN + 1]; | char name[MAXCOMLEN + 1]; | ||||
int error; | int error; | ||||
isrc = NULL; | isrc = NULL; | ||||
error = HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &bind_ipi); | error = HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &bind_ipi); | ||||
Show All 20 Lines | #ifdef SMP | ||||
if (isrc->xi_cpu != cpu) { | if (isrc->xi_cpu != cpu) { | ||||
/* | /* | ||||
* Too early in the boot process for the generic interrupt | * Too early in the boot process for the generic interrupt | ||||
* code to perform the binding. Update our event channel | * code to perform the binding. Update our event channel | ||||
* masks manually so events can't fire on the wrong cpu | * masks manually so events can't fire on the wrong cpu | ||||
* during AP startup. | * during AP startup. | ||||
*/ | */ | ||||
xen_intr_assign_cpu(&isrc->xi_intsrc, cpu_apic_ids[cpu]); | xen_intr_assign_cpu(&isrc->xi_intsrc, cpu); | ||||
} | } | ||||
/* | /* | ||||
* The Event Channel API opened this port, so it is | * The Event Channel API opened this port, so it is | ||||
* responsible for closing it automatically on unbind. | * responsible for closing it automatically on unbind. | ||||
*/ | */ | ||||
isrc->xi_close = 1; | isrc->xi_close = 1; | ||||
return (0); | return (0); | ||||
▲ Show 20 Lines • Show All 182 Lines • Show Last 20 Lines |
I'm afraid you cannot just change the parameter here from an apic_id into a cpuid, as this function is used by xen_intr_pic in order to fill the pic_assign_cpu hook, and that expects the second parameter of the hook to be an apic_id.