|
@@ -47,23 +47,18 @@ static void xen_restore_fl(unsigned long flags)
|
|
|
/* convert from IF type flag */
|
|
|
flags = !(flags & X86_EFLAGS_IF);
|
|
|
|
|
|
- /* There's a one instruction preempt window here. We need to
|
|
|
- make sure we're don't switch CPUs between getting the vcpu
|
|
|
- pointer and updating the mask. */
|
|
|
+ /* See xen_irq_enable() for why preemption must be disabled. */
|
|
|
preempt_disable();
|
|
|
vcpu = this_cpu_read(xen_vcpu);
|
|
|
vcpu->evtchn_upcall_mask = flags;
|
|
|
- preempt_enable_no_resched();
|
|
|
-
|
|
|
- /* Doesn't matter if we get preempted here, because any
|
|
|
- pending event will get dealt with anyway. */
|
|
|
|
|
|
if (flags == 0) {
|
|
|
- preempt_check_resched();
|
|
|
barrier(); /* unmask then check (avoid races) */
|
|
|
if (unlikely(vcpu->evtchn_upcall_pending))
|
|
|
xen_force_evtchn_callback();
|
|
|
- }
|
|
|
+ preempt_enable();
|
|
|
+ } else
|
|
|
+ preempt_enable_no_resched();
|
|
|
}
|
|
|
PV_CALLEE_SAVE_REGS_THUNK(xen_restore_fl);
|
|
|
|
|
@@ -82,10 +77,12 @@ static void xen_irq_enable(void)
|
|
|
{
|
|
|
struct vcpu_info *vcpu;
|
|
|
|
|
|
- /* We don't need to worry about being preempted here, since
|
|
|
- either a) interrupts are disabled, so no preemption, or b)
|
|
|
- the caller is confused and is trying to re-enable interrupts
|
|
|
- on an indeterminate processor. */
|
|
|
+ /*
|
|
|
+ * We may be preempted as soon as vcpu->evtchn_upcall_mask is
|
|
|
+ * cleared, so disable preemption to ensure we check for
|
|
|
+ * events on the VCPU we are still running on.
|
|
|
+ */
|
|
|
+ preempt_disable();
|
|
|
|
|
|
vcpu = this_cpu_read(xen_vcpu);
|
|
|
vcpu->evtchn_upcall_mask = 0;
|
|
@@ -96,6 +93,8 @@ static void xen_irq_enable(void)
|
|
|
barrier(); /* unmask then check (avoid races) */
|
|
|
if (unlikely(vcpu->evtchn_upcall_pending))
|
|
|
xen_force_evtchn_callback();
|
|
|
+
|
|
|
+ preempt_enable();
|
|
|
}
|
|
|
PV_CALLEE_SAVE_REGS_THUNK(xen_irq_enable);
|
|
|
|