[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 1/2] Add foreign page mapping functions to the GNTTAB interface
GNTTAB interface now includes functions to map and unmap memory pages granted by a foreign domain. The page(s) are mapped under an address allocated from the PCI BAR space. Signed-off-by: RafaÅ WojdyÅa <omeg@xxxxxxxxxxxxxxxxxxxxxx> --- include/gnttab_interface.h | 62 +++++++++++++++++++++++- include/xen.h | 19 ++++++++ src/xen/grant_table.c | 85 +++++++++++++++++++++++++++++++++ src/xenbus/gnttab.c | 114 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 278 insertions(+), 2 deletions(-) diff --git a/include/gnttab_interface.h b/include/gnttab_interface.h index d29440a..0016888 100644 --- a/include/gnttab_interface.h +++ b/include/gnttab_interface.h @@ -163,6 +163,47 @@ typedef VOID 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 + (allocated from the PCI IO space) + \param Handles An array of tracking numbers that represent the mapping + of each individual page + */ + +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, + OUT ULONG *Handles + ); + +/*! \typedef XENBUS_GNTTAB_UNMAP_FOREIGN_PAGES + \brief Unmap foreign memory pages from the system address space + + \param Interface The interface header + \param NumberPages Number of pages to unmap + \param Address The physical address that the foreign pages are mapped under + \param Handles An array of tracking numbers that represent the mapping + */ +typedef NTSTATUS +(*XENBUS_GNTTAB_UNMAP_FOREIGN_PAGES)( + IN PINTERFACE Interface, + IN ULONG NumberPages, + IN PHYSICAL_ADDRESS Address, + IN PULONG Handles + ); + // {763679C5-E5C2-4A6D-8B88-6BB02EC42D8E} DEFINE_GUID(GUID_XENBUS_GNTTAB_INTERFACE, 0x763679c5, 0xe5c2, 0x4a6d, 0x8b, 0x88, 0x6b, 0xb0, 0x2e, 0xc4, 0x2d, 0x8e); @@ -182,7 +223,24 @@ struct _XENBUS_GNTTAB_INTERFACE_V1 { XENBUS_GNTTAB_DESTROY_CACHE GnttabDestroyCache; }; -typedef struct _XENBUS_GNTTAB_INTERFACE_V1 XENBUS_GNTTAB_INTERFACE, *PXENBUS_GNTTAB_INTERFACE; +/*! \struct _XENBUS_GNTTAB_INTERFACE_V2 + \brief GNTTAB interface version 2 (added map/unmap foreign pages) + \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; +}; + +typedef struct _XENBUS_GNTTAB_INTERFACE_V2 XENBUS_GNTTAB_INTERFACE, *PXENBUS_GNTTAB_INTERFACE; /*! \def XENBUS_GNTTAB \brief Macro at assist in method invocation @@ -193,7 +251,7 @@ typedef struct _XENBUS_GNTTAB_INTERFACE_V1 XENBUS_GNTTAB_INTERFACE, *PXENBUS_GNT #endif // _WINDLL #define XENBUS_GNTTAB_INTERFACE_VERSION_MIN 1 -#define XENBUS_GNTTAB_INTERFACE_VERSION_MAX 1 +#define XENBUS_GNTTAB_INTERFACE_VERSION_MAX 2 #endif // _XENBUS_GNTTAB_INTERFACE_H diff --git a/include/xen.h b/include/xen.h index 6007582..23c7ac0 100644 --- a/include/xen.h +++ b/include/xen.h @@ -258,6 +258,25 @@ GrantTableCopy( IN ULONG Count ); +__checkReturn +XEN_API +NTSTATUS +GrantTableMapForeignPage( + IN USHORT Domain, + IN ULONG GrantRef, + IN PHYSICAL_ADDRESS Address, + IN BOOLEAN ReadOnly, + OUT ULONG *Handle + ); + +__checkReturn +XEN_API +NTSTATUS +GrantTableUnmapForeignPage( + IN ULONG Handle, + IN PHYSICAL_ADDRESS Address + ); + // SCHED __checkReturn diff --git a/src/xen/grant_table.c b/src/xen/grant_table.c index 6facb3f..6450062 100644 --- a/src/xen/grant_table.c +++ b/src/xen/grant_table.c @@ -131,3 +131,88 @@ fail1: return status; } + +__checkReturn +XEN_API +NTSTATUS +GrantTableMapForeignPage( + IN USHORT Domain, + IN ULONG GrantRef, + IN PHYSICAL_ADDRESS Address, + IN BOOLEAN ReadOnly, + OUT ULONG *Handle + ) +{ + struct gnttab_map_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.host_addr = Address.QuadPart; + + rc = GrantTableOp(GNTTABOP_map_grant_ref, &op, 1); + + if (rc < 0) { + ERRNO_TO_STATUS(-rc, status); + goto fail1; + } + + if (op.status != GNTST_okay) { + status = STATUS_UNSUCCESSFUL; + goto fail2; + } + + *Handle = op.handle; + + return STATUS_SUCCESS; + +fail2: + Error("fail2: op.status = %d\n", op.status); +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +__checkReturn +XEN_API +NTSTATUS +GrantTableUnmapForeignPage( + IN ULONG Handle, + IN PHYSICAL_ADDRESS Address + ) +{ + struct gnttab_unmap_grant_ref op; + LONG_PTR rc; + NTSTATUS status; + + RtlZeroMemory(&op, sizeof(op)); + op.handle = Handle; + op.host_addr = Address.QuadPart; + + rc = GrantTableOp(GNTTABOP_unmap_grant_ref, &op, 1); + + if (rc < 0) { + ERRNO_TO_STATUS(-rc, status); + goto fail1; + } + + if (op.status != GNTST_okay) { + status = STATUS_UNSUCCESSFUL; + goto fail2; + } + + return STATUS_SUCCESS; + +fail2: + Error("op.status = %d\n", op.status); +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} diff --git a/src/xenbus/gnttab.c b/src/xenbus/gnttab.c index 165e38f..24d45af 100644 --- a/src/xenbus/gnttab.c +++ b/src/xenbus/gnttab.c @@ -534,6 +534,90 @@ GnttabGetReference( return (ULONG)Entry->Reference; } +static NTSTATUS +GnttabMapForeignPages( + IN PINTERFACE Interface, + IN USHORT Domain, + IN ULONG NumberPages, + IN PULONG References, + IN BOOLEAN ReadOnly, + OUT PHYSICAL_ADDRESS *Address, + OUT ULONG *Handles + ) +{ + NTSTATUS status; + PXENBUS_GNTTAB_CONTEXT Context = Interface->Context; + ULONG PageIndex; + PHYSICAL_ADDRESS PageAddress; + + status = FdoAllocateIoSpace(Context->Fdo, NumberPages * PAGE_SIZE, Address); + if (!NT_SUCCESS(status)) + goto fail1; + + PageAddress.QuadPart = Address->QuadPart; + + for (PageIndex = 0; PageIndex < NumberPages; PageIndex++) { + status = GrantTableMapForeignPage(Domain, + References[PageIndex], + PageAddress, + ReadOnly, + &(Handles[PageIndex])); + if (!NT_SUCCESS(status)) + goto fail2; + + PageAddress.QuadPart += PAGE_SIZE; + } + + return STATUS_SUCCESS; + +fail2: + Error("fail2: PageIndex %lu, PageAddress %p, Handle %lu\n", PageIndex, PageAddress.QuadPart, Handles[PageIndex]); + + while (PageIndex > 0) { + --PageIndex; + PageAddress.QuadPart -= PAGE_SIZE; + ASSERT(NT_SUCCESS(GrantTableUnmapForeignPage(Handles[PageIndex], PageAddress))); + } + + FdoFreeIoSpace(Context->Fdo, *Address, NumberPages * PAGE_SIZE); + +fail1: + Error("fail1: (%08x)\n", status); + return status; +} + +static NTSTATUS +GnttabUnmapForeignPages( + IN PINTERFACE Interface, + IN ULONG NumberPages, + IN PHYSICAL_ADDRESS Address, + IN PULONG Handles + ) +{ + NTSTATUS status; + PXENBUS_GNTTAB_CONTEXT Context = Interface->Context; + ULONG PageIndex; + PHYSICAL_ADDRESS PageAddress; + + PageAddress.QuadPart = Address.QuadPart; + + for (PageIndex = 0; PageIndex < NumberPages; PageIndex++) { + status = GrantTableUnmapForeignPage(Handles[PageIndex], PageAddress); + if (!NT_SUCCESS(status)) + goto fail1; + + PageAddress.QuadPart += PAGE_SIZE; + } + + FdoFreeIoSpace(Context->Fdo, Address, NumberPages * PAGE_SIZE); + return STATUS_SUCCESS; + +fail1: + Error("fail1: (%08x), leaking memory at %p, size 0x%lx. PageIndex = %lu, PageAddress = %p, Handle = %lu\n", + status, Address.QuadPart, NumberPages * PAGE_SIZE, PageIndex, PageAddress.QuadPart, Handles[PageIndex]); + return status; +} + static VOID GnttabSuspendCallbackEarly( IN PVOID Argument @@ -789,6 +873,19 @@ static struct _XENBUS_GNTTAB_INTERFACE_V1 GnttabInterfaceVersion1 = { GnttabDestroyCache }; +static struct _XENBUS_GNTTAB_INTERFACE_V2 GnttabInterfaceVersion2 = { + { sizeof(struct _XENBUS_GNTTAB_INTERFACE_V2), 2, NULL, NULL, NULL }, + GnttabAcquire, + GnttabRelease, + GnttabCreateCache, + GnttabPermitForeignAccess, + GnttabRevokeForeignAccess, + GnttabGetReference, + GnttabDestroyCache, + GnttabMapForeignPages, + GnttabUnmapForeignPages +}; + NTSTATUS GnttabInitialize( IN PXENBUS_FDO Fdo, @@ -878,6 +975,23 @@ GnttabGetInterface( status = STATUS_SUCCESS; break; } + case 2: { + struct _XENBUS_GNTTAB_INTERFACE_V2 *GnttabInterface; + + GnttabInterface = (struct _XENBUS_GNTTAB_INTERFACE_V2 *)Interface; + + status = STATUS_BUFFER_OVERFLOW; + if (Size < sizeof(struct _XENBUS_GNTTAB_INTERFACE_V2)) + break; + + *GnttabInterface = GnttabInterfaceVersion2; + + ASSERT3U(Interface->Version, ==, Version); + Interface->Context = Context; + + status = STATUS_SUCCESS; + break; + } default: status = STATUS_NOT_SUPPORTED; break; _______________________________________________ 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 |