svn commit: r275678 - head/sys/x86/xen
Roger Pau Monné
royger at FreeBSD.org
Wed Dec 10 11:42:03 UTC 2014
Author: royger
Date: Wed Dec 10 11:42:02 2014
New Revision: 275678
URL: https://svnweb.freebsd.org/changeset/base/275678
Log:
xen: mask event channels while binding them to a vCPU
Mask the event channel source before trying to bind it to a CPU, this
prevents stray interrupts from firing while assigning them and hitting the
KASSERT in xen_intr_handle_upcall.
Sponsored by: Citrix Systems R&D
Modified:
head/sys/x86/xen/xen_intr.c
Modified: head/sys/x86/xen/xen_intr.c
==============================================================================
--- head/sys/x86/xen/xen_intr.c Wed Dec 10 11:35:41 2014 (r275677)
+++ head/sys/x86/xen/xen_intr.c Wed Dec 10 11:42:02 2014 (r275678)
@@ -851,7 +851,7 @@ xen_intr_assign_cpu(struct intsrc *base_
struct evtchn_bind_vcpu bind_vcpu;
struct xenisrc *isrc;
u_int to_cpu, vcpu_id;
- int error;
+ int error, masked;
#ifdef XENHVM
if (xen_vector_callback_enabled == 0)
@@ -869,6 +869,11 @@ xen_intr_assign_cpu(struct intsrc *base_
return (EINVAL);
}
+ /*
+ * Mask the event channel while binding it to prevent interrupt
+ * delivery with an inconsistent state in isrc->xi_cpu.
+ */
+ masked = evtchn_test_and_set_mask(isrc->xi_port);
if ((isrc->xi_type == EVTCHN_TYPE_VIRQ) ||
(isrc->xi_type == EVTCHN_TYPE_IPI)) {
/*
@@ -879,29 +884,25 @@ xen_intr_assign_cpu(struct intsrc *base_
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);
- mtx_unlock(&xen_intr_isrc_lock);
- return (0);
+ goto out;
}
bind_vcpu.port = isrc->xi_port;
bind_vcpu.vcpu = vcpu_id;
- /*
- * Allow interrupts to be fielded on the new VCPU before
- * we ask the hypervisor to deliver them there.
- */
- evtchn_cpu_unmask_port(to_cpu, isrc->xi_port);
error = HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu);
if (isrc->xi_cpu != to_cpu) {
if (error == 0) {
/* Commit to new binding by removing the old one. */
evtchn_cpu_mask_port(isrc->xi_cpu, isrc->xi_port);
isrc->xi_cpu = to_cpu;
- } else {
- /* Roll-back to previous binding. */
- evtchn_cpu_mask_port(to_cpu, isrc->xi_port);
+ 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
More information about the svn-src-head
mailing list