[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [win-pv-devel] [TEST] Add XENBUS APIs necessary for libvchan implementation



> -----Original Message-----
> From: win-pv-devel-bounces@xxxxxxxxxxxxxxxxxxxx [mailto:win-pv-devel-
> bounces@xxxxxxxxxxxxxxxxxxxx] On Behalf Of Rafal Wojdyla
> Sent: 11 September 2015 12:15
> To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> Subject: [win-pv-devel] [TEST] Add XENBUS APIs necessary for libvchan
> implementation
> 
> 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: Rafal Wojdyla <omeg@xxxxxxxxxxxxxxxxxxxxxx>

That works :-)

  Paul

> ---
>  include/gnttab_interface.h |  54 ++++++++++++++-
>  include/xen.h              |  19 ++++++
>  src/xen/grant_table.c      | 116 +++++++++++++++++++++++++++++++
>  src/xenbus/gnttab.c        | 165
> +++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 352 insertions(+), 2 deletions(-)
> 
> diff --git a/include/gnttab_interface.h b/include/gnttab_interface.h
> index d29440a..b0f4adf 100644
> --- a/include/gnttab_interface.h
> +++ b/include/gnttab_interface.h
> @@ -163,6 +163,39 @@ 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
> +*/
> +
> +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);
> @@ -182,7 +215,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
> +    \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 +243,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..6b00f65 100644
> --- a/src/xen/grant_table.c
> +++ b/src/xen/grant_table.c
> @@ -38,6 +38,35 @@
>  #include "dbg_print.h"
>  #include "assert.h"
> 
> +#pragma warning(disable:4127)   // conditional expression is constant
> +
> +// Most of the GNTST_* values don't have meaningful NTSTATUS
> counterparts,
> +// this macro translates those that do.
> +#define GNTST_TO_STATUS(_gntst, _status)                    \
> +        do {                                                \
> +            switch (_gntst) {                               \
> +            case GNTST_okay:                                \
> +                _status = STATUS_SUCCESS;                   \
> +                break;                                      \
> +                                                            \
> +            case GNTST_bad_handle:                          \
> +                _status = STATUS_INVALID_HANDLE;            \
> +                break;                                      \
> +                                                            \
> +            case GNTST_permission_denied:                   \
> +                _status = STATUS_ACCESS_DENIED;             \
> +                break;                                      \
> +                                                            \
> +            case GNTST_eagain:                              \
> +                _status = STATUS_RETRY;                     \
> +                break;                                      \
> +                                                            \
> +            default:                                        \
> +                _status = STATUS_UNSUCCESSFUL;              \
> +                break;                                      \
> +            }                                               \
> +        } while (FALSE)
> +
>  static LONG_PTR
>  GrantTableOp(
>      IN  ULONG   Command,
> @@ -131,3 +160,90 @@ 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) {
> +        GNTST_TO_STATUS(op.status, status);
> +        Error("hypercall status: %d\n", op.status);
> +        goto fail2;
> +    }
> +
> +    *Handle = op.handle;
> +
> +    return STATUS_SUCCESS;
> +
> +fail2:
> +    Error("fail2\n");
> +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) {
> +        GNTST_TO_STATUS(op.status, status);
> +        Error("hypercall status: %d\n", op.status);
> +        goto fail2;
> +    }
> +
> +    return STATUS_SUCCESS;
> +
> +fail2:
> +    Error("fail2\n");
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> diff --git a/src/xenbus/gnttab.c b/src/xenbus/gnttab.c
> index 165e38f..32b43c7 100644
> --- a/src/xenbus/gnttab.c
> +++ b/src/xenbus/gnttab.c
> @@ -40,6 +40,7 @@
>  #include "dbg_print.h"
>  #include "assert.h"
>  #include "util.h"
> +#include "hash_table.h"
> 
>  #define XENBUS_GNTTAB_MAXIMUM_FRAME_COUNT  32
>  #define XENBUS_GNTTAB_ENTRY_PER_FRAME      (PAGE_SIZE / sizeof
> (grant_entry_v1_t))
> @@ -68,6 +69,11 @@ struct _XENBUS_GNTTAB_ENTRY {
>      grant_entry_v1_t    Entry;
>  };
> 
> +typedef struct _XENBUS_GNTTAB_MAP_ENTRY {
> +    ULONG               NumberPages;
> +    ULONG               MapHandles[1];
> +} XENBUS_GNTTAB_MAP_ENTRY, *PXENBUS_GNTTAB_MAP_ENTRY;
> +
>  struct _XENBUS_GNTTAB_CONTEXT {
>      PXENBUS_FDO                 Fdo;
>      KSPIN_LOCK                  Lock;
> @@ -82,6 +88,7 @@ struct _XENBUS_GNTTAB_CONTEXT {
>      PXENBUS_SUSPEND_CALLBACK    SuspendCallbackEarly;
>      XENBUS_DEBUG_INTERFACE      DebugInterface;
>      PXENBUS_DEBUG_CALLBACK      DebugCallback;
> +    PXENBUS_HASH_TABLE          MapTable;
>      LIST_ENTRY                  List;
>  };
> 
> @@ -534,6 +541,124 @@ 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
> +    )
> +{
> +    NTSTATUS                    status;
> +    PXENBUS_GNTTAB_CONTEXT      Context = Interface->Context;
> +    ULONG                       PageIndex;
> +    PHYSICAL_ADDRESS            PageAddress;
> +    PXENBUS_GNTTAB_MAP_ENTRY    MapEntry;
> +
> +    status = FdoAllocateIoSpace(Context->Fdo, NumberPages * PAGE_SIZE,
> Address);
> +    if (!NT_SUCCESS(status))
> +        goto fail1;
> +
> +    status = STATUS_INSUFFICIENT_RESOURCES;
> +    MapEntry =
> __GnttabAllocate(FIELD_OFFSET(XENBUS_GNTTAB_MAP_ENTRY,
> MapHandles) + NumberPages*sizeof(ULONG));
> +    if (!MapEntry)
> +        goto fail2;
> +
> +    PageAddress.QuadPart = Address->QuadPart;
> +    MapEntry->NumberPages = NumberPages;
> +
> +    for (PageIndex = 0; PageIndex < NumberPages; PageIndex++) {
> +        status = GrantTableMapForeignPage(Domain,
> +                                          References[PageIndex],
> +                                          PageAddress,
> +                                          ReadOnly,
> +                                          &MapEntry->MapHandles[PageIndex]);
> +        if (!NT_SUCCESS(status))
> +            goto fail3;
> +
> +        PageAddress.QuadPart += PAGE_SIZE;
> +    }
> +
> +    status = HashTableAdd(Context->MapTable,
> +                          Address->QuadPart,
> +                          (ULONG_PTR)MapEntry);
> +
> +    if (!NT_SUCCESS(status))
> +        goto fail4;
> +
> +    return STATUS_SUCCESS;
> +
> +fail4:
> +    Error("fail4\n");
> +
> +fail3:
> +    Error("fail3\n");
> +
> +    while (PageIndex > 0) {
> +        --PageIndex;
> +        PageAddress.QuadPart -= PAGE_SIZE;
> +        ASSERT(NT_SUCCESS(GrantTableUnmapForeignPage(MapEntry-
> >MapHandles[PageIndex], PageAddress)));
> +    }
> +
> +    __GnttabFree(MapEntry);
> +
> +fail2:
> +    Error("fail2\n");
> +    FdoFreeIoSpace(Context->Fdo, *Address, NumberPages * PAGE_SIZE);
> +
> +fail1:
> +    Error("fail1: (%08x)\n", status);
> +    return status;
> +}
> +
> +static NTSTATUS
> +GnttabUnmapForeignPages(
> +    IN  PINTERFACE              Interface,
> +    IN  PHYSICAL_ADDRESS        Address
> +    )
> +{
> +    NTSTATUS                    Status;
> +    PXENBUS_GNTTAB_CONTEXT      Context = Interface->Context;
> +    ULONG                       PageIndex;
> +    PHYSICAL_ADDRESS            PageAddress;
> +    PXENBUS_GNTTAB_MAP_ENTRY    MapEntry;
> +
> +    Status = HashTableLookup(Context->MapTable, Address.QuadPart,
> (PULONG_PTR)&MapEntry);
> +    if (!NT_SUCCESS(Status))
> +        goto fail1;
> +
> +    Status = HashTableRemove(Context->MapTable, Address.QuadPart);
> +    if (!NT_SUCCESS(Status))
> +        goto fail2;
> +
> +    PageAddress.QuadPart = Address.QuadPart;
> +
> +    for (PageIndex = 0; PageIndex < MapEntry->NumberPages;
> PageIndex++) {
> +        Status = GrantTableUnmapForeignPage(MapEntry-
> >MapHandles[PageIndex], PageAddress);
> +        if (!NT_SUCCESS(Status))
> +            goto fail3;
> +
> +        PageAddress.QuadPart += PAGE_SIZE;
> +    }
> +
> +    FdoFreeIoSpace(Context->Fdo, Address, MapEntry->NumberPages *
> PAGE_SIZE);
> +    __GnttabFree(MapEntry);
> +    return STATUS_SUCCESS;
> +
> +fail3:
> +    Error("fail3\n");
> +    KeBugCheckEx(MEMORY_MANAGEMENT, XENBUS_GNTTAB_TAG,
> PageAddress.QuadPart, MapEntry->MapHandles[PageIndex],
> Address.QuadPart);
> +
> +fail2:
> +    Error("fail2\n");
> +
> +fail1:
> +    Error("fail1: (%08x)\n", Status);
> +    return Status;
> +}
> +
>  static VOID
>  GnttabSuspendCallbackEarly(
>      IN  PVOID               Argument
> @@ -789,6 +914,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,
> @@ -836,12 +974,19 @@ GnttabInitialize(
>      InitializeListHead(&(*Context)->List);
>      KeInitializeSpinLock(&(*Context)->Lock);
> 
> +    status = HashTableCreate(&(*Context)->MapTable);
> +    if (!NT_SUCCESS(status))
> +        goto fail2;
> +
>      (*Context)->Fdo = Fdo;
> 
>      Trace("<====\n");
> 
>      return STATUS_SUCCESS;
> 
> +fail2:
> +    Error("fail2\n");
> +
>  fail1:
>      Error("fail1 (%08x)\n", status);
> 
> @@ -878,6 +1023,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;
> @@ -895,6 +1057,9 @@ GnttabTeardown(
> 
>      Context->Fdo = NULL;
> 
> +    HashTableDestroy(Context->MapTable);
> +    Context->MapTable = NULL;
> +
>      RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK));
>      RtlZeroMemory(&Context->List, sizeof (LIST_ENTRY));
> 
> --
> 1.8.1.msysgit.1
> 
> 
> _______________________________________________
> win-pv-devel mailing list
> win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.