IN PVOID Argument
);
+typedef NTSTATUS
+(*XENBUS_CACHE_CREATE_V1)(
+ 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_CREATE
\brief Create a cache of objects of the given \a Size
\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 Cap The maximum 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
IN const CHAR *Name,
IN ULONG Size,
IN ULONG Reservation,
+ IN ULONG Cap,
IN XENBUS_CACHE_CTOR Ctor,
IN XENBUS_CACHE_DTOR Dtor,
IN XENBUS_CACHE_ACQUIRE_LOCK AcquireLock,
\ingroup interfaces
*/
struct _XENBUS_CACHE_INTERFACE_V1 {
+ INTERFACE Interface;
+ XENBUS_CACHE_ACQUIRE CacheAcquire;
+ XENBUS_CACHE_RELEASE CacheRelease;
+ XENBUS_CACHE_CREATE_V1 CacheCreateVersion1;
+ XENBUS_CACHE_GET CacheGet;
+ XENBUS_CACHE_PUT CachePut;
+ XENBUS_CACHE_DESTROY CacheDestroy;
+};
+
+/*! \struct _XENBUS_CACHE_INTERFACE_V2
+ \brief CACHE interface version 1
+ \ingroup interfaces
+*/
+struct _XENBUS_CACHE_INTERFACE_V2 {
INTERFACE Interface;
XENBUS_CACHE_ACQUIRE CacheAcquire;
XENBUS_CACHE_RELEASE CacheRelease;
XENBUS_CACHE_DESTROY CacheDestroy;
};
-typedef struct _XENBUS_CACHE_INTERFACE_V1 XENBUS_CACHE_INTERFACE, *PXENBUS_CACHE_INTERFACE;
+typedef struct _XENBUS_CACHE_INTERFACE_V2 XENBUS_CACHE_INTERFACE, *PXENBUS_CACHE_INTERFACE;
/*! \def XENBUS_CACHE
\brief Macro at assist in method invocation
#endif // _WINDLL
#define XENBUS_CACHE_INTERFACE_VERSION_MIN 1
-#define XENBUS_CACHE_INTERFACE_VERSION_MAX 1
+#define XENBUS_CACHE_INTERFACE_VERSION_MAX 2
#endif // _XENBUS_CACHE_INTERFACE_H
IN PINTERFACE Interface
);
+typedef NTSTATUS
+(*XENBUS_GNTTAB_CREATE_CACHE_V1)(
+ 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_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 Cap The maximum 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
IN PINTERFACE Interface,
IN const CHAR *Name,
IN ULONG Reservation,
+ IN ULONG Cap,
IN XENBUS_CACHE_ACQUIRE_LOCK AcquireLock,
IN XENBUS_CACHE_RELEASE_LOCK ReleaseLock,
IN PVOID Argument OPTIONAL,
INTERFACE Interface;
XENBUS_GNTTAB_ACQUIRE GnttabAcquire;
XENBUS_GNTTAB_RELEASE GnttabRelease;
- XENBUS_GNTTAB_CREATE_CACHE GnttabCreateCache;
+ XENBUS_GNTTAB_CREATE_CACHE_V1 GnttabCreateCacheVersion1;
XENBUS_GNTTAB_PERMIT_FOREIGN_ACCESS GnttabPermitForeignAccess;
XENBUS_GNTTAB_REVOKE_FOREIGN_ACCESS GnttabRevokeForeignAccess;
XENBUS_GNTTAB_GET_REFERENCE GnttabGetReference;
INTERFACE Interface;
XENBUS_GNTTAB_ACQUIRE GnttabAcquire;
XENBUS_GNTTAB_RELEASE GnttabRelease;
- XENBUS_GNTTAB_CREATE_CACHE GnttabCreateCache;
+ XENBUS_GNTTAB_CREATE_CACHE_V1 GnttabCreateCacheVersion1;
XENBUS_GNTTAB_PERMIT_FOREIGN_ACCESS GnttabPermitForeignAccess;
XENBUS_GNTTAB_REVOKE_FOREIGN_ACCESS GnttabRevokeForeignAccess;
XENBUS_GNTTAB_GET_REFERENCE GnttabGetReference;
\ingroup interfaces
*/
struct _XENBUS_GNTTAB_INTERFACE_V3 {
+ INTERFACE Interface;
+ XENBUS_GNTTAB_ACQUIRE GnttabAcquire;
+ XENBUS_GNTTAB_RELEASE GnttabRelease;
+ XENBUS_GNTTAB_CREATE_CACHE_V1 GnttabCreateCacheVersion1;
+ 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;
+};
+
+/*! \struct _XENBUS_GNTTAB_INTERFACE_V4
+ \brief GNTTAB interface version 4
+ \ingroup interfaces
+*/
+struct _XENBUS_GNTTAB_INTERFACE_V4 {
INTERFACE Interface;
XENBUS_GNTTAB_ACQUIRE GnttabAcquire;
XENBUS_GNTTAB_RELEASE GnttabRelease;
XENBUS_GNTTAB_UNMAP_FOREIGN_PAGES GnttabUnmapForeignPages;
};
-typedef struct _XENBUS_GNTTAB_INTERFACE_V3 XENBUS_GNTTAB_INTERFACE, *PXENBUS_GNTTAB_INTERFACE;
+typedef struct _XENBUS_GNTTAB_INTERFACE_V4 XENBUS_GNTTAB_INTERFACE, *PXENBUS_GNTTAB_INTERFACE;
/*! \def XENBUS_GNTTAB
\brief Macro at assist in method invocation
#endif // _WINDLL
#define XENBUS_GNTTAB_INTERFACE_VERSION_MIN 1
-#define XENBUS_GNTTAB_INTERFACE_VERSION_MAX 3
+#define XENBUS_GNTTAB_INTERFACE_VERSION_MAX 4
#endif // _XENBUS_GNTTAB_INTERFACE_H
DEFINE_REVISION(0x09000001, 1, 2, 6, 1, 2, 1, 1, 2, 1, 1, 1), \
DEFINE_REVISION(0x09000002, 1, 2, 7, 1, 2, 1, 1, 2, 1, 1, 1), \
DEFINE_REVISION(0x09000003, 1, 2, 8, 1, 2, 1, 1, 2, 1, 1, 1), \
- DEFINE_REVISION(0x09000004, 1, 2, 8, 1, 2, 1, 1, 3, 1, 1, 1)
+ DEFINE_REVISION(0x09000004, 1, 2, 8, 1, 2, 1, 1, 3, 1, 1, 1), \
+ DEFINE_REVISION(0x09000005, 1, 2, 8, 1, 2, 1, 2, 4, 1, 1, 1)
#endif // _REVISION_H
CHAR Name[MAXNAMELEN];
ULONG Size;
ULONG Reservation;
+ ULONG Cap;
NTSTATUS (*Ctor)(PVOID, PVOID);
VOID (*Dtor)(PVOID, PVOID);
VOID (*AcquireLock)(PVOID);
{
PXENBUS_CACHE_SLAB Slab;
ULONG NumberOfBytes;
+ ULONG Count;
LARGE_INTEGER LowAddress;
LARGE_INTEGER HighAddress;
LARGE_INTEGER Boundary;
NumberOfBytes = P2ROUNDUP(FIELD_OFFSET(XENBUS_CACHE_SLAB, Buffer) +
Cache->Size,
PAGE_SIZE);
+ Count = (NumberOfBytes - FIELD_OFFSET(XENBUS_CACHE_SLAB, Buffer)) /
+ Cache->Size;
+ ASSERT(Count != 0);
+
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ if (Cache->Count + Count > Cache->Cap)
+ goto fail1;
LowAddress.QuadPart = 0ull;
HighAddress.QuadPart = ~0ull;
status = STATUS_NO_MEMORY;
if (Slab == NULL)
- goto fail1;
+ goto fail2;
RtlZeroMemory(Slab, NumberOfBytes);
Slab->Magic = XENBUS_CACHE_SLAB_MAGIC;
Slab->Cache = Cache;
- Slab->Count = (NumberOfBytes -
- FIELD_OFFSET(XENBUS_CACHE_SLAB, Buffer)) /
- Cache->Size;
- ASSERT(Slab->Count != 0);
+ Slab->Count = Count;
for (Index = 0; Index < (LONG)Slab->Count; Index++) {
PVOID Object = (PVOID)&Slab->Buffer[Index * Cache->Size];
status = __CacheCtor(Cache, Object);
if (!NT_SUCCESS(status))
- goto fail2;
+ goto fail3;
}
CacheInsertSlab(Cache, Slab);
- Cache->Count += Slab->Count;
+ Cache->Count += Count;
return Slab;
-fail2:
+fail3:
+ Error("fail3\n");
+
while (--Index >= 0) {
PVOID Object = (PVOID)&Slab->Buffer[Index * Cache->Size];
MmFreeContiguousMemory(Slab);
+fail2:
+ Error("fail2\n");
+
fail1:
Error("fail1 (%08x)\n", status);
IN const CHAR *Name,
IN ULONG Size,
IN ULONG Reservation,
+ IN ULONG Cap,
IN NTSTATUS (*Ctor)(PVOID, PVOID),
IN VOID (*Dtor)(PVOID, PVOID),
IN VOID (*AcquireLock)(PVOID),
Size = __max(Size, MINIMUM_OBJECT_SIZE);
Size = P2ROUNDUP(Size, sizeof (ULONG_PTR));
+ if (Cap == 0)
+ Cap = ULONG_MAX;
+
(*Cache)->Size = Size;
(*Cache)->Reservation = Reservation;
+ (*Cache)->Cap = Cap;
(*Cache)->Ctor = Ctor;
(*Cache)->Dtor = Dtor;
(*Cache)->AcquireLock = AcquireLock;
InitializeListHead(&(*Cache)->SlabList);
+ status = STATUS_INVALID_PARAMETER;
+ if ((*Cache)->Reservation > (*Cache)->Cap)
+ goto fail3;
+
if ((*Cache)->Reservation != 0) {
status = __CacheFill(*Cache);
if (!NT_SUCCESS(status))
- goto fail3;
+ goto fail4;
}
(*Cache)->MagazineCount = KeQueryMaximumProcessorCountEx(ALL_PROCESSOR_GROUPS);
status = STATUS_NO_MEMORY;
if ((*Cache)->Magazine == NULL)
- goto fail4;
+ goto fail5;
KeAcquireSpinLock(&Context->Lock, &Irql);
InsertTailList(&Context->List, &(*Cache)->ListEntry);
return STATUS_SUCCESS;
-fail4:
- Error("fail4\n");
+fail5:
+ Error("fail5\n");
(*Cache)->MagazineCount = 0;
__CacheEmpty(*Cache);
+fail4:
+ Error("fail4\n");
+
fail3:
Error("fail3\n");
(*Cache)->AcquireLock = NULL;
(*Cache)->Dtor = NULL;
(*Cache)->Ctor = NULL;
+ (*Cache)->Cap = 0;
+ (*Cache)->Reservation = 0;
(*Cache)->Size = 0;
fail2:
return status;
}
+static NTSTATUS
+CacheCreateVersion1(
+ IN PINTERFACE Interface,
+ IN const CHAR *Name,
+ IN ULONG Size,
+ IN ULONG Reservation,
+ IN NTSTATUS (*Ctor)(PVOID, PVOID),
+ IN VOID (*Dtor)(PVOID, PVOID),
+ IN VOID (*AcquireLock)(PVOID),
+ IN VOID (*ReleaseLock)(PVOID),
+ IN PVOID Argument,
+ OUT PXENBUS_CACHE *Cache
+ )
+{
+ return CacheCreate(Interface,
+ Name,
+ Size,
+ Reservation,
+ 0,
+ Ctor,
+ Dtor,
+ AcquireLock,
+ ReleaseLock,
+ Argument,
+ Cache);
+}
+
static VOID
CacheDestroy(
IN PINTERFACE Interface,
Cache->AcquireLock = NULL;
Cache->Dtor = NULL;
Cache->Ctor = NULL;
+ Cache->Cap = 0;
+ Cache->Reservation = 0;
Cache->Size = 0;
RtlZeroMemory(Cache->Name, sizeof (Cache->Name));
{ sizeof (struct _XENBUS_CACHE_INTERFACE_V1), 1, NULL, NULL, NULL },
CacheAcquire,
CacheRelease,
+ CacheCreateVersion1,
+ CacheGet,
+ CachePut,
+ CacheDestroy
+};
+
+static struct _XENBUS_CACHE_INTERFACE_V2 CacheInterfaceVersion2 = {
+ { sizeof (struct _XENBUS_CACHE_INTERFACE_V2), 2, NULL, NULL, NULL },
+ CacheAcquire,
+ CacheRelease,
CacheCreate,
CacheGet,
CachePut,
status = STATUS_SUCCESS;
break;
}
+ case 2: {
+ struct _XENBUS_CACHE_INTERFACE_V2 *CacheInterface;
+
+ CacheInterface = (struct _XENBUS_CACHE_INTERFACE_V2 *)Interface;
+
+ status = STATUS_BUFFER_OVERFLOW;
+ if (Size < sizeof (struct _XENBUS_CACHE_INTERFACE_V2))
+ break;
+
+ *CacheInterface = CacheInterfaceVersion2;
+
+ ASSERT3U(Interface->Version, ==, Version);
+ Interface->Context = Context;
+
+ status = STATUS_SUCCESS;
+ break;
+ }
default:
status = STATUS_NOT_SUPPORTED;
break;
IN PINTERFACE Interface,
IN const CHAR *Name,
IN ULONG Reservation,
+ IN ULONG Cap,
IN VOID (*AcquireLock)(PVOID),
IN VOID (*ReleaseLock)(PVOID),
IN PVOID Argument,
(*Cache)->Name,
sizeof (XENBUS_GNTTAB_ENTRY),
Reservation,
+ Cap,
GnttabEntryCtor,
GnttabEntryDtor,
GnttabAcquireLock,
return status;
}
+static NTSTATUS
+GnttabCreateCacheVersion1(
+ IN PINTERFACE Interface,
+ IN const CHAR *Name,
+ IN ULONG Reservation,
+ IN VOID (*AcquireLock)(PVOID),
+ IN VOID (*ReleaseLock)(PVOID),
+ IN PVOID Argument,
+ OUT PXENBUS_GNTTAB_CACHE *Cache
+ )
+{
+ return GnttabCreateCache(Interface,
+ Name,
+ Reservation,
+ 0,
+ AcquireLock,
+ ReleaseLock,
+ Argument,
+ Cache);
+}
+
static VOID
GnttabDestroyCache(
IN PINTERFACE Interface,
{ sizeof (struct _XENBUS_GNTTAB_INTERFACE_V1), 1, NULL, NULL, NULL },
GnttabAcquire,
GnttabRelease,
- GnttabCreateCache,
+ GnttabCreateCacheVersion1,
GnttabPermitForeignAccess,
GnttabRevokeForeignAccess,
GnttabGetReference,
{ sizeof (struct _XENBUS_GNTTAB_INTERFACE_V2), 2, NULL, NULL, NULL },
GnttabAcquire,
GnttabRelease,
- GnttabCreateCache,
+ GnttabCreateCacheVersion1,
GnttabPermitForeignAccess,
GnttabRevokeForeignAccess,
GnttabGetReference,
{ sizeof (struct _XENBUS_GNTTAB_INTERFACE_V3), 3, NULL, NULL, NULL },
GnttabAcquire,
GnttabRelease,
+ GnttabCreateCacheVersion1,
+ GnttabPermitForeignAccess,
+ GnttabRevokeForeignAccess,
+ GnttabGetReference,
+ GnttabQueryReference,
+ GnttabDestroyCache,
+ GnttabMapForeignPages,
+ GnttabUnmapForeignPages
+};
+
+static struct _XENBUS_GNTTAB_INTERFACE_V4 GnttabInterfaceVersion4 = {
+ { sizeof (struct _XENBUS_GNTTAB_INTERFACE_V4), 4, NULL, NULL, NULL },
+ GnttabAcquire,
+ GnttabRelease,
GnttabCreateCache,
GnttabPermitForeignAccess,
GnttabRevokeForeignAccess,
status = STATUS_SUCCESS;
break;
}
+ case 4: {
+ struct _XENBUS_GNTTAB_INTERFACE_V4 *GnttabInterface;
+
+ GnttabInterface = (struct _XENBUS_GNTTAB_INTERFACE_V4 *)Interface;
+
+ status = STATUS_BUFFER_OVERFLOW;
+ if (Size < sizeof (struct _XENBUS_GNTTAB_INTERFACE_V4))
+ break;
+
+ *GnttabInterface = GnttabInterfaceVersion4;
+
+ ASSERT3U(Interface->Version, ==, Version);
+ Interface->Context = Context;
+
+ status = STATUS_SUCCESS;
+ break;
+ }
default:
status = STATUS_NOT_SUPPORTED;
break;