[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH] Use EVTCHNOP_unmask to unmask in some cases
If the EVTCHN Unmask method is called in context of the event channel upcall, or on a CPU to which the event is not bound then use the unmask hypercall. In the former case not doing this may lead to priorty inversion once setting event channel priorities is enabled. In the latter case not doing it again stops a lower priority event handler trigger from blocking a higher priority event injection. Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> --- include/xen.h | 7 ++++++ src/xen/event_channel.c | 28 ++++++++++++++++++++++++ src/xenbus/evtchn.c | 56 +++++++++++++++++++++++++++++------------------- src/xenbus/evtchn_fifo.c | 5 +---- src/xenbus/shared_info.c | 5 +---- 5 files changed, 71 insertions(+), 30 deletions(-) diff --git a/include/xen.h b/include/xen.h index 84197a5..fa95edd 100644 --- a/include/xen.h +++ b/include/xen.h @@ -212,6 +212,13 @@ EventChannelBindVirtualCpu( IN unsigned int vcpu_id ); +__checkReturn +XEN_API +NTSTATUS +EventChannelUnmask( + IN ULONG LocalPort + ); + // GRANT TABLE __checkReturn diff --git a/src/xen/event_channel.c b/src/xen/event_channel.c index 94a6b82..aa9fb48 100644 --- a/src/xen/event_channel.c +++ b/src/xen/event_channel.c @@ -357,3 +357,31 @@ fail1: return status; } + +__checkReturn +XEN_API +NTSTATUS +EventChannelUnmask( + IN ULONG LocalPort + ) +{ + struct evtchn_unmask op; + LONG_PTR rc; + NTSTATUS status; + + op.port = LocalPort; + + rc = EventChannelOp(EVTCHNOP_unmask, &op); + + if (rc < 0) { + ERRNO_TO_STATUS(-rc, status); + goto fail1; + } + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c index c6ac30d..f88c208 100644 --- a/src/xenbus/evtchn.c +++ b/src/xenbus/evtchn.c @@ -624,60 +624,72 @@ static BOOLEAN EvtchnUnmask( IN PINTERFACE Interface, IN PXENBUS_EVTCHN_CHANNEL Channel, - IN BOOLEAN InCallback + IN BOOLEAN InUpcall ) { PXENBUS_EVTCHN_CONTEXT Context = Interface->Context; KIRQL Irql = PASSIVE_LEVEL; - BOOLEAN Pending = FALSE; + BOOLEAN Pending; + ULONG LocalPort; ULONG Cpu; - PXENBUS_INTERRUPT Interrupt; ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC); - if (!InCallback) + if (!InUpcall) KeAcquireSpinLock(&Channel->Lock, &Irql); ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL); + Pending = FALSE; + if (!Channel->Active) goto done; + LocalPort = Channel->LocalPort; + Pending = XENBUS_EVTCHN_ABI(PortUnmask, &Context->EvtchnAbi, - Channel->LocalPort); + LocalPort); if (!Pending) goto done; - if (InCallback) - goto mask; - - ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL); - Cpu = KeGetCurrentProcessorNumber(); - - Interrupt = Context->LatchedInterrupt[Cpu]; + // + // If we are in context of the upcall then use a hypercall + // to schedule the pending event. + // + if (InUpcall) { + (VOID) EventChannelUnmask(LocalPort); - if (Channel->Interrupt == Interrupt) - goto mask; + Pending = FALSE; + goto done; + } // - // We are not on the CPU to which the event is bound so - // we must trigger. + // If we are not unmasking on the same CPU to which the + // event channel is bound, then we need to use a hypercall + // to schedule the upcall on the correct CPU. // - EvtchnTrigger(Interface, Channel); + Cpu = KeGetCurrentProcessorNumber(); - Pending = FALSE; - goto done; + if (Channel->Cpu != Cpu) { + (VOID) EventChannelUnmask(LocalPort); + + Pending = FALSE; + goto done; + } -mask: if (Channel->Mask) XENBUS_EVTCHN_ABI(PortMask, &Context->EvtchnAbi, - Channel->LocalPort); + LocalPort); + + XENBUS_EVTCHN_ABI(PortAck, + &Context->EvtchnAbi, + LocalPort); done: - if (!InCallback) + if (!InUpcall) KeReleaseSpinLock(&Channel->Lock, Irql); return Pending; diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c index f65cc1b..e045cd0 100644 --- a/src/xenbus/evtchn_fifo.c +++ b/src/xenbus/evtchn_fifo.c @@ -437,10 +437,7 @@ EvtchnFifoPortUnmask( return FALSE; // If we cleared the mask then check whether something is pending - if (!__EvtchnFifoTestAndClearFlag(EventWord, EVTCHN_FIFO_PENDING)) - return FALSE; - - return TRUE; + return __EvtchnFifoTestFlag(EventWord, EVTCHN_FIFO_PENDING); } static VOID diff --git a/src/xenbus/shared_info.c b/src/xenbus/shared_info.c index 67be20c..240d87b 100644 --- a/src/xenbus/shared_info.c +++ b/src/xenbus/shared_info.c @@ -316,10 +316,7 @@ SharedInfoEvtchnUnmask( KeMemoryBarrier(); // If we cleared the mask then check whether something was pending - if (!SharedInfoClearBit(&Shared->evtchn_pending[SelectorBit], PortBit)) - return FALSE; - - return TRUE; + return SharedInfoTestBit(&Shared->evtchn_pending[SelectorBit], PortBit); } static LARGE_INTEGER -- 2.1.1 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |