Date: Wed, 10 Dec 2014 11:42:02 +0000 (UTC) From: Roger Pau Monné <royger@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r275678 - head/sys/x86/xen Message-ID: <201412101142.sBABg2Id031091@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201412101142.sBABg2Id031091>