[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [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> --- 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 |