|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC XENBUS PATCH 1/1] Add GNTTAB_INTERFACE_V5
Avoid retrying and calling SCHEDOP_yield in RevokeForeignAccess. Leave
the retry logic to the individual drivers instead, because individual
drivers need to revoke grants in the background to avoid having backends
trample over pages that have an active grant entry yet have already been
released to the OS.
RevokeForeignAccessV2 continues providing the retry logic to legacy
clients.
Note that RevokeForeignAccess in GNTTAB_INTERFACE_V5 cannot
transparently replace RevokeForeignAccessV2 because of semantic changes.
Migrating to GNTTAB_INTERFACE_V5 requires reimplementing the drivers'
grant revocation path.
Assisted-by: LLM
Signed-off-by: Tu Dinh <ngoc-tu.dinh@xxxxxxxxxx>
---
This silently changes the semantics of RevokeForeignAccess. I can rename
it to e.g. TryRevokeForeignAccess if that is preferable.
---
include/gnttab_interface.h | 90 ++++++++++++++++++++++++++++----------
include/revision.h | 3 +-
src/xenbus/gnttab.c | 77 +++++++++++++++++++++++++++-----
3 files changed, 135 insertions(+), 35 deletions(-)
diff --git a/include/gnttab_interface.h b/include/gnttab_interface.h
index 92a95a7..3ca4407 100644
--- a/include/gnttab_interface.h
+++ b/include/gnttab_interface.h
@@ -132,6 +132,26 @@ typedef NTSTATUS
_Outptr_ PXENBUS_GNTTAB_ENTRY *Entry
);
+/*! \typedef XENBUS_GNTTAB_REVOKE_FOREIGN_ACCESS_V2
+ \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
+
+ If the foreign domain is still accessing the granted page, this retries
+ for a while before giving up.
+*/
+typedef NTSTATUS
+(*XENBUS_GNTTAB_REVOKE_FOREIGN_ACCESS_V2)(
+ _In_ PINTERFACE Interface,
+ _In_ PXENBUS_GNTTAB_CACHE Cache,
+ _In_ BOOLEAN Locked,
+ _In_ PXENBUS_GNTTAB_ENTRY Entry
+ );
+
/*! \typedef XENBUS_GNTTAB_REVOKE_FOREIGN_ACCESS
\brief Revoke foreign access and return the \a Entry to the \a Cache
@@ -140,6 +160,12 @@ typedef NTSTATUS
\param Locked If mutually exclusive access to the cache is already
guaranteed then set this to TRUE
\param Entry The grant table entry handle
+ \return STATUS_DEVICE_BUSY if the foreign domain is still accessing the
+ granted page
+
+ This does not wait for the foreign domain. On failure, foreign access
+ remains in effect and \a Entry remains valid: the caller must keep the
+ granted page alive, and should retry the revocation later.
*/
typedef NTSTATUS
(*XENBUS_GNTTAB_REVOKE_FOREIGN_ACCESS)(
@@ -239,16 +265,16 @@ DEFINE_GUID(GUID_XENBUS_GNTTAB_INTERFACE,
\ingroup interfaces
*/
struct _XENBUS_GNTTAB_INTERFACE_V2 {
- 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_DESTROY_CACHE GnttabDestroyCache;
- XENBUS_GNTTAB_MAP_FOREIGN_PAGES GnttabMapForeignPages;
- XENBUS_GNTTAB_UNMAP_FOREIGN_PAGES GnttabUnmapForeignPages;
+ 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_V2 GnttabRevokeForeignAccessVersion2;
+ 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
@@ -256,17 +282,17 @@ struct _XENBUS_GNTTAB_INTERFACE_V2 {
\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;
+ 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_V2 GnttabRevokeForeignAccessVersion2;
+ 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
@@ -274,6 +300,24 @@ struct _XENBUS_GNTTAB_INTERFACE_V3 {
\ingroup interfaces
*/
struct _XENBUS_GNTTAB_INTERFACE_V4 {
+ 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_V2 GnttabRevokeForeignAccessVersion2;
+ 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_V5
+ \brief GNTTAB interface version 5
+ \ingroup interfaces
+*/
+struct _XENBUS_GNTTAB_INTERFACE_V5 {
INTERFACE Interface;
XENBUS_GNTTAB_ACQUIRE GnttabAcquire;
XENBUS_GNTTAB_RELEASE GnttabRelease;
@@ -287,7 +331,7 @@ struct _XENBUS_GNTTAB_INTERFACE_V4 {
XENBUS_GNTTAB_UNMAP_FOREIGN_PAGES GnttabUnmapForeignPages;
};
-typedef struct _XENBUS_GNTTAB_INTERFACE_V4 XENBUS_GNTTAB_INTERFACE,
*PXENBUS_GNTTAB_INTERFACE;
+typedef struct _XENBUS_GNTTAB_INTERFACE_V5 XENBUS_GNTTAB_INTERFACE,
*PXENBUS_GNTTAB_INTERFACE;
/*! \def XENBUS_GNTTAB
\brief Macro at assist in method invocation
@@ -298,6 +342,6 @@ typedef struct _XENBUS_GNTTAB_INTERFACE_V4
XENBUS_GNTTAB_INTERFACE, *PXENBUS_GNT
#endif // _WINDLL
#define XENBUS_GNTTAB_INTERFACE_VERSION_MIN 2
-#define XENBUS_GNTTAB_INTERFACE_VERSION_MAX 4
+#define XENBUS_GNTTAB_INTERFACE_VERSION_MAX 5
#endif // _XENBUS_GNTTAB_INTERFACE_H
diff --git a/include/revision.h b/include/revision.h
index a63e550..c1ab047 100644
--- a/include/revision.h
+++ b/include/revision.h
@@ -52,6 +52,7 @@
DEFINE_REVISION(0x09000009, 1, 4, 9, 1, 2, 1, 2, 4, 1, 1, 2), \
DEFINE_REVISION(0x0900000A, 1, 4, 9, 1, 2, 1, 2, 4, 2, 1, 2), \
DEFINE_REVISION(0x0900000B, 1, 4, 9, 1, 2, 1, 2, 4, 3, 1, 2), \
- DEFINE_REVISION(0x0900000C, 1, 4, 9, 1, 2, 1, 2, 4, 3, 1, 3)
+ DEFINE_REVISION(0x0900000C, 1, 4, 9, 1, 2, 1, 2, 4, 3, 1, 3), \
+ DEFINE_REVISION(0x0900000D, 1, 4, 9, 1, 2, 1, 2, 5, 3, 1, 3)
#endif // _REVISION_H
diff --git a/src/xenbus/gnttab.c b/src/xenbus/gnttab.c
index bdf8b2b..47be658 100644
--- a/src/xenbus/gnttab.c
+++ b/src/xenbus/gnttab.c
@@ -559,7 +559,6 @@ GnttabRevokeForeignAccess(
PXENBUS_GNTTAB_FRAME Frame;
ULONG Index;
volatile SHORT *flags;
- ULONG Attempt;
NTSTATUS status;
ASSERT3U(Entry->Magic, ==, XENBUS_GNTTAB_ENTRY_MAGIC);
@@ -571,25 +570,21 @@ GnttabRevokeForeignAccess(
flags = (volatile SHORT *)&Frame->Entry[Index].flags;
- for (Attempt = 0; Attempt < 100; Attempt++) {
+ for (;;) {
uint16_t Old;
uint16_t New;
Old = *flags;
- Old &= ~(GTF_reading | GTF_writing);
+
+ if (Old & (GTF_reading | GTF_writing))
+ return STATUS_DEVICE_BUSY;
New = Old & ~GTF_permit_access;
if (InterlockedCompareExchange16(flags, New, Old) == Old)
break;
-
- SchedYield();
}
- status = STATUS_UNSUCCESSFUL;
- if (Attempt == 100)
- goto fail1;
-
RtlZeroMemory(&Frame->Entry[Index], sizeof (grant_entry_v1_t));
RtlZeroMemory(&Entry->Entry, sizeof (grant_entry_v1_t));
@@ -600,6 +595,35 @@ GnttabRevokeForeignAccess(
Locked);
return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+GnttabRevokeForeignAccessVersion2(
+ _In_ PINTERFACE Interface,
+ _In_ PXENBUS_GNTTAB_CACHE Cache,
+ _In_ BOOLEAN Locked,
+ _In_ PXENBUS_GNTTAB_ENTRY Entry
+ )
+{
+ ULONG Attempt;
+ NTSTATUS status;
+
+ for (Attempt = 0; Attempt < 100; Attempt++) {
+ status = GnttabRevokeForeignAccess(Interface,
+ Cache,
+ Locked,
+ Entry);
+ if (NT_SUCCESS(status))
+ break;
+
+ SchedYield();
+ }
+
+ status = STATUS_UNSUCCESSFUL;
+ if (Attempt == 100)
+ goto fail1;
+
+ return STATUS_SUCCESS;
fail1:
Error("fail1 (%08x)\n", status);
@@ -1044,7 +1068,7 @@ static struct _XENBUS_GNTTAB_INTERFACE_V2
GnttabInterfaceVersion2 = {
GnttabRelease,
GnttabCreateCacheVersion1,
GnttabPermitForeignAccess,
- GnttabRevokeForeignAccess,
+ GnttabRevokeForeignAccessVersion2,
GnttabGetReference,
GnttabDestroyCache,
GnttabMapForeignPages,
@@ -1057,7 +1081,7 @@ static struct _XENBUS_GNTTAB_INTERFACE_V3
GnttabInterfaceVersion3 = {
GnttabRelease,
GnttabCreateCacheVersion1,
GnttabPermitForeignAccess,
- GnttabRevokeForeignAccess,
+ GnttabRevokeForeignAccessVersion2,
GnttabGetReference,
GnttabQueryReference,
GnttabDestroyCache,
@@ -1071,6 +1095,20 @@ static struct _XENBUS_GNTTAB_INTERFACE_V4
GnttabInterfaceVersion4 = {
GnttabRelease,
GnttabCreateCache,
GnttabPermitForeignAccess,
+ GnttabRevokeForeignAccessVersion2,
+ GnttabGetReference,
+ GnttabQueryReference,
+ GnttabDestroyCache,
+ GnttabMapForeignPages,
+ GnttabUnmapForeignPages
+};
+
+static struct _XENBUS_GNTTAB_INTERFACE_V5 GnttabInterfaceVersion5 = {
+ { sizeof (struct _XENBUS_GNTTAB_INTERFACE_V5), 5, NULL, NULL, NULL },
+ GnttabAcquire,
+ GnttabRelease,
+ GnttabCreateCache,
+ GnttabPermitForeignAccess,
GnttabRevokeForeignAccess,
GnttabGetReference,
GnttabQueryReference,
@@ -1212,6 +1250,23 @@ GnttabGetInterface(
status = STATUS_SUCCESS;
break;
}
+ case 5: {
+ struct _XENBUS_GNTTAB_INTERFACE_V5 *GnttabInterface;
+
+ GnttabInterface = (struct _XENBUS_GNTTAB_INTERFACE_V5 *)Interface;
+
+ status = STATUS_BUFFER_OVERFLOW;
+ if (Size < sizeof (struct _XENBUS_GNTTAB_INTERFACE_V5))
+ break;
+
+ *GnttabInterface = GnttabInterfaceVersion5;
+
+ ASSERT3U(Interface->Version, ==, Version);
+ Interface->Context = Context;
+
+ status = STATUS_SUCCESS;
+ break;
+ }
default:
status = STATUS_NOT_SUPPORTED;
break;
--
2.56.0.windows.3
--
Ngoc Tu Dinh | Vates XCP-ng Developer
XCP-ng & Xen Orchestra - Vates solutions
web: https://vates.tech
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |