|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 1/2] Use batched hypercalls for mapping foreign pages
Use one hypercall op with multiple pages instead of
separate hypercalls for each page.
Signed-off-by: Rafał Wojdyła <omeg@xxxxxxxxxxxxxxxxxxxxxx>
---
include/xen.h | 20 +++--
src/xen/grant_table.c | 187 +++++++++++++++++++++++++++++++++---------
src/xenbus/gnttab.c | 47 ++++-------
3 files changed, 177 insertions(+), 77 deletions(-)
diff --git a/include/xen.h b/include/xen.h
index 0c3e8a4..eaab567 100644
--- a/include/xen.h
+++ b/include/xen.h
@@ -265,20 +265,22 @@ GrantTableCopy(
_Check_return_
XEN_API
NTSTATUS
-GrantTableMapForeignPage(
- _In_ USHORT Domain,
- _In_ ULONG GrantRef,
- _In_ PHYSICAL_ADDRESS Address,
- _In_ BOOLEAN ReadOnly,
- _Out_ ULONG *Handle
+GrantTableMapForeignPages(
+ _In_ USHORT Domain,
+ _In_ ULONG NumberPages,
+ _In_reads_(NumberPages) PULONG GrantRefs,
+ _In_ PHYSICAL_ADDRESS Address,
+ _In_ BOOLEAN ReadOnly,
+ _Out_writes_(NumberPages) PULONG Handles
);
_Check_return_
XEN_API
NTSTATUS
-GrantTableUnmapForeignPage(
- _In_ ULONG Handle,
- _In_ PHYSICAL_ADDRESS Address
+GrantTableUnmapForeignPages(
+ _In_ ULONG NumberPages,
+ _In_reads_(NumberPages) PULONG Handles,
+ _In_ PHYSICAL_ADDRESS Address
);
_Check_return_
diff --git a/src/xen/grant_table.c b/src/xen/grant_table.c
index 96a5a26..a9099c6 100644
--- a/src/xen/grant_table.c
+++ b/src/xen/grant_table.c
@@ -38,10 +38,13 @@
#include "hypercall.h"
#include "dbg_print.h"
#include "assert.h"
+#include "util.h"
#pragma warning(push)
#pragma warning(disable:4127) // conditional expression is constant
+#define XEN_GNTTAB_TAG 'TNGX'
+
// Most of the GNTST_* values don't have meaningful NTSTATUS counterparts,
// this macro translates those that do.
#define GNTST_TO_STATUS(_gntst, _status) \
@@ -168,27 +171,20 @@ fail1:
_Check_return_
XEN_API
NTSTATUS
-GrantTableMapForeignPage(
- _In_ USHORT Domain,
- _In_ ULONG GrantRef,
- _In_ PHYSICAL_ADDRESS Address,
- _In_ BOOLEAN ReadOnly,
- _Out_ ULONG *Handle
+GrantTableUnmapForeignPage(
+ _In_ ULONG Handle,
+ _In_ PHYSICAL_ADDRESS Address
)
{
- struct gnttab_map_grant_ref op;
- LONG_PTR rc;
- NTSTATUS status;
+ struct gnttab_unmap_grant_ref op;
+ LONG_PTR rc;
+ NTSTATUS status;
RtlZeroMemory(&op, sizeof(op));
- op.dom = Domain;
- op.ref = GrantRef;
- op.flags = GNTMAP_host_map;
- if (ReadOnly)
- op.flags |= GNTMAP_readonly;
+ op.handle = Handle;
op.host_addr = Address.QuadPart;
- rc = GrantTableOp(GNTTABOP_map_grant_ref, &op, 1);
+ rc = GrantTableOp(GNTTABOP_unmap_grant_ref, &op, 1);
if (rc < 0) {
ERRNO_TO_STATUS(-rc, status);
@@ -196,9 +192,7 @@ GrantTableMapForeignPage(
}
if (op.status != GNTST_okay) {
- Warning("%u:%u -> %u.%u failed (%d)\n",
- op.dom,
- op.ref,
+ Warning("%u.%u failed (%d)\n",
Address.HighPart,
Address.LowPart,
op.status);
@@ -207,8 +201,6 @@ GrantTableMapForeignPage(
goto fail2;
}
- *Handle = op.handle;
-
return STATUS_SUCCESS;
fail2:
@@ -223,40 +215,161 @@ fail1:
_Check_return_
XEN_API
NTSTATUS
-GrantTableUnmapForeignPage(
- _In_ ULONG Handle,
- _In_ PHYSICAL_ADDRESS Address
+GrantTableMapForeignPages(
+ _In_ USHORT Domain,
+ _In_ ULONG NumberPages,
+ _In_reads_(NumberPages) PULONG GrantRefs,
+ _In_ PHYSICAL_ADDRESS Address,
+ _In_ BOOLEAN ReadOnly,
+ _Out_writes_(NumberPages) PULONG Handles
)
{
- struct gnttab_unmap_grant_ref op;
- LONG_PTR rc;
- NTSTATUS status;
+ struct gnttab_map_grant_ref *ops;
+ LONG_PTR rc;
+ NTSTATUS status;
+ ULONG i;
+ PHYSICAL_ADDRESS page_address;
+
+ status = STATUS_NO_MEMORY;
+ ops = __AllocatePoolWithTag(NonPagedPool,
+ NumberPages * sizeof(*ops),
+ XEN_GNTTAB_TAG);
+ if (ops == NULL)
+ goto fail1;
- RtlZeroMemory(&op, sizeof(op));
- op.handle = Handle;
- op.host_addr = Address.QuadPart;
+ page_address.QuadPart = Address.QuadPart;
+ for (i = 0; i < NumberPages; i++) {
+ ops[i].dom = Domain;
+ ops[i].ref = GrantRefs[i];
+ ops[i].flags = GNTMAP_host_map;
+ if (ReadOnly)
+ ops[i].flags |= GNTMAP_readonly;
- rc = GrantTableOp(GNTTABOP_unmap_grant_ref, &op, 1);
+ ops[i].host_addr = page_address.QuadPart;
+ page_address.QuadPart += PAGE_SIZE;
+ }
+
+ rc = GrantTableOp(GNTTABOP_map_grant_ref, ops, NumberPages);
if (rc < 0) {
ERRNO_TO_STATUS(-rc, status);
+ goto fail2;
+ }
+
+ // check every op, they are independently processed
+ status = STATUS_SUCCESS;
+ for (i = 0; i < NumberPages; i++) {
+ if (ops[i].status != GNTST_okay) {
+ Warning("op[%u] %u:%u -> %u.%u failed (%d)\n",
+ i, ops[i].dom, ops[i].ref,
+ (ULONG)(ops[i].host_addr >> 32),
+ (ULONG)ops[i].host_addr,
+ ops[i].status);
+
+ if (NT_SUCCESS(status))
+ GNTST_TO_STATUS(ops[i].status, status);
+ continue;
+ }
+
+ Handles[i] = ops[i].handle;
+ }
+
+ if (!NT_SUCCESS(status))
+ goto fail3;
+
+ __FreePoolWithTag(ops, XEN_GNTTAB_TAG);
+ return STATUS_SUCCESS;
+
+fail3:
+ Error("fail3 (%08x)\n", status);
+
+ // undo successful ops
+ for (i = 0; i < NumberPages; i++) {
+ PHYSICAL_ADDRESS unmap_address;
+ NTSTATUS unmap_status;
+
+ if (ops[i].status != GNTST_okay)
+ continue;
+
+ unmap_address.QuadPart = ops[i].host_addr;
+ unmap_status = GrantTableUnmapForeignPage(ops[i].handle,
+ unmap_address);
+ // don't leave the memory in inconsistent state
+ BUG_ON(!NT_SUCCESS(unmap_status));
+ }
+
+fail2:
+ Error("fail2 (%08x)\n", status);
+ __FreePoolWithTag(ops, XEN_GNTTAB_TAG);
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ return status;
+}
+
+_Check_return_
+XEN_API
+NTSTATUS
+GrantTableUnmapForeignPages(
+ _In_ ULONG NumberPages,
+ _In_reads_(NumberPages) PULONG Handles,
+ _In_ PHYSICAL_ADDRESS Address
+ )
+{
+ struct gnttab_unmap_grant_ref *ops;
+ LONG_PTR rc;
+ NTSTATUS status;
+ ULONG i;
+ PHYSICAL_ADDRESS page_address;
+
+ status = STATUS_NO_MEMORY;
+ ops = __AllocatePoolWithTag(NonPagedPool,
+ NumberPages * sizeof(*ops),
+ XEN_GNTTAB_TAG);
+ if (ops == NULL)
goto fail1;
+
+ page_address.QuadPart = Address.QuadPart;
+ for (i = 0; i < NumberPages; i++) {
+ ops[i].handle = Handles[i];
+ ops[i].host_addr = page_address.QuadPart;
+ page_address.QuadPart += PAGE_SIZE;
}
- if (op.status != GNTST_okay) {
- Warning("%u.%u failed (%d)\n",
- Address.HighPart,
- Address.LowPart,
- op.status);
+ rc = GrantTableOp(GNTTABOP_unmap_grant_ref, ops, NumberPages);
- GNTST_TO_STATUS(op.status, status);
+ if (rc < 0) {
+ ERRNO_TO_STATUS(-rc, status);
goto fail2;
}
+ status = STATUS_SUCCESS;
+ for (i = 0; i < NumberPages; i++) {
+ if (ops[i].status != GNTST_okay) {
+ Warning("op[%u] %u.%u failed (%d)\n",
+ i,
+ (ULONG)(ops[i].host_addr >> 32),
+ (ULONG)ops[i].host_addr,
+ ops[i].status);
+
+ if (NT_SUCCESS(status))
+ GNTST_TO_STATUS(ops[i].status, status);
+ }
+ }
+
+ __FreePoolWithTag(ops, XEN_GNTTAB_TAG);
+
+ if (!NT_SUCCESS(status)) {
+ Error("fail3 (%08x)\n", status);
+ return status;
+ }
+
return STATUS_SUCCESS;
fail2:
- Error("fail2\n");
+ Error("fail2 (%08x)\n", status);
+ __FreePoolWithTag(ops, XEN_GNTTAB_TAG);
fail1:
Error("fail1 (%08x)\n", status);
diff --git a/src/xenbus/gnttab.c b/src/xenbus/gnttab.c
index 71f8ec1..f6fcef6 100644
--- a/src/xenbus/gnttab.c
+++ b/src/xenbus/gnttab.c
@@ -667,8 +667,6 @@ GnttabMapForeignPages(
{
PXENBUS_GNTTAB_CONTEXT Context = Interface->Context;
PMDL Mdl;
- LONG PageIndex;
- PHYSICAL_ADDRESS PageAddress;
PXENBUS_GNTTAB_MAP_ENTRY MapEntry;
NTSTATUS status;
@@ -689,19 +687,15 @@ GnttabMapForeignPages(
MapEntry->Mdl = Mdl;
Address->QuadPart = MmGetMdlPfnArray(Mdl)[0] << PAGE_SHIFT;
- PageAddress.QuadPart = Address->QuadPart;
-
- for (PageIndex = 0; PageIndex < (LONG)NumberPages; PageIndex++) {
- status = GrantTableMapForeignPage(Domain,
- References[PageIndex],
- PageAddress,
- ReadOnly,
- &MapEntry->MapHandles[PageIndex]);
- if (!NT_SUCCESS(status))
- goto fail3;
- PageAddress.QuadPart += PAGE_SIZE;
- }
+ status = GrantTableMapForeignPages(Domain,
+ NumberPages,
+ References,
+ *Address,
+ ReadOnly,
+ MapEntry->MapHandles);
+ if (!NT_SUCCESS(status))
+ goto fail3;
status = HashTableAdd(Context->MapTable,
(ULONG_PTR)Address->QuadPart,
@@ -714,15 +708,13 @@ GnttabMapForeignPages(
fail4:
Error("fail4\n");
+ (VOID) GrantTableUnmapForeignPages(NumberPages,
+ MapEntry->MapHandles,
+ *Address);
+
fail3:
Error("fail3\n");
- while (--PageIndex >= 0) {
- PageAddress.QuadPart -= PAGE_SIZE;
- (VOID) GrantTableUnmapForeignPage(MapEntry->MapHandles[PageIndex],
- PageAddress);
- }
-
Address->QuadPart = 0;
__GnttabFree(MapEntry);
@@ -746,8 +738,6 @@ GnttabUnmapForeignPages(
{
PXENBUS_GNTTAB_CONTEXT Context = Interface->Context;
ULONG NumberPages;
- PHYSICAL_ADDRESS PageAddress;
- ULONG PageIndex;
PXENBUS_GNTTAB_MAP_ENTRY MapEntry;
PMDL Mdl;
NTSTATUS status;
@@ -763,18 +753,13 @@ GnttabUnmapForeignPages(
if (!NT_SUCCESS(status))
goto fail2;
- PageAddress.QuadPart = Address.QuadPart;
-
Mdl = MapEntry->Mdl;
NumberPages = Mdl->ByteCount >> PAGE_SHIFT;
- for (PageIndex = 0; PageIndex < NumberPages; PageIndex++) {
- status = GrantTableUnmapForeignPage(MapEntry->MapHandles[PageIndex],
- PageAddress);
- BUG_ON(!NT_SUCCESS(status));
-
- PageAddress.QuadPart += PAGE_SIZE;
- }
+ status = GrantTableUnmapForeignPages(NumberPages,
+ MapEntry->MapHandles,
+ Address);
+ BUG_ON(!NT_SUCCESS(status));
__GnttabFree(MapEntry);
--
2.54.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |