[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 09/14] add boilerplate ring
From: Owen Smith <owen.smith@xxxxxxxxxx> Also queries for gnttab and evtchn interface and adds those headers Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx> --- include/cache_interface.h | 233 +++++++++++++++++ include/evtchn_interface.h | 357 +++++++++++++++++++++++++ include/gnttab_interface.h | 287 ++++++++++++++++++++ src/xencons/fdo.c | 42 ++- src/xencons/fdo.h | 4 + src/xencons/frontend.c | 61 +++-- src/xencons/ring.c | 578 +++++++++++++++++++++++++++++++++++++++++ src/xencons/ring.h | 78 ++++++ vs2015/xencons/xencons.vcxproj | 1 + 9 files changed, 1621 insertions(+), 20 deletions(-) create mode 100755 include/cache_interface.h create mode 100755 include/evtchn_interface.h create mode 100755 include/gnttab_interface.h create mode 100755 src/xencons/ring.c create mode 100755 src/xencons/ring.h diff --git a/include/cache_interface.h b/include/cache_interface.h new file mode 100755 index 0000000..dae3ac6 --- /dev/null +++ b/include/cache_interface.h @@ -0,0 +1,233 @@ +/* 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. + */ + +/*! \file cache_interface.h + \brief XENBUS CACHE Interface + + This interface provides access to XENBUS's object cache + implementation. +*/ + +#ifndef _XENBUS_CACHE_INTERFACE_H +#define _XENBUS_CACHE_INTERFACE_H + +#ifndef _WINDLL + +/*! \typedef XENBUS_CACHE + \brief Cache handle +*/ +typedef struct _XENBUS_CACHE XENBUS_CACHE, *PXENBUS_CACHE; + +/*! \typedef XENBUS_CACHE_ACQUIRE + \brief Acquire a reference to the CACHE interface + + \param Interface The interface header +*/ +typedef NTSTATUS +(*XENBUS_CACHE_ACQUIRE)( + IN PINTERFACE Interface + ); + +/*! \typedef XENBUS_CACHE_RELEASE + \brief Release a reference to the CACHE interface + + \param Interface The interface header +*/ +typedef VOID +(*XENBUS_CACHE_RELEASE)( + IN PINTERFACE Interface + ); + +/*! \typedef XENBUS_CACHE_CTOR + \brief Object creator callback + + \param Argument Context \a Argument supplied to \a XENBUS_CACHE_CREATE + \param Object Newly allocated object + + This callback is invoked just after a new object is allocated and may + be used to initialize any object data prior to its insertion into the + cache. +*/ +typedef NTSTATUS +(*XENBUS_CACHE_CTOR)( + IN PVOID Argument, + IN PVOID Object + ); + +/*! \typedef XENBUS_CACHE_DTOR + \brief Object destructor callback + + \param Argument Context \a Argument supplied to \a XENBUS_CACHE_CREATE + \param Object Object about to be freed + + This callback is invoked just after an object is removed from the + cache and before it is freed and may be used to tear down any object data. +*/ +typedef VOID +(*XENBUS_CACHE_DTOR)( + IN PVOID Argument, + IN PVOID Object + ); + +/*! \typedef XENBUS_CACHE_ACQUIRE_LOCK + \brief Cache lock callback + + \param Argument Context \a Argument supplied to \a XENBUS_CACHE_CREATE + + This callback is invoked if the cache implementation requires mutual + exclusion. +*/ +typedef VOID +(*XENBUS_CACHE_ACQUIRE_LOCK)( + IN PVOID Argument + ); + +/*! \typedef XENBUS_CACHE_RELEASE_LOCK + \brief Cache unlock callback + + \param Argument Context \a Argument supplied to \a XENBUS_CACHE_CREATE + + This callback is invoked to release the mutual exclusion lock acquired + by a previous invocation of \a XENBUS_CACHE_ACQUIRE_LOCK. +*/ +typedef VOID +(*XENBUS_CACHE_RELEASE_LOCK)( + IN PVOID Argument + ); + +/*! \typedef XENBUS_CACHE_CREATE + \brief Create a cache of objects of the given \a Size + + \param Interface The interface header + \param Name A name for the cache which will be used in debug output + \param Size The size of each object in bytes + \param Reservation The target minimum population of the cache + \param Ctor A callback which is invoked when a new object created + \param Dtor A callback which is invoked when an object is destroyed + \param AcquireLock A callback invoked to acquire a spinlock + \param ReleaseLock A callback invoked to release the spinlock + \param Argument An optional context argument passed to the callbacks + \param Cache A pointer to a cache handle to be initialized + + If a non-zero \a Reservation is specified then this method will fail + unless that number of objects can be immediately created. +*/ +typedef NTSTATUS +(*XENBUS_CACHE_CREATE)( + IN PINTERFACE Interface, + IN const CHAR *Name, + IN ULONG Size, + IN ULONG Reservation, + IN XENBUS_CACHE_CTOR Ctor, + IN XENBUS_CACHE_DTOR Dtor, + IN XENBUS_CACHE_ACQUIRE_LOCK AcquireLock, + IN XENBUS_CACHE_RELEASE_LOCK ReleaseLock, + IN PVOID Argument OPTIONAL, + OUT PXENBUS_CACHE *Cache + ); + +/*! \typedef XENBUS_CACHE_GET + \brief Get an object from a \a Cache + + \param Interface The interface header + \param Cache The cache handle + \param Locked If mutually exclusive access to the cache is already + guaranteed then set this to TRUE +*/ +typedef PVOID +(*XENBUS_CACHE_GET)( + IN PINTERFACE Interface, + IN PXENBUS_CACHE Cache, + IN BOOLEAN Locked + ); + +/*! \typedef XENBUS_CACHE_PUT + \brief Return an object to a \a Cache + + \param Interface The interface header + \param Cache The cache handle + \param Locked If mutually exclusive access to the cache is already + guaranteed then set this to TRUE +*/ +typedef VOID +(*XENBUS_CACHE_PUT)( + IN PINTERFACE Interface, + IN PXENBUS_CACHE Cache, + IN PVOID Object, + IN BOOLEAN Locked + ); + +/*! \typedef XENBUS_CACHE_DESTROY + \brief Destroy a \a Cache + + \param Interface The interface header + \param Cache The cache handle + + All objects must have been returned to the cache prior to destruction +*/ +typedef VOID +(*XENBUS_CACHE_DESTROY)( + IN PINTERFACE Interface, + IN PXENBUS_CACHE Cache + ); + +// {A98DFD78-416A-4949-92A5-E084F2F4B44E} +DEFINE_GUID(GUID_XENBUS_CACHE_INTERFACE, +0xa98dfd78, 0x416a, 0x4949, 0x92, 0xa5, 0xe0, 0x84, 0xf2, 0xf4, 0xb4, 0x4e); + +/*! \struct _XENBUS_CACHE_INTERFACE_V1 + \brief CACHE interface version 1 + \ingroup interfaces +*/ +struct _XENBUS_CACHE_INTERFACE_V1 { + INTERFACE Interface; + XENBUS_CACHE_ACQUIRE CacheAcquire; + XENBUS_CACHE_RELEASE CacheRelease; + XENBUS_CACHE_CREATE CacheCreate; + XENBUS_CACHE_GET CacheGet; + XENBUS_CACHE_PUT CachePut; + XENBUS_CACHE_DESTROY CacheDestroy; +}; + +typedef struct _XENBUS_CACHE_INTERFACE_V1 XENBUS_CACHE_INTERFACE, *PXENBUS_CACHE_INTERFACE; + +/*! \def XENBUS_CACHE + \brief Macro at assist in method invocation +*/ +#define XENBUS_CACHE(_Method, _Interface, ...) \ + (_Interface)->Cache ## _Method((PINTERFACE)(_Interface), __VA_ARGS__) + +#endif // _WINDLL + +#define XENBUS_CACHE_INTERFACE_VERSION_MIN 1 +#define XENBUS_CACHE_INTERFACE_VERSION_MAX 1 + +#endif // _XENBUS_CACHE_INTERFACE_H diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h new file mode 100755 index 0000000..068a697 --- /dev/null +++ b/include/evtchn_interface.h @@ -0,0 +1,357 @@ +/* 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. + */ + +/*! \file evtchn_interface.h + \brief XENBUS EVTCHN Interface + + This interface provides access to hypervisor event channels +*/ + +#ifndef _XENBUS_EVTCHN_INTERFACE_H +#define _XENBUS_EVTCHN_INTERFACE_H + +#ifndef _WINDLL + +/*! \enum _XENBUS_EVTCHN_TYPE + \brief Event channel type to be opened +*/ +typedef enum _XENBUS_EVTCHN_TYPE { + XENBUS_EVTCHN_TYPE_INVALID = 0, + XENBUS_EVTCHN_TYPE_FIXED, /*!< Fixed */ + XENBUS_EVTCHN_TYPE_UNBOUND, /*!< Unbound */ + XENBUS_EVTCHN_TYPE_INTER_DOMAIN, /*!< Interdomain */ + XENBUS_EVTCHN_TYPE_VIRQ /*!< VIRQ */ +} XENBUS_EVTCHN_TYPE, *PXENBUS_EVTCHN_TYPE; + +/*! \typedef XENBUS_EVTCHN_CHANNEL + \brief Event channel handle +*/ +typedef struct _XENBUS_EVTCHN_CHANNEL XENBUS_EVTCHN_CHANNEL, *PXENBUS_EVTCHN_CHANNEL; + +/*! \typedef XENBUS_EVTCHN_ACQUIRE + \brief Acquire a reference to the EVTCHN interface + + \param Interface The interface header +*/ +typedef NTSTATUS +(*XENBUS_EVTCHN_ACQUIRE)( + IN PINTERFACE Interface + ); + +/*! \typedef XENBUS_EVTCHN_RELEASE + \brief Release a reference to the EVTCHN interface + + \param Interface The interface header +*/ +typedef VOID +(*XENBUS_EVTCHN_RELEASE)( + IN PINTERFACE Interface + ); + +/*! \typedef XENBUS_EVTCHN_OPEN + \brief Open an event channel + + \param Interface The interface header + \param Type The type of event channel to open + \param Function The callback function + \param Argument An optional context argument passed to the callback + \param ... Additional parameters required by \a Type + + \b Fixed: + \param LocalPort The local port number of the (already bound) channel + \param Mask Set to TRUE if the channel should be automatically masked before invoking the callback + + \b Unbound: + \param RemoteDomain The domid of the remote domain which will bind the channel + \param Mask Set to TRUE if the channel should be automatically masked before invoking the callback + + \b Interdomain: + \param RemoteDomain The domid of the remote domain which has already bound the channel + \param RemotePort The port number bound to the channel in the remote domain + \param Mask Set to TRUE if the channel should be automatically masked before invoking the callback + + \b VIRQ: + \param Index The index number of the VIRQ + + \return Event channel handle +*/ +typedef PXENBUS_EVTCHN_CHANNEL +(*XENBUS_EVTCHN_OPEN)( + IN PINTERFACE Interface, + IN XENBUS_EVTCHN_TYPE Type, + IN PKSERVICE_ROUTINE Function, + IN PVOID Argument OPTIONAL, + ... + ); + +/*! \typedef XENBUS_EVTCHN_BIND + \brief Bind an event channel to a specific CPU + + \param Interface The interface header + \param Channel The channel handle + \param Group The group number of the CPU that should handle events + \param Number The relative number of the CPU that should handle events +*/ +typedef NTSTATUS +(*XENBUS_EVTCHN_BIND)( + IN PINTERFACE Interface, + IN PXENBUS_EVTCHN_CHANNEL Channel, + IN USHORT Group, + IN UCHAR Number + ); + +typedef VOID +(*XENBUS_EVTCHN_UNMASK_V4)( + IN PINTERFACE Interface, + IN PXENBUS_EVTCHN_CHANNEL Channel, + IN BOOLEAN InCallback + ); + +/*! \typedef XENBUS_EVTCHN_UNMASK + \brief Unmask an event channel + + \param Interface The interface header + \param Channel The channel handle + \param InCallback Set to TRUE if this method is invoked in context of the channel callback + \param Force Set to TRUE if the unmask must succeed, otherwise set to FALSE and the function will return FALSE if the unmask did not complete. +*/ +typedef BOOLEAN +(*XENBUS_EVTCHN_UNMASK)( + IN PINTERFACE Interface, + IN PXENBUS_EVTCHN_CHANNEL Channel, + IN BOOLEAN InCallback, + IN BOOLEAN Force + ); + +typedef VOID +(*XENBUS_EVTCHN_SEND_V1)( + IN PINTERFACE Interface, + IN PXENBUS_EVTCHN_CHANNEL Channel + ); + +/*! \typedef XENBUS_EVTCHN_SEND + \brief Send an event to the remote end of the channel + + It is assumed that the domain cannot suspend during this call so + IRQL must be >= DISPATCH_LEVEL. + + \param Interface The interface header + \param Channel The channel handle +*/ +typedef VOID +(*XENBUS_EVTCHN_SEND)( + IN PINTERFACE Interface, + IN PXENBUS_EVTCHN_CHANNEL Channel + ); + +/*! \typedef XENBUS_EVTCHN_TRIGGER + \brief Send an event to the local end of the channel + + \param Interface The interface header + \param Channel The channel handle +*/ +typedef VOID +(*XENBUS_EVTCHN_TRIGGER)( + IN PINTERFACE Interface, + IN PXENBUS_EVTCHN_CHANNEL Channel + ); + +/*! \typedef XENBUS_EVTCHN_GET_COUNT + \brief Get the number of events received by the channel since it was opened + + \param Interface The interface header + \param Channel The channel handle + \return The number of events +*/ +typedef ULONG +(*XENBUS_EVTCHN_GET_COUNT)( + IN PINTERFACE Interface, + IN PXENBUS_EVTCHN_CHANNEL Channel + ); + +typedef NTSTATUS +(*XENBUS_EVTCHN_WAIT_V5)( + IN PINTERFACE Interface, + IN PXENBUS_EVTCHN_CHANNEL Channel, + IN PLARGE_INTEGER Timeout OPTIONAL + ); + +/*! \typedef XENBUS_EVTCHN_WAIT + \brief Wait for events to the local end of the channel + + \param Interface The interface header + \param Channel The channel handle + \param Count The event count to wait for + \param Timeout An optional timeout value (similar to KeWaitForSingleObject(), but non-zero values are allowed at DISPATCH_LEVEL). +*/ +typedef NTSTATUS +(*XENBUS_EVTCHN_WAIT)( + IN PINTERFACE Interface, + IN PXENBUS_EVTCHN_CHANNEL Channel, + IN ULONG Count, + IN PLARGE_INTEGER Timeout OPTIONAL + ); + +/*! \typedef XENBUS_EVTCHN_GET_PORT + \brief Get the local port number bound to the channel + + \param Interface The interface header + \param Channel The channel handle + \return The port number +*/ +typedef ULONG +(*XENBUS_EVTCHN_GET_PORT)( + IN PINTERFACE Interface, + IN PXENBUS_EVTCHN_CHANNEL Channel + ); + +/*! \typedef XENBUS_EVTCHN_CLOSE + \brief Close an event channel + + \param Interface The interface header + \param Channel The channel handle +*/ +typedef VOID +(*XENBUS_EVTCHN_CLOSE)( + IN PINTERFACE Interface, + IN PXENBUS_EVTCHN_CHANNEL Channel + ); + +// {BE2440AC-1098-4150-AF4D-452FADCEF923} +DEFINE_GUID(GUID_XENBUS_EVTCHN_INTERFACE, +0xbe2440ac, 0x1098, 0x4150, 0xaf, 0x4d, 0x45, 0x2f, 0xad, 0xce, 0xf9, 0x23); + +/*! \struct _XENBUS_EVTCHN_INTERFACE_V4 + \brief EVTCHN interface version 4 + \ingroup interfaces +*/ +struct _XENBUS_EVTCHN_INTERFACE_V4 { + INTERFACE Interface; + XENBUS_EVTCHN_ACQUIRE EvtchnAcquire; + XENBUS_EVTCHN_RELEASE EvtchnRelease; + XENBUS_EVTCHN_OPEN EvtchnOpen; + XENBUS_EVTCHN_BIND EvtchnBind; + XENBUS_EVTCHN_UNMASK_V4 EvtchnUnmaskVersion4; + XENBUS_EVTCHN_SEND_V1 EvtchnSendVersion1; + XENBUS_EVTCHN_TRIGGER EvtchnTrigger; + XENBUS_EVTCHN_GET_PORT EvtchnGetPort; + XENBUS_EVTCHN_CLOSE EvtchnClose; +}; + +/*! \struct _XENBUS_EVTCHN_INTERFACE_V5 + \brief EVTCHN interface version 5 + \ingroup interfaces +*/ +struct _XENBUS_EVTCHN_INTERFACE_V5 { + INTERFACE Interface; + XENBUS_EVTCHN_ACQUIRE EvtchnAcquire; + XENBUS_EVTCHN_RELEASE EvtchnRelease; + XENBUS_EVTCHN_OPEN EvtchnOpen; + XENBUS_EVTCHN_BIND EvtchnBind; + XENBUS_EVTCHN_UNMASK_V4 EvtchnUnmaskVersion4; + XENBUS_EVTCHN_SEND_V1 EvtchnSendVersion1; + XENBUS_EVTCHN_TRIGGER EvtchnTrigger; + XENBUS_EVTCHN_WAIT_V5 EvtchnWaitVersion5; + XENBUS_EVTCHN_GET_PORT EvtchnGetPort; + XENBUS_EVTCHN_CLOSE EvtchnClose; +}; + +/*! \struct _XENBUS_EVTCHN_INTERFACE_V6 + \brief EVTCHN interface version 6 + \ingroup interfaces +*/ +struct _XENBUS_EVTCHN_INTERFACE_V6 { + INTERFACE Interface; + XENBUS_EVTCHN_ACQUIRE EvtchnAcquire; + XENBUS_EVTCHN_RELEASE EvtchnRelease; + XENBUS_EVTCHN_OPEN EvtchnOpen; + XENBUS_EVTCHN_BIND EvtchnBind; + XENBUS_EVTCHN_UNMASK_V4 EvtchnUnmaskVersion4; + XENBUS_EVTCHN_SEND EvtchnSend; + XENBUS_EVTCHN_TRIGGER EvtchnTrigger; + XENBUS_EVTCHN_WAIT_V5 EvtchnWaitVersion5; + XENBUS_EVTCHN_GET_PORT EvtchnGetPort; + XENBUS_EVTCHN_CLOSE EvtchnClose; +}; + +/*! \struct _XENBUS_EVTCHN_INTERFACE_V7 + \brief EVTCHN interface version 7 + \ingroup interfaces +*/ +struct _XENBUS_EVTCHN_INTERFACE_V7 { + INTERFACE Interface; + XENBUS_EVTCHN_ACQUIRE EvtchnAcquire; + XENBUS_EVTCHN_RELEASE EvtchnRelease; + XENBUS_EVTCHN_OPEN EvtchnOpen; + XENBUS_EVTCHN_BIND EvtchnBind; + XENBUS_EVTCHN_UNMASK_V4 EvtchnUnmaskVersion4; + XENBUS_EVTCHN_SEND EvtchnSend; + XENBUS_EVTCHN_TRIGGER EvtchnTrigger; + XENBUS_EVTCHN_GET_COUNT EvtchnGetCount; + XENBUS_EVTCHN_WAIT EvtchnWait; + XENBUS_EVTCHN_GET_PORT EvtchnGetPort; + XENBUS_EVTCHN_CLOSE EvtchnClose; +}; + +/*! \struct _XENBUS_EVTCHN_INTERFACE_V8 + \brief EVTCHN interface version 8 + \ingroup interfaces +*/ +struct _XENBUS_EVTCHN_INTERFACE_V8 { + INTERFACE Interface; + XENBUS_EVTCHN_ACQUIRE EvtchnAcquire; + XENBUS_EVTCHN_RELEASE EvtchnRelease; + XENBUS_EVTCHN_OPEN EvtchnOpen; + XENBUS_EVTCHN_BIND EvtchnBind; + XENBUS_EVTCHN_UNMASK EvtchnUnmask; + XENBUS_EVTCHN_SEND EvtchnSend; + XENBUS_EVTCHN_TRIGGER EvtchnTrigger; + XENBUS_EVTCHN_GET_COUNT EvtchnGetCount; + XENBUS_EVTCHN_WAIT EvtchnWait; + XENBUS_EVTCHN_GET_PORT EvtchnGetPort; + XENBUS_EVTCHN_CLOSE EvtchnClose; +}; + +typedef struct _XENBUS_EVTCHN_INTERFACE_V8 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE; + +/*! \def XENBUS_EVTCHN + \brief Macro at assist in method invocation +*/ +#define XENBUS_EVTCHN(_Method, _Interface, ...) \ + (_Interface)->Evtchn ## _Method((PINTERFACE)(_Interface), __VA_ARGS__) + +#endif // _WINDLL + +#define XENBUS_EVTCHN_INTERFACE_VERSION_MIN 4 +#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 8 + +#endif // _XENBUS_EVTCHN_INTERFACE_H + diff --git a/include/gnttab_interface.h b/include/gnttab_interface.h new file mode 100755 index 0000000..61272ab --- /dev/null +++ b/include/gnttab_interface.h @@ -0,0 +1,287 @@ +/* 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. + */ + +/*! \file gnttab_interface.h + \brief XENBUS GNTTAB Interface + + This interface provides access to the hypervisor grant table +*/ + +#ifndef _XENBUS_GNTTAB_INTERFACE_H +#define _XENBUS_GNTTAB_INTERFACE_H + +#include <cache_interface.h> + +#ifndef _WINDLL + +/*! \typedef XENBUS_GNTTAB_ENTRY + \brief Grant table entry handle +*/ +typedef struct _XENBUS_GNTTAB_ENTRY XENBUS_GNTTAB_ENTRY, *PXENBUS_GNTTAB_ENTRY; + +/*! \typedef XENBUS_GNTTAB_CACHE + \brief Grant table cache handle +*/ +typedef struct _XENBUS_GNTTAB_CACHE XENBUS_GNTTAB_CACHE, *PXENBUS_GNTTAB_CACHE; + +/*! \typedef XENBUS_GNTTAB_ACQUIRE + \brief Acquire a reference to the GNTTAB interface + + \param Interface The interface header +*/ +typedef NTSTATUS +(*XENBUS_GNTTAB_ACQUIRE)( + IN PINTERFACE Interface + ); + +/*! \typedef XENBUS_GNTTAB_RELEASE + \brief Release a reference to the GNTTAB interface + + \param Interface The interface header +*/ +typedef VOID +(*XENBUS_GNTTAB_RELEASE)( + IN PINTERFACE Interface + ); + +/*! \typedef XENBUS_GNTTAB_CREATE_CACHE + \brief Create a cache of grant table entries + + \param Interface The interface header + \param Name A name for the cache which will be used in debug output + \param Reservation The target minimum population of the cache + \param AcquireLock A callback invoked to acquire a spinlock + \param ReleaseLock A callback invoked to release the spinlock + \param Argument An optional context argument passed to the callbacks + \param Cache A pointer to a grant table cache handle to be initialized +*/ +typedef NTSTATUS +(*XENBUS_GNTTAB_CREATE_CACHE)( + IN PINTERFACE Interface, + IN const CHAR *Name, + IN ULONG Reservation, + IN XENBUS_CACHE_ACQUIRE_LOCK AcquireLock, + IN XENBUS_CACHE_RELEASE_LOCK ReleaseLock, + IN PVOID Argument OPTIONAL, + OUT PXENBUS_GNTTAB_CACHE *Cache + ); + +/*! \typedef XENBUS_GNTTAB_PERMIT_FOREIGN_ACCESS + \brief Get a table entry from the \a Cache permitting access to a given \a Pfn + + \param Interface The interface header + \param Cache The grant table cache handle + \param Locked If mutually exclusive access to the cache is already + guaranteed then set this to TRUE + \param Domain The domid of the domain being granted access + \param Pfn The frame number of the page that we are granting access to + \param ReadOnly Set to TRUE if the foreign domain is only being granted + read access + \param Entry A pointer to a grant table entry handle to be initialized +*/ +typedef NTSTATUS +(*XENBUS_GNTTAB_PERMIT_FOREIGN_ACCESS)( + IN PINTERFACE Interface, + IN PXENBUS_GNTTAB_CACHE Cache, + IN BOOLEAN Locked, + IN USHORT Domain, + IN PFN_NUMBER Pfn, + IN BOOLEAN ReadOnly, + OUT PXENBUS_GNTTAB_ENTRY *Entry + ); + +/*! \typedef XENBUS_GNTTAB_REVOKE_FOREIGN_ACCESS + \brief Revoke foreign access and return the \a Entry to the \a Cache + + \param Interface The interface header + \param Cache The grant table cache handle + \param Locked If mutually exclusive access to the cache is already + guaranteed then set this to TRUE + \param Entry The grant table entry handle +*/ +typedef NTSTATUS +(*XENBUS_GNTTAB_REVOKE_FOREIGN_ACCESS)( + IN PINTERFACE Interface, + IN PXENBUS_GNTTAB_CACHE Cache, + IN BOOLEAN Locked, + IN PXENBUS_GNTTAB_ENTRY Entry + ); + +/*! \typedef XENBUS_GNTTAB_GET_REFERENCE + \brief Get the reference number of the entry + + \param Interface The interface header + \param Entry The grant table entry handle + \return The reference number +*/ +typedef ULONG +(*XENBUS_GNTTAB_GET_REFERENCE)( + IN PINTERFACE Interface, + IN PXENBUS_GNTTAB_ENTRY Entry + ); + +/*! \typedef XENBUS_GNTTAB_QUERY_REFERENCE + \brief Get the reference number of the entry + + \param Interface The interface header + \param Reference The reference number + \param Pfn An optional pointer to receive the value of the reference frame number + \param ReadOnly An optional pointer to receive the boolean value of the read-only flag +*/ +typedef NTSTATUS +(*XENBUS_GNTTAB_QUERY_REFERENCE)( + IN PINTERFACE Interface, + IN ULONG Reference, + OUT PPFN_NUMBER Pfn OPTIONAL, + OUT PBOOLEAN ReadOnly OPTIONAL + ); + +#define XENBUS_GNTTAB_CONSOLE_REFERENCE 0 +#define XENBUS_GNTTAB_STORE_REFERENCE 1 + + +/*! \typedef XENBUS_GNTTAB_DESTROY_CACHE + \brief Destroy a cache of grant table entries + + \param Interface The interface header + \param Cache The grant table cache handle + + All grant table entries must have been revoked prior to destruction + of the cache +*/ +typedef VOID +(*XENBUS_GNTTAB_DESTROY_CACHE)( + IN PINTERFACE Interface, + IN PXENBUS_GNTTAB_CACHE Cache + ); + +/*! \typedef XENBUS_GNTTAB_MAP_FOREIGN_PAGES + \brief Map foreign memory pages into the system address space + + \param Interface The interface header + \param Domain The domid of the foreign domain that granted the pages + \param NumberPages Number of pages to map + \param References Array of grant reference numbers shared by the foreign domain + \param ReadOnly If TRUE, pages are mapped with read-only access + \param Address The physical address that the foreign pages are mapped under +*/ + +typedef NTSTATUS +(*XENBUS_GNTTAB_MAP_FOREIGN_PAGES)( + IN PINTERFACE Interface, + IN USHORT Domain, + IN ULONG NumberPages, + IN PULONG References, + IN BOOLEAN ReadOnly, + OUT PHYSICAL_ADDRESS *Address + ); + +/*! \typedef XENBUS_GNTTAB_UNMAP_FOREIGN_PAGES + \brief Unmap foreign memory pages from the system address space + + \param Interface The interface header + \param Address The physical address that the foreign pages are mapped under +*/ +typedef NTSTATUS +(*XENBUS_GNTTAB_UNMAP_FOREIGN_PAGES)( + IN PINTERFACE Interface, + IN PHYSICAL_ADDRESS Address + ); + +// {763679C5-E5C2-4A6D-8B88-6BB02EC42D8E} +DEFINE_GUID(GUID_XENBUS_GNTTAB_INTERFACE, +0x763679c5, 0xe5c2, 0x4a6d, 0x8b, 0x88, 0x6b, 0xb0, 0x2e, 0xc4, 0x2d, 0x8e); + +/*! \struct _XENBUS_GNTTAB_INTERFACE_V1 + \brief GNTTAB interface version 1 + \ingroup interfaces +*/ +struct _XENBUS_GNTTAB_INTERFACE_V1 { + INTERFACE Interface; + XENBUS_GNTTAB_ACQUIRE GnttabAcquire; + XENBUS_GNTTAB_RELEASE GnttabRelease; + XENBUS_GNTTAB_CREATE_CACHE GnttabCreateCache; + XENBUS_GNTTAB_PERMIT_FOREIGN_ACCESS GnttabPermitForeignAccess; + XENBUS_GNTTAB_REVOKE_FOREIGN_ACCESS GnttabRevokeForeignAccess; + XENBUS_GNTTAB_GET_REFERENCE GnttabGetReference; + XENBUS_GNTTAB_DESTROY_CACHE GnttabDestroyCache; +}; + +/*! \struct _XENBUS_GNTTAB_INTERFACE_V2 + \brief GNTTAB interface version 2 + \ingroup interfaces +*/ +struct _XENBUS_GNTTAB_INTERFACE_V2 { + INTERFACE Interface; + XENBUS_GNTTAB_ACQUIRE GnttabAcquire; + XENBUS_GNTTAB_RELEASE GnttabRelease; + XENBUS_GNTTAB_CREATE_CACHE GnttabCreateCache; + XENBUS_GNTTAB_PERMIT_FOREIGN_ACCESS GnttabPermitForeignAccess; + XENBUS_GNTTAB_REVOKE_FOREIGN_ACCESS GnttabRevokeForeignAccess; + XENBUS_GNTTAB_GET_REFERENCE GnttabGetReference; + XENBUS_GNTTAB_DESTROY_CACHE GnttabDestroyCache; + XENBUS_GNTTAB_MAP_FOREIGN_PAGES GnttabMapForeignPages; + XENBUS_GNTTAB_UNMAP_FOREIGN_PAGES GnttabUnmapForeignPages; +}; + +/*! \struct _XENBUS_GNTTAB_INTERFACE_V3 + \brief GNTTAB interface version 3 + \ingroup interfaces +*/ +struct _XENBUS_GNTTAB_INTERFACE_V3 { + INTERFACE Interface; + XENBUS_GNTTAB_ACQUIRE GnttabAcquire; + XENBUS_GNTTAB_RELEASE GnttabRelease; + XENBUS_GNTTAB_CREATE_CACHE GnttabCreateCache; + XENBUS_GNTTAB_PERMIT_FOREIGN_ACCESS GnttabPermitForeignAccess; + XENBUS_GNTTAB_REVOKE_FOREIGN_ACCESS GnttabRevokeForeignAccess; + XENBUS_GNTTAB_GET_REFERENCE GnttabGetReference; + XENBUS_GNTTAB_QUERY_REFERENCE GnttabQueryReference; + XENBUS_GNTTAB_DESTROY_CACHE GnttabDestroyCache; + XENBUS_GNTTAB_MAP_FOREIGN_PAGES GnttabMapForeignPages; + XENBUS_GNTTAB_UNMAP_FOREIGN_PAGES GnttabUnmapForeignPages; +}; + +typedef struct _XENBUS_GNTTAB_INTERFACE_V3 XENBUS_GNTTAB_INTERFACE, *PXENBUS_GNTTAB_INTERFACE; + +/*! \def XENBUS_GNTTAB + \brief Macro at assist in method invocation +*/ +#define XENBUS_GNTTAB(_Method, _Interface, ...) \ + (_Interface)->Gnttab ## _Method((PINTERFACE)(_Interface), __VA_ARGS__) + +#endif // _WINDLL + +#define XENBUS_GNTTAB_INTERFACE_VERSION_MIN 1 +#define XENBUS_GNTTAB_INTERFACE_VERSION_MAX 3 + +#endif // _XENBUS_GNTTAB_INTERFACE_H + diff --git a/src/xencons/fdo.c b/src/xencons/fdo.c index 5296c7f..ef26869 100644 --- a/src/xencons/fdo.c +++ b/src/xencons/fdo.c @@ -100,6 +100,8 @@ struct _XENCONS_FDO { XENBUS_SUSPEND_INTERFACE SuspendInterface; XENBUS_STORE_INTERFACE StoreInterface; XENBUS_CONSOLE_INTERFACE ConsoleInterface; + XENBUS_EVTCHN_INTERFACE EvtchnInterface; + XENBUS_GNTTAB_INTERFACE GnttabInterface; PXENBUS_SUSPEND_CALLBACK SuspendCallbackLate; }; @@ -3140,6 +3142,8 @@ DEFINE_FDO_GET_INTERFACE(Debug, PXENBUS_DEBUG_INTERFACE) DEFINE_FDO_GET_INTERFACE(Suspend, PXENBUS_SUSPEND_INTERFACE) DEFINE_FDO_GET_INTERFACE(Store, PXENBUS_STORE_INTERFACE) DEFINE_FDO_GET_INTERFACE(Console, PXENBUS_CONSOLE_INTERFACE) +DEFINE_FDO_GET_INTERFACE(Evtchn, PXENBUS_EVTCHN_INTERFACE) +DEFINE_FDO_GET_INTERFACE(Gnttab, PXENBUS_GNTTAB_INTERFACE) #pragma warning(push) #pragma warning(disable:6014) // Leaking memory '&Dx->Link' @@ -3252,10 +3256,28 @@ FdoCreate( if (!NT_SUCCESS(status)) goto fail11; - status = ConsoleCreate(Fdo, &Fdo->Console); + status = FDO_QUERY_INTERFACE(Fdo, + XENBUS, + EVTCHN, + (PINTERFACE)&Fdo->EvtchnInterface, + sizeof(Fdo->EvtchnInterface), + FALSE); if (!NT_SUCCESS(status)) goto fail12; + status = FDO_QUERY_INTERFACE(Fdo, + XENBUS, + GNTTAB, + (PINTERFACE)&Fdo->GnttabInterface, + sizeof(Fdo->GnttabInterface), + FALSE); + if (!NT_SUCCESS(status)) + goto fail13; + + status = ConsoleCreate(Fdo, &Fdo->Console); + if (!NT_SUCCESS(status)) + goto fail14; + FunctionDeviceObject->Flags |= DO_BUFFERED_IO; Dx->Fdo = Fdo; @@ -3272,6 +3294,18 @@ FdoCreate( FunctionDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; return STATUS_SUCCESS; +fail14: + Error("fail14\n"); + + RtlZeroMemory(&Fdo->GnttabInterface, + sizeof(XENBUS_GNTTAB_INTERFACE)); + +fail13: + Error("fail13\n"); + + RtlZeroMemory(&Fdo->EvtchnInterface, + sizeof(XENBUS_EVTCHN_INTERFACE)); + fail12: Error("fail12\n"); @@ -3374,6 +3408,12 @@ FdoDestroy( ConsoleDestroy(Fdo->Console); Fdo->Console = NULL; + RtlZeroMemory(&Fdo->GnttabInterface, + sizeof(XENBUS_GNTTAB_INTERFACE)); + + RtlZeroMemory(&Fdo->EvtchnInterface, + sizeof(XENBUS_EVTCHN_INTERFACE)); + RtlZeroMemory(&Fdo->ConsoleInterface, sizeof (XENBUS_CONSOLE_INTERFACE)); diff --git a/src/xencons/fdo.h b/src/xencons/fdo.h index 189c70f..c61cc55 100644 --- a/src/xencons/fdo.h +++ b/src/xencons/fdo.h @@ -37,6 +37,8 @@ #include <suspend_interface.h> #include <store_interface.h> #include <console_interface.h> +#include <evtchn_interface.h> +#include <gnttab_interface.h> #include "driver.h" @@ -100,6 +102,8 @@ DECLARE_FDO_GET_INTERFACE(Debug, PXENBUS_DEBUG_INTERFACE) DECLARE_FDO_GET_INTERFACE(Suspend, PXENBUS_SUSPEND_INTERFACE) DECLARE_FDO_GET_INTERFACE(Store, PXENBUS_STORE_INTERFACE) DECLARE_FDO_GET_INTERFACE(Console, PXENBUS_CONSOLE_INTERFACE) +DECLARE_FDO_GET_INTERFACE(Evtchn, PXENBUS_EVTCHN_INTERFACE) +DECLARE_FDO_GET_INTERFACE(Gnttab, PXENBUS_GNTTAB_INTERFACE) extern NTSTATUS FdoCreate( diff --git a/src/xencons/frontend.c b/src/xencons/frontend.c index 3cb4f07..fa7443d 100755 --- a/src/xencons/frontend.c +++ b/src/xencons/frontend.c @@ -40,6 +40,7 @@ #include "driver.h" #include "frontend.h" +#include "ring.h" #include "thread.h" #include "dbg_print.h" #include "assert.h" @@ -62,6 +63,7 @@ struct _XENCONS_FRONTEND { PCHAR Name; PCHAR Protocol; + PXENCONS_RING Ring; XENBUS_DEBUG_INTERFACE DebugInterface; XENBUS_SUSPEND_INTERFACE SuspendInterface; @@ -664,9 +666,9 @@ FrontendConnect( if (!NT_SUCCESS(status)) goto fail2; - //status = RingConnect(Frontend->Ring); - //if (!NT_SUCCESS(status)) - // goto fail3; + status = RingConnect(Frontend->Ring); + if (!NT_SUCCESS(status)) + goto fail3; Attempt = 0; do { @@ -678,9 +680,9 @@ FrontendConnect( if (!NT_SUCCESS(status)) break; - //status = RingStoreWrite(Frontend->Ring, Transaction); - //if (!NT_SUCCESS(status)) - // goto abort; + status = RingStoreWrite(Frontend->Ring, Transaction); + if (!NT_SUCCESS(status)) + goto abort; status = XENBUS_STORE(TransactionEnd, &Frontend->StoreInterface, @@ -691,12 +693,12 @@ FrontendConnect( continue; - //abort: - // (VOID)XENBUS_STORE(TransactionEnd, - // &Frontend->StoreInterface, - // Transaction, - // FALSE); - // break; + abort: + (VOID)XENBUS_STORE(TransactionEnd, + &Frontend->StoreInterface, + Transaction, + FALSE); + break; } while (status == STATUS_RETRY); if (!NT_SUCCESS(status)) @@ -747,8 +749,8 @@ fail5: fail4: Error("fail4\n"); -//fail3: -// Error("fail3\n"); +fail3: + Error("fail3\n"); XENBUS_DEBUG(Deregister, &Frontend->DebugInterface, @@ -780,7 +782,7 @@ FrontendDisconnect( __FrontendFree(Frontend->Name); Frontend->Name = NULL; - //RingDisconnect(Frontend->Ring); + RingDisconnect(Frontend->Ring); XENBUS_DEBUG(Deregister, &Frontend->DebugInterface, @@ -797,13 +799,21 @@ FrontendEnable( IN PXENCONS_FRONTEND Frontend ) { + NTSTATUS status; + Trace("====>\n"); - UNREFERENCED_PARAMETER(Frontend); - //RingEnable(Frontend->Ring); + status = RingEnable(Frontend->Ring); + if (!NT_SUCCESS(status)) + goto fail1; Trace("<====\n"); return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; } static VOID @@ -813,8 +823,7 @@ FrontendDisable( { Trace("====>\n"); - UNREFERENCED_PARAMETER(Frontend); - //RingDisable(Frontend->Ring); + RingDisable(Frontend->Ring); Trace("<====\n"); } @@ -1204,8 +1213,19 @@ FrontendCreate( if (!NT_SUCCESS(status)) goto fail4; + status = RingCreate(*Frontend, &(*Frontend)->Ring); + if (!NT_SUCCESS(status)) + goto fail5; + return STATUS_SUCCESS; +fail5: + Error("fail5\n"); + + ThreadAlert((*Frontend)->EjectThread); + ThreadJoin((*Frontend)->EjectThread); + (*Frontend)->EjectThread = NULL; + fail4: Error("fail4\n"); @@ -1256,6 +1276,9 @@ FrontendDestroy( ASSERT(Frontend->State == FRONTEND_UNKNOWN); + RingDestroy(Frontend->Ring); + Frontend->Ring = NULL; + ThreadAlert(Frontend->EjectThread); ThreadJoin(Frontend->EjectThread); Frontend->EjectThread = NULL; diff --git a/src/xencons/ring.c b/src/xencons/ring.c new file mode 100755 index 0000000..321f4e9 --- /dev/null +++ b/src/xencons/ring.c @@ -0,0 +1,578 @@ +/* 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 <ntstrsafe.h> +#include <stdlib.h> +#include <xen.h> + +#include <debug_interface.h> +#include <store_interface.h> +#include <evtchn_interface.h> +#include <gnttab_interface.h> + +#include "frontend.h" +#include "ring.h" +#include "dbg_print.h" +#include "assert.h" +#include "util.h" + +struct _XENCONS_RING { + PXENCONS_FRONTEND Frontend; + KSPIN_LOCK Lock; + PMDL Mdl; + struct xencons_interface *Shared; + PXENBUS_GNTTAB_ENTRY Entry; + BOOLEAN Connected; + BOOLEAN Enabled; + KDPC Dpc; + ULONG Dpcs; + PXENBUS_EVTCHN_CHANNEL Channel; + ULONG Events; + XENBUS_STORE_INTERFACE StoreInterface; + XENBUS_GNTTAB_INTERFACE GnttabInterface; + XENBUS_EVTCHN_INTERFACE EvtchnInterface; + XENBUS_DEBUG_INTERFACE DebugInterface; + PXENBUS_DEBUG_CALLBACK DebugCallback; + PXENBUS_GNTTAB_CACHE GnttabCache; +}; + +#define RING_TAG 'GNIR' +#define MAXNAMELEN 128 + +static FORCEINLINE PVOID +__RingAllocate( + IN ULONG Length + ) +{ + return __AllocatePoolWithTag(NonPagedPool, Length, RING_TAG); +} + +static FORCEINLINE VOID +__RingFree( + IN PVOID Buffer + ) +{ + __FreePoolWithTag(Buffer, RING_TAG); +} + +__drv_requiresIRQL(DISPATCH_LEVEL) +RingAcquireLock( + IN PXENCONS_RING Ring + ) +{ + ASSERT3U(KeGetCurrentIrql(), == , DISPATCH_LEVEL); + + KeAcquireSpinLockAtDpcLevel(&Ring->Lock); +} + +__drv_requiresIRQL(DISPATCH_LEVEL) +RingReleaseLock( + IN PXENCONS_RING Ring + ) +{ + ASSERT3U(KeGetCurrentIrql(), == , DISPATCH_LEVEL); + + KeReleaseSpinLockFromDpcLevel(&Ring->Lock); +} + +static BOOLEAN +RingPoll( + IN PXENCONS_RING Ring + ) +{ + UNREFERENCED_PARAMETER(Ring); + return FALSE; +} + +__drv_functionClass(KDEFERRED_ROUTINE) +__drv_maxIRQL(DISPATCH_LEVEL) +__drv_minIRQL(DISPATCH_LEVEL) +__drv_requiresIRQL(DISPATCH_LEVEL) +__drv_sameIRQL +static VOID +RingDpc( + IN PKDPC Dpc, + IN PVOID Context, + IN PVOID Argument1, + IN PVOID Argument2 + ) +{ + PXENCONS_RING Ring = Context; + + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(Argument1); + UNREFERENCED_PARAMETER(Argument2); + + ASSERT(Ring != NULL); + + for (;;) { + if (!RingPoll(Ring)) + break; + } + + (VOID) XENBUS_EVTCHN(Unmask, + &Ring->EvtchnInterface, + Ring->Channel, + FALSE, + FALSE); +} + +KSERVICE_ROUTINE RingEvtchnCallback; + +BOOLEAN +RingEvtchnCallback( + IN PKINTERRUPT InterruptObject, + IN PVOID Argument + ) +{ + PXENCONS_RING Ring = Argument; + + UNREFERENCED_PARAMETER(InterruptObject); + + ASSERT(Ring != NULL); + + Ring->Events++; + + if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL)) + Ring->Dpcs++; + + return TRUE; +} + +static VOID +RingDebugCallback( + IN PVOID Argument, + IN BOOLEAN Crashing + ) +{ + PXENCONS_RING Ring = Argument; + + UNREFERENCED_PARAMETER(Crashing); + + XENBUS_DEBUG(Printf, + &Ring->DebugInterface, + "0x%p [%s]\n", + Ring, + (Ring->Enabled) ? "ENABLED" : "DISABLED"); + + XENBUS_DEBUG(Printf, + &Ring->DebugInterface, + "Events = %lu, Dpcs = %lu\n", + Ring->Events, + Ring->Dpcs); + + XENBUS_DEBUG(Printf, + &Ring->DebugInterface, + "SHARED: in_cons = %u in_prod = %u out_cons = %u out_prod = %u\n", + Ring->Shared->in_cons, + Ring->Shared->in_prod, + Ring->Shared->out_cons, + Ring->Shared->out_prod); + + // Raw Dump of in/out buffers? +} + +NTSTATUS +RingConnect( + IN PXENCONS_RING Ring + ) +{ + CHAR Name[MAXNAMELEN]; + PFN_NUMBER Pfn; + NTSTATUS status; + + Trace("=====>\n"); + + status = XENBUS_DEBUG(Acquire, &Ring->DebugInterface); + if (!NT_SUCCESS(status)) + goto fail1; + + status = XENBUS_STORE(Acquire, &Ring->StoreInterface); + if (!NT_SUCCESS(status)) + goto fail2; + + status = XENBUS_EVTCHN(Acquire, &Ring->EvtchnInterface); + if (!NT_SUCCESS(status)) + goto fail3; + + status = XENBUS_GNTTAB(Acquire, &Ring->GnttabInterface); + if (!NT_SUCCESS(status)) + goto fail4; + + status = RtlStringCbPrintfA(Name, + sizeof(Name), + "xencons_%s_gnttab", + PdoGetName(FrontendGetPdo(Ring->Frontend))); + if (!NT_SUCCESS(status)) + goto fail5; + + status = XENBUS_GNTTAB(CreateCache, + &Ring->GnttabInterface, + Name, + 0, + RingAcquireLock, + RingReleaseLock, + Ring, + &Ring->GnttabCache); + if (!NT_SUCCESS(status)) + goto fail6; + + Ring->Mdl = __AllocatePage(); + + status = STATUS_NO_MEMORY; + if (Ring->Mdl == NULL) + goto fail7; + + ASSERT(Ring->Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA); + Ring->Shared = Ring->Mdl->MappedSystemVa; + ASSERT(Ring->Shared != NULL); + + Pfn = MmGetMdlPfnArray(Ring->Mdl)[0]; + + status = XENBUS_GNTTAB(PermitForeignAccess, + &Ring->GnttabInterface, + Ring->GnttabCache, + TRUE, + FrontendGetBackendDomain(Ring->Frontend), + Pfn, + FALSE, + &Ring->Entry); + if (!NT_SUCCESS(status)) + goto fail8; + + Ring->Channel = XENBUS_EVTCHN(Open, + &Ring->EvtchnInterface, + XENBUS_EVTCHN_TYPE_UNBOUND, + RingEvtchnCallback, + Ring, + FrontendGetBackendDomain(Ring->Frontend), + TRUE); + + status = STATUS_UNSUCCESSFUL; + if (Ring->Channel == NULL) + goto fail9; + + (VOID)XENBUS_EVTCHN(Unmask, + &Ring->EvtchnInterface, + Ring->Channel, + FALSE, + TRUE); + + ASSERT(!Ring->Connected); + Ring->Connected = TRUE; + + status = XENBUS_DEBUG(Register, + &Ring->DebugInterface, + __MODULE__ "|RING", + RingDebugCallback, + Ring, + &Ring->DebugCallback); + if (!NT_SUCCESS(status)) + goto fail10; + + Trace("<=====\n"); + return STATUS_SUCCESS; + +fail10: + Error("fail10\n"); + + Ring->Connected = FALSE; + + XENBUS_EVTCHN(Close, + &Ring->EvtchnInterface, + Ring->Channel); + Ring->Channel = NULL; + +fail9: + Error("fail9\n"); + + (VOID)XENBUS_GNTTAB(RevokeForeignAccess, + &Ring->GnttabInterface, + Ring->GnttabCache, + TRUE, + Ring->Entry); + Ring->Entry = NULL; + +fail8: + Error("fail8\n"); + + RtlZeroMemory(Ring->Shared, PAGE_SIZE); + + Ring->Shared = NULL; + __FreePage(Ring->Mdl); + Ring->Mdl = NULL; + + +fail7: + Error("fail7\n"); + + XENBUS_GNTTAB(DestroyCache, + &Ring->GnttabInterface, + Ring->GnttabCache); + Ring->GnttabCache = NULL; + +fail6: + Error("fail6\n"); + +fail5: + Error("fail5\n"); + + XENBUS_GNTTAB(Release, &Ring->GnttabInterface); + +fail4: + Error("fail4\n"); + + XENBUS_EVTCHN(Release, &Ring->EvtchnInterface); + +fail3: + Error("fail3\n"); + + XENBUS_STORE(Release, &Ring->StoreInterface); + +fail2: + Error("fail2\n"); + + XENBUS_DEBUG(Release, &Ring->DebugInterface); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +NTSTATUS +RingStoreWrite( + IN PXENCONS_RING Ring, + IN PVOID Transaction + ) +{ + ULONG GrantRef; + ULONG Port; + NTSTATUS status; + + Port = XENBUS_EVTCHN(GetPort, + &Ring->EvtchnInterface, + Ring->Channel); + + status = XENBUS_STORE(Printf, + &Ring->StoreInterface, + Transaction, + FrontendGetPath(Ring->Frontend), + "port", + "%u", + Port); + if (!NT_SUCCESS(status)) + goto fail1; + + GrantRef = XENBUS_GNTTAB(GetReference, + &Ring->GnttabInterface, + Ring->Entry); + + status = XENBUS_STORE(Printf, + &Ring->StoreInterface, + Transaction, + FrontendGetPath(Ring->Frontend), + "ring-ref", + "%u", + GrantRef); + if (!NT_SUCCESS(status)) + goto fail2; + + return STATUS_SUCCESS; + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +NTSTATUS +RingEnable( + IN PXENCONS_RING Ring + ) +{ + Trace("=====>\n"); + + ASSERT3U(KeGetCurrentIrql(), == , DISPATCH_LEVEL); + + KeAcquireSpinLockAtDpcLevel(&Ring->Lock); + Ring->Enabled = TRUE; + KeReleaseSpinLockFromDpcLevel(&Ring->Lock); + + (VOID)KeInsertQueueDpc(&Ring->Dpc, NULL, NULL); + + Trace("<=====\n"); + return STATUS_SUCCESS; +} + +VOID +RingDisable( + IN PXENCONS_RING Ring + ) +{ + Trace("=====>\n"); + + // empty queue(s) + + ASSERT3U(KeGetCurrentIrql(), == , DISPATCH_LEVEL); + + KeAcquireSpinLockAtDpcLevel(&Ring->Lock); + Ring->Enabled = FALSE; + KeReleaseSpinLockFromDpcLevel(&Ring->Lock); + + Trace("<=====\n"); +} + +VOID +RingDisconnect( + IN PXENCONS_RING Ring + ) +{ + Trace("=====>\n"); + + XENBUS_DEBUG(Deregister, + &Ring->DebugInterface, + Ring->DebugCallback); + Ring->DebugCallback = NULL; + + ASSERT(Ring->Connected); + Ring->Connected = FALSE; + + ASSERT3U(KeGetCurrentIrql(), == , DISPATCH_LEVEL); + + Ring->Dpcs = 0; + + Ring->Events = 0; + + XENBUS_EVTCHN(Close, + &Ring->EvtchnInterface, + Ring->Channel); + Ring->Channel = NULL; + + (VOID)XENBUS_GNTTAB(RevokeForeignAccess, + &Ring->GnttabInterface, + Ring->GnttabCache, + TRUE, + Ring->Entry); + Ring->Entry = NULL; + + RtlZeroMemory(Ring->Shared, PAGE_SIZE); + + Ring->Shared = NULL; + __FreePage(Ring->Mdl); + Ring->Mdl = NULL; + + XENBUS_GNTTAB(DestroyCache, + &Ring->GnttabInterface, + Ring->GnttabCache); + Ring->GnttabCache = NULL; + + XENBUS_GNTTAB(Release, &Ring->GnttabInterface); + + XENBUS_EVTCHN(Release, &Ring->EvtchnInterface); + + XENBUS_STORE(Release, &Ring->StoreInterface); + + XENBUS_DEBUG(Release, &Ring->DebugInterface); + + Trace("<=====\n"); +} + +NTSTATUS +RingCreate( + IN PXENCONS_FRONTEND Frontend, + OUT PXENCONS_RING *Ring + ) +{ + NTSTATUS status; + + *Ring = __RingAllocate(sizeof(XENCONS_RING)); + + status = STATUS_NO_MEMORY; + if (*Ring == NULL) + goto fail1; + + (*Ring)->Frontend = Frontend; + + FdoGetGnttabInterface(PdoGetFdo(FrontendGetPdo(Frontend)), + &(*Ring)->GnttabInterface); + + FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)), + &(*Ring)->EvtchnInterface); + + FdoGetStoreInterface(PdoGetFdo(FrontendGetPdo(Frontend)), + &(*Ring)->StoreInterface); + + FdoGetDebugInterface(PdoGetFdo(FrontendGetPdo(Frontend)), + &(*Ring)->DebugInterface); + + KeInitializeSpinLock(&(*Ring)->Lock); + + KeInitializeDpc(&(*Ring)->Dpc, RingDpc, *Ring); + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +VOID +RingDestroy( + IN PXENCONS_RING Ring + ) +{ + RtlZeroMemory(&Ring->Dpc, sizeof(KDPC)); + + RtlZeroMemory(&Ring->Lock, sizeof(KSPIN_LOCK)); + + RtlZeroMemory(&Ring->GnttabInterface, + sizeof(XENBUS_GNTTAB_INTERFACE)); + + RtlZeroMemory(&Ring->EvtchnInterface, + sizeof(XENBUS_EVTCHN_INTERFACE)); + + RtlZeroMemory(&Ring->StoreInterface, + sizeof(XENBUS_STORE_INTERFACE)); + + RtlZeroMemory(&Ring->DebugInterface, + sizeof(XENBUS_DEBUG_INTERFACE)); + + Ring->Frontend = NULL; + + ASSERT(IsZeroMemory(Ring, sizeof(XENCONS_RING))); + __RingFree(Ring); +} diff --git a/src/xencons/ring.h b/src/xencons/ring.h new file mode 100755 index 0000000..e9f549d --- /dev/null +++ b/src/xencons/ring.h @@ -0,0 +1,78 @@ +/* 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 _XENCONS_RING_H +#define _XENCONS_RING_H + +#include <ntddk.h> + +typedef struct _XENCONS_RING XENCONS_RING, *PXENCONS_RING; + +#include "frontend.h" + +extern NTSTATUS +RingCreate( + IN PXENCONS_FRONTEND Frontend, + OUT PXENCONS_RING *Ring + ); + +extern VOID +RingDestroy( + IN PXENCONS_RING Ring + ); + +extern NTSTATUS +RingConnect( + IN PXENCONS_RING Ring + ); + +extern NTSTATUS +RingStoreWrite( + IN PXENCONS_RING Ring, + IN PVOID Transaction + ); + +extern NTSTATUS +RingEnable( + IN PXENCONS_RING Ring + ); + +extern VOID +RingDisable( + IN PXENCONS_RING Ring + ); + +extern VOID +RingDisconnect( + IN PXENCONS_RING Ring + ); + +#endif // _XENCONS_RING_H diff --git a/vs2015/xencons/xencons.vcxproj b/vs2015/xencons/xencons.vcxproj index 3a1b934..a2fe7d6 100644 --- a/vs2015/xencons/xencons.vcxproj +++ b/vs2015/xencons/xencons.vcxproj @@ -68,6 +68,7 @@ <ClCompile Include="../../src/xencons/fdo.c" /> <ClCompile Include="../../src/xencons/pdo.c" /> <ClCompile Include="../../src/xencons/frontend.c" /> + <ClCompile Include="../../src/xencons/ring.c" /> <ClCompile Include="../../src/xencons/registry.c" /> <ClCompile Include="../../src/xencons/console.c" /> <ClCompile Include="../../src/xencons/stream.c" /> -- 2.8.3 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |