[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [win-pv-devel] [PATCH 10/10] Add support for the FIFO event channel ABI
> -----Original Message----- > From: Paul Durrant [mailto:paul.durrant@xxxxxxxxxx] > Sent: 06 November 2014 14:31 > To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx > Cc: Paul Durrant > Subject: [PATCH 10/10] Add support for the FIFO event channel ABI > > If it is available then the fifo ABI will be used. If it is not then the > two-level ABI will be used instead. > The ABI is released and re-acquired across suspend/resume so this should > allow moving between hosts with different capabilities. > > Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> Cc-ing David Vrabel for review. Paul > --- > include/xen.h | 41 ++- > src/xen/event_channel.c | 128 ++++++++ > src/xenbus/evtchn.c | 27 +- > src/xenbus/evtchn_fifo.c | 702 > +++++++++++++++++++++++++++++++++++++++++++ > src/xenbus/evtchn_fifo.h | 59 ++++ > src/xenbus/store.c | 11 +- > vs2012/xenbus/xenbus.vcxproj | 1 + > vs2013/xenbus/xenbus.vcxproj | 1 + > 8 files changed, 962 insertions(+), 8 deletions(-) > create mode 100644 src/xenbus/evtchn_fifo.c > create mode 100644 src/xenbus/evtchn_fifo.h > > diff --git a/include/xen.h b/include/xen.h > index 674676c..0039d7a 100644 > --- a/include/xen.h > +++ b/include/xen.h > @@ -136,17 +136,26 @@ __checkReturn > XEN_API > NTSTATUS > EventChannelBindInterDomain( > - IN domid_t RemoteDomain, > - IN evtchn_port_t RemotePort, > - OUT evtchn_port_t *LocalPort > + IN domid_t RemoteDomain, > + IN evtchn_port_t RemotePort, > + OUT evtchn_port_t *LocalPort > ); > > __checkReturn > XEN_API > NTSTATUS > EventChannelBindVirq( > - IN uint32_t Virq, > - OUT evtchn_port_t *LocalPort > + IN uint32_t Virq, > + OUT evtchn_port_t *LocalPort > + ); > + > +__checkReturn > +XEN_API > +NTSTATUS > +EventChannelQueryInterDomain( > + IN evtchn_port_t LocalPort, > + OUT domid_t *RemoteDomain, > + OUT evtchn_port_t *RemotePort > ); > > __checkReturn > @@ -156,6 +165,28 @@ EventChannelClose( > IN evtchn_port_t LocalPort > ); > > +__checkReturn > +XEN_API > +NTSTATUS > +EventChannelExpandArray( > + IN PFN_NUMBER Pfn > + ); > + > +__checkReturn > +XEN_API > +NTSTATUS > +EventChannelInitControl( > + IN PFN_NUMBER Pfn, > + IN unsigned int vcpu_id > + ); > + > +__checkReturn > +XEN_API > +NTSTATUS > +EventChannelReset( > + VOID > + ); > + > // GRANT TABLE > > __checkReturn > diff --git a/src/xen/event_channel.c b/src/xen/event_channel.c > index 23e4659..aa87fd4 100644 > --- a/src/xen/event_channel.c > +++ b/src/xen/event_channel.c > @@ -175,6 +175,47 @@ fail1: > __checkReturn > XEN_API > NTSTATUS > +EventChannelQueryInterDomain( > + IN evtchn_port_t LocalPort, > + OUT domid_t *RemoteDomain, > + OUT evtchn_port_t *RemotePort > + ) > +{ > + struct evtchn_status op; > + LONG_PTR rc; > + NTSTATUS status; > + > + op.dom = DOMID_SELF; > + op.port = LocalPort; > + > + rc = EventChannelOp(EVTCHNOP_status, &op); > + > + if (rc < 0) { > + ERRNO_TO_STATUS(-rc, status); > + goto fail1; > + } > + > + status = STATUS_INVALID_PARAMETER; > + if (op.status != EVTCHNSTAT_interdomain) > + goto fail2; > + > + *RemoteDomain = op.u.interdomain.dom; > + *RemotePort = op.u.interdomain.port; > + > + return STATUS_SUCCESS; > + > +fail2: > + Error("fail2\n"); > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + return status; > +} > + > +__checkReturn > +XEN_API > +NTSTATUS > EventChannelClose( > IN evtchn_port_t LocalPort > ) > @@ -199,3 +240,90 @@ fail1: > > return status; > } > + > +__checkReturn > +XEN_API > +NTSTATUS > +EventChannelExpandArray( > + IN PFN_NUMBER Pfn > + ) > +{ > + struct evtchn_expand_array op; > + LONG_PTR rc; > + NTSTATUS status; > + > + op.array_gfn = Pfn; > + > + rc = EventChannelOp(EVTCHNOP_expand_array, &op); > + > + if (rc < 0) { > + ERRNO_TO_STATUS(-rc, status); > + goto fail1; > + } > + > + return STATUS_SUCCESS; > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + return status; > +} > + > +__checkReturn > +XEN_API > +NTSTATUS > +EventChannelInitControl( > + IN PFN_NUMBER Pfn, > + IN unsigned int vcpu_id > + ) > +{ > + struct evtchn_init_control op; > + LONG_PTR rc; > + NTSTATUS status; > + > + op.control_gfn = Pfn; > + op.offset = 0; > + op.vcpu = vcpu_id; > + > + rc = EventChannelOp(EVTCHNOP_init_control, &op); > + > + if (rc < 0) { > + ERRNO_TO_STATUS(-rc, status); > + goto fail1; > + } > + > + return STATUS_SUCCESS; > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + return status; > +} > + > +__checkReturn > +XEN_API > +NTSTATUS > +EventChannelReset( > + VOID > + ) > +{ > + struct evtchn_reset op; > + LONG_PTR rc; > + NTSTATUS status; > + > + op.dom = DOMID_SELF; > + > + rc = EventChannelOp(EVTCHNOP_reset, &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 f13667e..2be0da8 100644 > --- a/src/xenbus/evtchn.c > +++ b/src/xenbus/evtchn.c > @@ -36,6 +36,7 @@ > > #include "evtchn.h" > #include "evtchn_2l.h" > +#include "evtchn_fifo.h" > #include "fdo.h" > #include "hash_table.h" > #include "dbg_print.h" > @@ -95,6 +96,7 @@ struct _XENBUS_EVTCHN_CONTEXT { > PXENBUS_DEBUG_CALLBACK DebugCallback; > XENBUS_SHARED_INFO_INTERFACE SharedInfoInterface; > PXENBUS_EVTCHN_ABI_CONTEXT EvtchnTwoLevelContext; > + PXENBUS_EVTCHN_ABI_CONTEXT EvtchnFifoContext; > XENBUS_EVTCHN_ABI EvtchnAbi; > PXENBUS_HASH_TABLE Table; > LIST_ENTRY List; > @@ -234,7 +236,9 @@ EvtchnOpenInterDomain( > RemotePort = va_arg(Arguments, ULONG); > Mask = va_arg(Arguments, BOOLEAN); > > - status = EventChannelBindInterDomain(RemoteDomain, RemotePort, > &LocalPort); > + status = EventChannelBindInterDomain(RemoteDomain, > + RemotePort, > + &LocalPort); > if (!NT_SUCCESS(status)) > goto fail1; > > @@ -666,6 +670,13 @@ EvtchnAbiAcquire( > { > NTSTATUS status; > > + EvtchnFifoGetAbi(Context->EvtchnFifoContext, > + &Context->EvtchnAbi); > + > + status = XENBUS_EVTCHN_ABI(Acquire, &Context->EvtchnAbi); > + if (NT_SUCCESS(status)) > + goto done; > + > EvtchnTwoLevelGetAbi(Context->EvtchnTwoLevelContext, > &Context->EvtchnAbi); > > @@ -673,6 +684,7 @@ EvtchnAbiAcquire( > if (!NT_SUCCESS(status)) > goto fail1; > > +done: > return STATUS_SUCCESS; > > fail1: > @@ -1024,6 +1036,10 @@ EvtchnInitialize( > if (!NT_SUCCESS(status)) > goto fail3; > > + status = EvtchnFifoInitialize(Fdo, &(*Context)->EvtchnFifoContext); > + if (!NT_SUCCESS(status)) > + goto fail4; > + > status = SuspendGetInterface(FdoGetSuspendContext(Fdo), > XENBUS_SUSPEND_INTERFACE_VERSION_MAX, > (PINTERFACE)&(*Context)->SuspendInterface, > @@ -1054,6 +1070,12 @@ EvtchnInitialize( > > return STATUS_SUCCESS; > > +fail4: > + Error("fail4\n"); > + > + EvtchnTwoLevelTeardown((*Context)->EvtchnTwoLevelContext); > + (*Context)->EvtchnTwoLevelContext = NULL; > + > fail3: > Error("fail3\n"); > > @@ -1131,6 +1153,9 @@ EvtchnTeardown( > RtlZeroMemory(&Context->SuspendInterface, > sizeof (XENBUS_SUSPEND_INTERFACE)); > > + EvtchnFifoTeardown(Context->EvtchnFifoContext); > + Context->EvtchnFifoContext = NULL; > + > EvtchnTwoLevelTeardown(Context->EvtchnTwoLevelContext); > Context->EvtchnTwoLevelContext = NULL; > > diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c > new file mode 100644 > index 0000000..d37b1cd > --- /dev/null > +++ b/src/xenbus/evtchn_fifo.c > @@ -0,0 +1,702 @@ > +/* Copyright (c) Citrix Systems Inc. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, > + * with or without modification, are permitted provided > + * that the following conditions are met: > + * > + * * Redistributions of source code must retain the above > + * copyright notice, this list of conditions and the > + * following disclaimer. > + * * Redistributions in binary form must reproduce the above > + * copyright notice, this list of conditions and the > + * following disclaimer in the documentation and/or other > + * materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, > + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR > + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, > + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR > + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, > + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING > + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + */ > + > +#include <ntddk.h> > +#include <stdarg.h> > +#include <xen.h> > +#include <util.h> > + > +#include "evtchn_fifo.h" > +#include "shared_info.h" > +#include "fdo.h" > +#include "dbg_print.h" > +#include "assert.h" > + > +#define MAX_HVM_VCPUS 128 > + > +typedef struct _XENBUS_EVTCHN_FIFO_CONTEXT { > + PXENBUS_FDO Fdo; > + KSPIN_LOCK Lock; > + LONG References; > + PMDL ControlBlockMdl[MAX_HVM_VCPUS]; > + PMDL *EventPageMdl; > + ULONG EventPageCount; > + ULONG Head[EVTCHN_FIFO_MAX_QUEUES]; > +} XENBUS_EVTCHN_FIFO_CONTEXT, *PXENBUS_EVTCHN_FIFO_CONTEXT; > + > +#define EVENT_WORDS_PER_PAGE (PAGE_SIZE / sizeof (event_word_t)) > + > +#define XENBUS_EVTCHN_FIFO_TAG 'OFIF' > + > +static FORCEINLINE PVOID > +__EvtchnFifoAllocate( > + IN ULONG Length > + ) > +{ > + return __AllocatePoolWithTag(NonPagedPool, Length, > XENBUS_EVTCHN_FIFO_TAG); > +} > + > +static FORCEINLINE VOID > +__EvtchnFifoFree( > + IN PVOID Buffer > + ) > +{ > + ExFreePoolWithTag(Buffer, XENBUS_EVTCHN_FIFO_TAG); > +} > + > +static event_word_t * > +EvtchnFifoEventWord( > + IN PXENBUS_EVTCHN_FIFO_CONTEXT Context, > + IN ULONG Port > + ) > +{ > + ULONG Index; > + PMDL Mdl; > + event_word_t *EventWord; > + > + Index = Port / EVENT_WORDS_PER_PAGE; > + ASSERT3U(Index, <, Context->EventPageCount); > + > + Mdl = Context->EventPageMdl[Index]; > + > + EventWord = MmGetSystemAddressForMdlSafe(Mdl, > NormalPagePriority); > + ASSERT(EventWord != NULL); > + > + ASSERT3U(Port, >=, Index * EVENT_WORDS_PER_PAGE); > + Port -= Index * EVENT_WORDS_PER_PAGE; > + > + return &EventWord[Port]; > +} > + > +static FORCEINLINE BOOLEAN > +__EvtchnFifoTestFlag( > + IN event_word_t *EventWord, > + IN ULONG Flag > + ) > +{ > + KeMemoryBarrier(); > + > + return !!(*EventWord & (1 << Flag)); > +} > + > +static FORCEINLINE BOOLEAN > +__EvtchnFifoTestAndSetFlag( > + IN event_word_t *EventWord, > + IN ULONG Flag > + ) > +{ > + KeMemoryBarrier(); > + > + return !!InterlockedBitTestAndSet((LONG *)EventWord, Flag); > +} > + > +static FORCEINLINE BOOLEAN > +__EvtchnFifoTestAndClearFlag( > + IN event_word_t *EventWord, > + IN ULONG Flag > + ) > +{ > + KeMemoryBarrier(); > + > + return !!InterlockedBitTestAndReset((LONG *)EventWord, Flag); > +} > + > +static FORCEINLINE VOID > +__EvtchnFifoSetFlag( > + IN event_word_t *EventWord, > + IN ULONG Flag > + ) > +{ > + *EventWord |= (1 << Flag); > + KeMemoryBarrier(); > +} > + > +static FORCEINLINE VOID > +__EvtchnFifoClearFlag( > + IN event_word_t *EventWord, > + IN ULONG Flag > + ) > +{ > + *EventWord &= ~(1 << Flag); > + KeMemoryBarrier(); > +} > + > +static FORCEINLINE ULONG > +__EvtchnFifoUnlink( > + IN event_word_t *EventWord > + ) > +{ > + LONG Old; > + LONG New; > + > + do { > + Old = *EventWord; > + > + // Clear linked bit and link value > + New = Old & ~((1 << EVTCHN_FIFO_LINKED) | > EVTCHN_FIFO_LINK_MASK); > + } while (InterlockedCompareExchange((LONG *)EventWord, New, Old) != > Old); > + > + return Old & EVTCHN_FIFO_LINK_MASK; > +} > + > +static NTSTATUS > +EvtchnFifoExpand( > + IN PXENBUS_EVTCHN_FIFO_CONTEXT Context, > + IN ULONG Port > + ) > +{ > + LONG Index; > + ULONG EventPageCount; > + PMDL *EventPageMdl; > + PMDL Mdl; > + ULONG Start; > + ULONG End; > + NTSTATUS status; > + > + Index = Port / EVENT_WORDS_PER_PAGE; > + ASSERT3U(Index, >=, (LONG)Context->EventPageCount); > + > + EventPageCount = Index + 1; > + EventPageMdl = __EvtchnFifoAllocate(sizeof (PMDL) * EventPageCount); > + > + status = STATUS_NO_MEMORY; > + if (EventPageMdl == NULL) > + goto fail1; > + > + for (Index = 0; Index < (LONG)Context->EventPageCount; Index++) > + EventPageMdl[Index] = Context->EventPageMdl[Index]; > + > + Index = Context->EventPageCount; > + while (Index < (LONG)EventPageCount) { > + event_word_t *EventWord; > + PFN_NUMBER Pfn; > + PHYSICAL_ADDRESS Address; > + > + Mdl = __AllocatePage(); > + > + status = STATUS_NO_MEMORY; > + if (Mdl == NULL) > + goto fail2; > + > + EventWord = MmGetSystemAddressForMdlSafe(Mdl, > NormalPagePriority); > + ASSERT(EventWord != NULL); > + > + for (Port = 0; Port < EVENT_WORDS_PER_PAGE; Port++) > + __EvtchnFifoSetFlag(&EventWord[Port], EVTCHN_FIFO_MASKED); > + > + Pfn = MmGetMdlPfnArray(Mdl)[0]; > + > + status = EventChannelExpandArray(Pfn); > + if (!NT_SUCCESS(status)) > + goto fail3; > + > + Address.QuadPart = (ULONGLONG)Pfn << PAGE_SHIFT; > + > + LogPrintf(LOG_LEVEL_INFO, > + "EVTCHN_FIFO: EVENTARRAY[%u] @ %08x.%08x\n", > + Index, > + Address.HighPart, > + Address.LowPart); > + > + EventPageMdl[Index++] = Mdl; > + } > + > + Start = Context->EventPageCount * EVENT_WORDS_PER_PAGE; > + End = (EventPageCount * EVENT_WORDS_PER_PAGE) - 1; > + > + Info("added ports [%08x - %08x]\n", Start, End); > + > + if (Context->EventPageMdl != NULL) > + __EvtchnFifoFree(Context->EventPageMdl); > + > + Context->EventPageMdl = EventPageMdl; > + Context->EventPageCount = EventPageCount; > + > + return STATUS_SUCCESS; > + > +fail3: > + Error("fail3\n"); > + > + __FreePage(Mdl); > + > +fail2: > + Error("fail2\n"); > + > + while (--Index >= (LONG)Context->EventPageCount) { > + Mdl = EventPageMdl[Index]; > + > + __FreePage(Mdl); > + } > + > + __EvtchnFifoFree(EventPageMdl); > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + return status; > +} > + > +static VOID > +EvtchnFifoContract( > + IN PXENBUS_EVTCHN_FIFO_CONTEXT Context > + ) > +{ > + LONG Index; > + > + Index = Context->EventPageCount; > + while (--Index >= 0) { > + PMDL Mdl; > + > + Mdl = Context->EventPageMdl[Index]; > + > + __FreePage(Mdl); > + } > + > + __EvtchnFifoFree(Context->EventPageMdl); > + > + Context->EventPageMdl = NULL; > + Context->EventPageCount = 0; > +} > + > +static BOOLEAN > +EvtchnFifoPollPriority( > + IN PXENBUS_EVTCHN_FIFO_CONTEXT Context, > + IN evtchn_fifo_control_block_t *ControlBlock, > + IN ULONG Priority, > + IN PULONG Ready, > + IN XENBUS_EVTCHN_ABI_EVENT Event, > + IN PVOID Argument > + ) > +{ > + ULONG Head; > + ULONG Port; > + event_word_t *EventWord; > + BOOLEAN DoneSomething; > + > + Head = Context->Head[Priority]; > + > + if (Head == 0) { > + KeMemoryBarrier(); > + Head = ControlBlock->head[Priority]; > + } > + > + Port = Head; > + EventWord = EvtchnFifoEventWord(Context, Port); > + > + Head = __EvtchnFifoUnlink(EventWord); > + > + if (Head == 0) > + *Ready &= ~(1ull << Priority); > + > + DoneSomething = FALSE; > + > + if (!__EvtchnFifoTestFlag(EventWord, EVTCHN_FIFO_MASKED) && > + __EvtchnFifoTestFlag(EventWord, EVTCHN_FIFO_PENDING)) > + DoneSomething = Event(Argument, Port); > + > + Context->Head[Priority] = Head; > + > + return DoneSomething; > +} > + > +static BOOLEAN > +EvtchnFifoPoll( > + IN PXENBUS_EVTCHN_ABI_CONTEXT _Context, > + IN ULONG Cpu, > + IN XENBUS_EVTCHN_ABI_EVENT Event, > + IN PVOID Argument > + ) > +{ > + PXENBUS_EVTCHN_FIFO_CONTEXT Context = (PVOID)_Context; > + unsigned int vcpu_id = SystemVirtualCpuIndex(Cpu); > + PMDL Mdl; > + evtchn_fifo_control_block_t *ControlBlock; > + ULONG Ready; > + ULONG Priority; > + BOOLEAN DoneSomething; > + > + Mdl = Context->ControlBlockMdl[vcpu_id]; > + > + ControlBlock = MmGetSystemAddressForMdlSafe(Mdl, > NormalPagePriority); > + ASSERT(ControlBlock != NULL); > + > + Ready = InterlockedExchange((LONG *)&ControlBlock->ready, 0); > + DoneSomething = FALSE; > + > + while (_BitScanReverse(&Priority, Ready)) { > + DoneSomething |= EvtchnFifoPollPriority(Context, > + ControlBlock, > + Priority, > + &Ready, > + Event, > + Argument); > + Ready |= InterlockedExchange((LONG *)&ControlBlock->ready, 0); > + } > + > + return DoneSomething; > +} > + > +static NTSTATUS > +EvtchnFifoPortEnable( > + IN PXENBUS_EVTCHN_ABI_CONTEXT _Context, > + IN ULONG Port > + ) > +{ > + PXENBUS_EVTCHN_FIFO_CONTEXT Context = (PVOID)_Context; > + KIRQL Irql; > + NTSTATUS status; > + > + KeAcquireSpinLock(&Context->Lock, &Irql); > + > + if (Port / EVENT_WORDS_PER_PAGE >= Context->EventPageCount) { > + status = EvtchnFifoExpand(Context, Port); > + > + if (!NT_SUCCESS(status)) > + goto fail1; > + } > + > + KeReleaseSpinLock(&Context->Lock, Irql); > + > + return STATUS_SUCCESS; > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + KeReleaseSpinLock(&Context->Lock, Irql); > + > + return status; > +} > + > +static VOID > +EvtchnFifoPortAck( > + IN PXENBUS_EVTCHN_ABI_CONTEXT _Context, > + IN ULONG Port > + ) > +{ > + PXENBUS_EVTCHN_FIFO_CONTEXT Context = (PVOID)_Context; > + event_word_t *EventWord; > + > + EventWord = EvtchnFifoEventWord(Context, Port); > + __EvtchnFifoClearFlag(&EventWord[Port], EVTCHN_FIFO_PENDING); > +} > + > +static VOID > +EvtchnFifoPortMask( > + IN PXENBUS_EVTCHN_ABI_CONTEXT _Context, > + IN ULONG Port > + ) > +{ > + PXENBUS_EVTCHN_FIFO_CONTEXT Context = (PVOID)_Context; > + event_word_t *EventWord; > + > + EventWord = EvtchnFifoEventWord(Context, Port); > + __EvtchnFifoSetFlag(&EventWord[Port], EVTCHN_FIFO_MASKED); > +} > + > +static BOOLEAN > +EvtchnFifoPortUnmask( > + IN PXENBUS_EVTCHN_ABI_CONTEXT _Context, > + IN ULONG Port > + ) > +{ > + PXENBUS_EVTCHN_FIFO_CONTEXT Context = (PVOID)_Context; > + event_word_t *EventWord; > + LONG Old; > + LONG New; > + > + EventWord = EvtchnFifoEventWord(Context, Port); > + > + // Clear masked bit, spinning if busy > + do { > + Old = *EventWord & ~(1 << EVTCHN_FIFO_BUSY); > + New = Old & ~(1 << EVTCHN_FIFO_MASKED); > + } while (InterlockedCompareExchange((LONG *)EventWord, New, Old) != > Old); > + > + // Check whether the port was masked > + if (~Old & (1 << EVTCHN_FIFO_MASKED)) > + return FALSE; > + > + // If we cleared the mask then check whether something is pending > + if (!__EvtchnFifoTestAndClearFlag(EventWord, EVTCHN_FIFO_PENDING)) > + return FALSE; > + > + return TRUE; > +} > + > +static VOID > +EvtchnFifoPortDisable( > + IN PXENBUS_EVTCHN_ABI_CONTEXT _Context, > + IN ULONG Port > + ) > +{ > + EvtchnFifoPortMask(_Context, Port); > +} > + > +static VOID > +EvtchnFifoReset( > + IN PXENBUS_EVTCHN_FIFO_CONTEXT Context > + ) > +{ > + ULONGLONG Value; > + ULONG LocalPort; > + ULONG RemotePort; > + USHORT RemoteDomain; > + NTSTATUS status; > + > + UNREFERENCED_PARAMETER(Context); > + > + status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Value); > + ASSERT(NT_SUCCESS(status)); > + > + LocalPort = (LONG)Value; > + > + // > + // When we reset the event channel ABI we will lose our > + // binding to the STORE event channel, which was set up > + // by the toolstack during domain build. > + // We need to get the binding back, so we must query the > + // remote domain and port, and then re-bind after the > + // reset. > + // > + > + status = EventChannelQueryInterDomain(LocalPort, > + &RemoteDomain, > + &RemotePort); > + ASSERT(NT_SUCCESS(status)); > + > + LogPrintf(LOG_LEVEL_INFO, "EVTCHN_FIFO: RESET\n"); > + (VOID) EventChannelReset(); > + > + status = EventChannelBindInterDomain(RemoteDomain, > + RemotePort, > + &LocalPort); > + ASSERT(NT_SUCCESS(status)); > + > + Value = LocalPort; > + > + status = HvmSetParam(HVM_PARAM_STORE_EVTCHN, Value); > + ASSERT(NT_SUCCESS(status)); > +} > + > +static NTSTATUS > +EvtchnFifoAcquire( > + IN PXENBUS_EVTCHN_ABI_CONTEXT _Context > + ) > +{ > + PXENBUS_EVTCHN_FIFO_CONTEXT Context = (PVOID)_Context; > + KIRQL Irql; > + LONG Cpu; > + PMDL Mdl; > + NTSTATUS status; > + > + KeAcquireSpinLock(&Context->Lock, &Irql); > + > + if (Context->References++ != 0) > + goto done; > + > + Trace("====>\n"); > + > + Cpu = 0; > + while (Cpu < KeNumberProcessors) { > + unsigned int vcpu_id; > + PFN_NUMBER Pfn; > + PHYSICAL_ADDRESS Address; > + > + Mdl = __AllocatePage(); > + > + status = STATUS_NO_MEMORY; > + if (Mdl == NULL) > + goto fail1; > + > + vcpu_id = SystemVirtualCpuIndex(Cpu); > + Pfn = MmGetMdlPfnArray(Mdl)[0]; > + > + status = EventChannelInitControl(Pfn, vcpu_id); > + if (!NT_SUCCESS(status)) > + goto fail2; > + > + Address.QuadPart = (ULONGLONG)Pfn << PAGE_SHIFT; > + > + LogPrintf(LOG_LEVEL_INFO, > + "EVTCHN_FIFO: CONTROLBLOCK[%u] @ %08x.%08x\n", > + vcpu_id, > + Address.HighPart, > + Address.LowPart); > + > + Context->ControlBlockMdl[vcpu_id] = Mdl; > + Cpu++; > + } > + > + Trace("<====\n"); > + > +done: > + KeReleaseSpinLock(&Context->Lock, Irql); > + > + return STATUS_SUCCESS; > + > +fail2: > + __FreePage(Mdl); > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + (VOID) EventChannelReset(); > + > + while (--Cpu >= 0) { > + unsigned int vcpu_id; > + > + vcpu_id = SystemVirtualCpuIndex(Cpu); > + > + Mdl = Context->ControlBlockMdl[vcpu_id]; > + Context->ControlBlockMdl[vcpu_id] = NULL; > + > + __FreePage(Mdl); > + } > + > + --Context->References; > + ASSERT3U(Context->References, ==, 0); > + KeReleaseSpinLock(&Context->Lock, Irql); > + > + return status; > +} > + > +VOID > +EvtchnFifoRelease( > + IN PXENBUS_EVTCHN_ABI_CONTEXT _Context > + ) > +{ > + PXENBUS_EVTCHN_FIFO_CONTEXT Context = (PVOID)_Context; > + KIRQL Irql; > + LONG Cpu; > + > + KeAcquireSpinLock(&Context->Lock, &Irql); > + > + if (--Context->References > 0) > + goto done; > + > + Trace("====>\n"); > + > + EvtchnFifoReset(Context); > + > + EvtchnFifoContract(Context); > + > + Cpu = KeNumberProcessors; > + while (--Cpu >= 0) { > + unsigned int vcpu_id; > + PMDL Mdl; > + > + vcpu_id = SystemVirtualCpuIndex(Cpu); > + > + Mdl = Context->ControlBlockMdl[vcpu_id]; > + Context->ControlBlockMdl[vcpu_id] = NULL; > + > + __FreePage(Mdl); > + } > + > + Trace("<====\n"); > + > +done: > + KeReleaseSpinLock(&Context->Lock, Irql); > +} > + > +static XENBUS_EVTCHN_ABI EvtchnAbiFifo = { > + NULL, > + EvtchnFifoAcquire, > + EvtchnFifoRelease, > + EvtchnFifoPoll, > + EvtchnFifoPortEnable, > + EvtchnFifoPortDisable, > + EvtchnFifoPortAck, > + EvtchnFifoPortMask, > + EvtchnFifoPortUnmask > +}; > + > +NTSTATUS > +EvtchnFifoInitialize( > + IN PXENBUS_FDO Fdo, > + OUT PXENBUS_EVTCHN_ABI_CONTEXT *_Context > + ) > +{ > + PXENBUS_EVTCHN_FIFO_CONTEXT Context; > + NTSTATUS status; > + > + Trace("====>\n"); > + > + Context = __EvtchnFifoAllocate(sizeof > (XENBUS_EVTCHN_FIFO_CONTEXT)); > + > + status = STATUS_NO_MEMORY; > + if (Context == NULL) > + goto fail1; > + > + KeInitializeSpinLock(&Context->Lock); > + > + Context->Fdo = Fdo; > + > + *_Context = (PVOID)Context; > + > + Trace("<====\n"); > + > + return STATUS_SUCCESS; > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + return status; > +} > + > +VOID > +EvtchnFifoGetAbi( > + IN PXENBUS_EVTCHN_ABI_CONTEXT _Context, > + OUT PXENBUS_EVTCHN_ABI Abi) > +{ > + *Abi = EvtchnAbiFifo; > + > + Abi->Context = (PVOID)_Context; > +} > + > +VOID > +EvtchnFifoTeardown( > + IN PXENBUS_EVTCHN_ABI_CONTEXT _Context > + ) > +{ > + PXENBUS_EVTCHN_FIFO_CONTEXT Context = (PVOID)_Context; > + > + Trace("====>\n"); > + > + Context->Fdo = NULL; > + > + RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK)); > + > + ASSERT(IsZeroMemory(Context, sizeof > (XENBUS_EVTCHN_FIFO_CONTEXT))); > + __EvtchnFifoFree(Context); > + > + Trace("<====\n"); > +} > diff --git a/src/xenbus/evtchn_fifo.h b/src/xenbus/evtchn_fifo.h > new file mode 100644 > index 0000000..bf96b19 > --- /dev/null > +++ b/src/xenbus/evtchn_fifo.h > @@ -0,0 +1,59 @@ > +/* Copyright (c) Citrix Systems Inc. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, > + * with or without modification, are permitted provided > + * that the following conditions are met: > + * > + * * Redistributions of source code must retain the above > + * copyright notice, this list of conditions and the > + * following disclaimer. > + * * Redistributions in binary form must reproduce the above > + * copyright notice, this list of conditions and the > + * following disclaimer in the documentation and/or other > + * materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, > + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR > + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, > + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR > + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, > + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING > + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + */ > + > +#ifndef _XENBUS_EVTCHN_FIFO_H > +#define _XENBUS_EVTCHN_FIFO_H > + > +#include <ntddk.h> > +#include <xen.h> > + > +#include "evtchn_abi.h" > +#include "fdo.h" > + > +extern NTSTATUS > +EvtchnFifoInitialize( > + IN PXENBUS_FDO Fdo, > + OUT PXENBUS_EVTCHN_ABI_CONTEXT *Context > + ); > + > +extern VOID > +EvtchnFifoGetAbi( > + IN PXENBUS_EVTCHN_ABI_CONTEXT Context, > + OUT PXENBUS_EVTCHN_ABI Abi > + ); > + > +extern VOID > +EvtchnFifoTeardown( > + IN PXENBUS_EVTCHN_ABI_CONTEXT Context > + ); > + > +#endif // _XENBUS_EVTCHN_FIFO_H > + > diff --git a/src/xenbus/store.c b/src/xenbus/store.c > index 62ec60b..22c2a12 100644 > --- a/src/xenbus/store.c > +++ b/src/xenbus/store.c > @@ -1825,13 +1825,20 @@ StoreEnable( > IN PXENBUS_STORE_CONTEXT Context > ) > { > - ULONGLONG Port; > + ULONGLONG Value; > + ULONG Port; > BOOLEAN Pending; > NTSTATUS status; > > - status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Port); > + status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Value); > ASSERT(NT_SUCCESS(status)); > > + Port = (ULONG)Value; > + > + LogPrintf(LOG_LEVEL_INFO, > + "STORE: EVTCHN %u\n", > + Port); > + > Context->Channel = XENBUS_EVTCHN(Open, > &Context->EvtchnInterface, > XENBUS_EVTCHN_TYPE_FIXED, > diff --git a/vs2012/xenbus/xenbus.vcxproj b/vs2012/xenbus/xenbus.vcxproj > index 6cd12d1..3c184e0 100644 > --- a/vs2012/xenbus/xenbus.vcxproj > +++ b/vs2012/xenbus/xenbus.vcxproj > @@ -89,6 +89,7 @@ > <ClCompile Include="..\..\src\xenbus\driver.c" /> > <ClCompile Include="..\..\src\xenbus\evtchn.c" /> > <ClCompile Include="..\..\src\xenbus\evtchn_2l.c" /> > + <ClCompile Include="..\..\src\xenbus\evtchn_fifo.c" /> > <ClCompile Include="..\..\src\xenbus\fdo.c" /> > <ClCompile Include="..\..\src\xenbus\gnttab.c" /> > <ClCompile Include="..\..\src\xenbus\pdo.c" /> > diff --git a/vs2013/xenbus/xenbus.vcxproj b/vs2013/xenbus/xenbus.vcxproj > index 0f37f68..ecb602b 100644 > --- a/vs2013/xenbus/xenbus.vcxproj > +++ b/vs2013/xenbus/xenbus.vcxproj > @@ -129,6 +129,7 @@ > <ClCompile Include="..\..\src\xenbus\driver.c" /> > <ClCompile Include="..\..\src\xenbus\evtchn.c" /> > <ClCompile Include="..\..\src\xenbus\evtchn_2l.c" /> > + <ClCompile Include="..\..\src\xenbus\evtchn_fifo.c" /> > <ClCompile Include="..\..\src\xenbus\fdo.c" /> > <ClCompile Include="..\..\src\xenbus\gnttab.c" /> > <ClCompile Include="..\..\src\xenbus\pdo.c" /> > -- > 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 |