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

Re: [Xen-devel] [PATCH v2 08/18] OvmfPkg/XenBusDxe: Add Grant Table functions.



On Thu, Sep 04, 2014 at 05:51:03PM +0100, Anthony PERARD wrote:
> There are used to grant access of pages to other Xen domains.
> 
> This code originaly comes from the Xen Project, and more precisely from
> MiniOS.
> 
> Signed-off-by: Steven Smith <sos22@xxxxxxxxx>
> Signed-off-by: Grzegorz Milos <gm281@xxxxxxxxx>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx>

Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
> 
> ---
> Change in V2:
> - Adding locks
> - Redo the file header
> - Add functions comment
> - Add license
> ---
>  OvmfPkg/XenBusDxe/GrantTable.c  | 217 
> ++++++++++++++++++++++++++++++++++++++++
>  OvmfPkg/XenBusDxe/GrantTable.h  |  68 +++++++++++++
>  OvmfPkg/XenBusDxe/XenBusDxe.c   |  15 +++
>  OvmfPkg/XenBusDxe/XenBusDxe.inf |   2 +
>  4 files changed, 302 insertions(+)
>  create mode 100644 OvmfPkg/XenBusDxe/GrantTable.c
>  create mode 100644 OvmfPkg/XenBusDxe/GrantTable.h
> 
> diff --git a/OvmfPkg/XenBusDxe/GrantTable.c b/OvmfPkg/XenBusDxe/GrantTable.c
> new file mode 100644
> index 0000000..8b08134
> --- /dev/null
> +++ b/OvmfPkg/XenBusDxe/GrantTable.c
> @@ -0,0 +1,217 @@
> +/** @file
> +  Grant Table function implementation.
> +
> +  Grant Table are used to grant access to certain page of the current
> +  VM to an other VM.
> +
> +  Author: Steven Smith (sos22@xxxxxxxxx)
> +  Changes: Grzegorz Milos (gm281@xxxxxxxxx)
> +  Copyright (C) 2006, Cambridge University
> +  Copyright (C) 2014, Citrix Ltd.
> +
> +  Redistribution and use in source and binary forms, with or without
> +  modification, are permitted provided that the following conditions
> +  are met:
> +  1. Redistributions of source code must retain the above copyright
> +     notice, this list of conditions and the following disclaimer.
> +  2. Redistributions in binary form must reproduce the above copyright
> +     notice, this list of conditions and the following disclaimer in the
> +     documentation and/or other materials provided with the distribution.
> +
> +  THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> +  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> +  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> +  ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
> +  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> +  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> +  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> +  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> +  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> +  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> +  SUCH DAMAGE.
> +**/
> +#include "XenBusDxe.h"
> +
> +#include <IndustryStandard/Xen/memory.h>
> +
> +#include "XenHypercall.h"
> +
> +#include "GrantTable.h"
> +#include "InterlockedCompareExchange16.h"
> +
> +#define NR_RESERVED_ENTRIES 8
> +
> +/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
> +#define NR_GRANT_FRAMES 4
> +#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * EFI_PAGE_SIZE / 
> sizeof(grant_entry_v1_t))
> +
> +STATIC grant_entry_v1_t *GrantTable = NULL;
> +STATIC grant_ref_t GrantList[NR_GRANT_ENTRIES];
> +STATIC EFI_LOCK mGrantListLock;
> +#ifdef GNT_DEBUG
> +STATIC BOOLEAN GrantInUseList[NR_GRANT_ENTRIES];
> +#endif
> +
> +STATIC
> +VOID
> +XenGrantTablePutFreeEntry (
> +  grant_ref_t Ref
> +  )
> +{
> +  EfiAcquireLock (&mGrantListLock);
> +#ifdef GNT_DEBUG
> +  ASSERT (GrantInUseList[Ref]);
> +  GrantInUseList[Ref] = FALSE;
> +#endif
> +  GrantList[Ref] = GrantList[0];
> +  GrantList[0] = Ref;
> +  EfiReleaseLock (&mGrantListLock);
> +}
> +
> +STATIC
> +grant_ref_t
> +XenGrantTableGetFreeEntry (
> +  VOID
> +  )
> +{
> +  UINTN Ref;
> +
> +  EfiAcquireLock (&mGrantListLock);
> +  Ref = GrantList[0];
> +  ASSERT (Ref >= NR_RESERVED_ENTRIES && Ref < NR_GRANT_ENTRIES);
> +  GrantList[0] = GrantList[Ref];
> +#ifdef GNT_DEBUG
> +  ASSERT (!GrantInUseList[Ref]);
> +  GrantInUseList[Ref] = TRUE;
> +#endif
> +  EfiReleaseLock (&mGrantListLock);
> +  return Ref;
> +}
> +
> +STATIC
> +grant_ref_t
> +XenGrantTableGrantAccess (
> +  IN domid_t  DomainId,
> +  IN UINTN    Frame,
> +  IN BOOLEAN  ReadOnly
> +  )
> +{
> +  grant_ref_t Ref;
> +  UINT32 Flags;
> +
> +  ASSERT (GrantTable != NULL);
> +  Ref = XenGrantTableGetFreeEntry ();
> +  GrantTable[Ref].frame = Frame;
> +  GrantTable[Ref].domid = DomainId;
> +  MemoryFence ();
> +  Flags = GTF_permit_access;
> +  if (ReadOnly) {
> +    Flags |= GTF_readonly;
> +  }
> +  GrantTable[Ref].flags = Flags;
> +
> +  return Ref;
> +}
> +
> +STATIC
> +EFI_STATUS
> +XenGrantTableEndAccess (
> +  grant_ref_t Ref
> +  )
> +{
> +  UINT16 Flags, OldFlags;
> +
> +  ASSERT (GrantTable != NULL);
> +  ASSERT (Ref >= NR_RESERVED_ENTRIES && Ref < NR_GRANT_ENTRIES);
> +
> +  OldFlags = GrantTable[Ref].flags;
> +  do {
> +    if ((Flags = OldFlags) & (GTF_reading | GTF_writing)) {
> +      DEBUG ((EFI_D_WARN, "WARNING: g.e. still in use! (%x)\n", Flags));
> +      return EFI_NOT_READY;
> +    }
> +    OldFlags = InterlockedCompareExchange16 (&GrantTable[Ref].flags, Flags, 
> 0);
> +  } while (OldFlags != Flags);
> +
> +  XenGrantTablePutFreeEntry (Ref);
> +  return EFI_SUCCESS;
> +}
> +
> +VOID
> +XenGrantTableInit (
> +  IN XENBUS_DEVICE  *Dev,
> +  IN UINT64         MmioAddr
> +  )
> +{
> +  xen_add_to_physmap_t Parameters;
> +  INTN Index;
> +  INTN ReturnCode;
> +
> +#ifdef GNT_DEBUG
> +  SetMem(GrantInUseList, sizeof (GrantInUseList), 1);
> +#endif
> +  EfiInitializeLock (&mGrantListLock, TPL_NOTIFY);
> +  for (Index = NR_RESERVED_ENTRIES; Index < NR_GRANT_ENTRIES; Index++) {
> +    XenGrantTablePutFreeEntry (Index);
> +  }
> +
> +  GrantTable = (VOID*)(UINTN) MmioAddr;
> +  for (Index = 0; Index < NR_GRANT_FRAMES; Index++) {
> +    Parameters.domid = DOMID_SELF;
> +    Parameters.idx = Index;
> +    Parameters.space = XENMAPSPACE_grant_table;
> +    Parameters.gpfn = (((xen_pfn_t) GrantTable) >> EFI_PAGE_SHIFT) + Index;
> +    ReturnCode = XenHypercallMemoryOp (Dev, XENMEM_add_to_physmap, 
> &Parameters);
> +    if (ReturnCode != 0) {
> +      DEBUG ((EFI_D_ERROR, "Xen GrantTable, add_to_physmap hypercall error: 
> %d\n", ReturnCode));
> +    }
> +  }
> +}
> +
> +VOID
> +XenGrantTableDeinit (
> +  XENBUS_DEVICE *Dev
> +  )
> +{
> +  INTN ReturnCode, Index;
> +  xen_remove_from_physmap_t Parameters;
> +
> +  if (GrantTable == NULL) {
> +    return;
> +  }
> +
> +  for (Index = NR_GRANT_FRAMES - 1; Index >= 0; Index--) {
> +    Parameters.domid = DOMID_SELF;
> +    Parameters.gpfn = (((xen_pfn_t) GrantTable) >> EFI_PAGE_SHIFT) + Index;
> +    DEBUG ((EFI_D_INFO, "Xen GrantTable, removing %X\n", Parameters.gpfn));
> +    ReturnCode = XenHypercallMemoryOp (Dev, XENMEM_remove_from_physmap, 
> &Parameters);
> +    if (ReturnCode != 0) {
> +      DEBUG ((EFI_D_ERROR, "Xen GrantTable, remove_from_physmap hypercall 
> error: %d\n", ReturnCode));
> +    }
> +  }
> +  GrantTable = NULL;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +XenBusGrantAccess (
> +  IN  XENBUS_PROTOCOL *This,
> +  IN  domid_t         DomainId,
> +  IN  UINTN           Frame, // MFN
> +  IN  BOOLEAN         ReadOnly,
> +  OUT grant_ref_t     *RefPtr
> +  )
> +{
> +  *RefPtr = XenGrantTableGrantAccess (DomainId, Frame, ReadOnly);
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +XenBusGrantEndAccess (
> +  IN XENBUS_PROTOCOL  *This,
> +  IN grant_ref_t      Ref
> +  )
> +{
> +  return XenGrantTableEndAccess (Ref);
> +}
> diff --git a/OvmfPkg/XenBusDxe/GrantTable.h b/OvmfPkg/XenBusDxe/GrantTable.h
> new file mode 100644
> index 0000000..bbead2e
> --- /dev/null
> +++ b/OvmfPkg/XenBusDxe/GrantTable.h
> @@ -0,0 +1,68 @@
> +/** @file
> +  Grant Table function declaration.
> +
> +  Grant Table are used to grant access to certain page of the current
> +  VM to an other VM.
> +
> +  Copyright (C) 2014, Citrix Ltd.
> +**/
> +#ifndef __GNTTAB_H__
> +#define __GNTTAB_H__
> +
> +#include <IndustryStandard/Xen/grant_table.h>
> +
> +/**
> +  Initialize the Grant Table at the address MmioAddr.
> +
> +  @param Dev      A pointer to XENBUS_DEVICE.
> +  @param MmioAddr An address where the grant table can be mapped into
> +                  the guest.
> +**/
> +VOID
> +XenGrantTableInit (
> +  IN XENBUS_DEVICE  *Dev,
> +  IN UINT64         MmioAddr
> +  );
> +
> +/**
> +  Desinitilize the Grant Table.
> +**/
> +VOID
> +XenGrantTableDeinit (
> +  IN XENBUS_DEVICE  *Dev
> +  );
> +
> +/**
> +  Grant access to the page Frame to the domain DomainId.
> +
> +  @param This       A pointer to XENBUS_PROTOCOL instance.
> +  @param DomainId   ID of the domain to grant acces to.
> +  @param Frame      Frame Number of the page to grant access to.
> +  @param ReadOnly   Provide read-only or read-write access.
> +  @param RefPtr     Reference number of the grant will be writen to this 
> pointer.
> +**/
> +EFI_STATUS
> +EFIAPI
> +XenBusGrantAccess (
> +  IN  XENBUS_PROTOCOL *This,
> +  IN  domid_t         DomainId,
> +  IN  UINTN           Frame, // MFN
> +  IN  BOOLEAN         ReadOnly,
> +  OUT grant_ref_t     *RefPtr
> +  );
> +
> +/**
> +  End access to grant Ref, previously return by XenBusGrantAccess.
> +
> +  @param This       A pointer to XENBUS_PROTOCOL instance.
> +  @param Ref        Reference numeber of a grant previously returned by
> +                    XenBusGrantAccess.
> +**/
> +EFI_STATUS
> +EFIAPI
> +XenBusGrantEndAccess (
> +  IN XENBUS_PROTOCOL  *This,
> +  IN grant_ref_t      Ref
> +  );
> +
> +#endif /* !__GNTTAB_H__ */
> diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.c b/OvmfPkg/XenBusDxe/XenBusDxe.c
> index 15420c8..29aadb1 100644
> --- a/OvmfPkg/XenBusDxe/XenBusDxe.c
> +++ b/OvmfPkg/XenBusDxe/XenBusDxe.c
> @@ -46,6 +46,7 @@
>  #include "XenBusDxe.h"
>  
>  #include "XenHypercall.h"
> +#include "GrantTable.h"
>  
>  
>  ///
> @@ -297,6 +298,8 @@ XenBusDxeDriverBindingStart (
>    EFI_STATUS Status;
>    XENBUS_DEVICE *Dev;
>    EFI_PCI_IO_PROTOCOL *PciIo;
> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;
> +  UINT64 MmioAddr;
>  
>    Status = gBS->OpenProtocol (
>                       ControllerHandle,
> @@ -316,6 +319,15 @@ XenBusDxeDriverBindingStart (
>    Dev->ControllerHandle = ControllerHandle;
>    Dev->PciIo = PciIo;
>  
> +  Status = PciIo->GetBarAttributes (PciIo, PCI_BAR_IDX1, NULL, (VOID**) 
> &BarDesc);
> +  ASSERT_EFI_ERROR (Status);
> +  ASSERT (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM);
> +
> +  /* Get a Memory address for mapping the Grant Table. */
> +  DEBUG ((EFI_D_INFO, "XenBus: BAR at %LX\n", BarDesc->AddrRangeMin));
> +  MmioAddr = BarDesc->AddrRangeMin;
> +  FreePool (BarDesc);
> +
>    Status = XenHyperpageInit (Dev);
>    if (EFI_ERROR (Status)) {
>      DEBUG ((EFI_D_ERROR, "XenBus: Unable to retrieve the hyperpage."));
> @@ -330,6 +342,8 @@ XenBusDxeDriverBindingStart (
>      goto ErrorNoHyperpage;
>    }
>  
> +  XenGrantTableInit (Dev, MmioAddr);
> +
>    Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
>                               NotifyExitBoot,
>                               (VOID*) Dev,
> @@ -384,6 +398,7 @@ XenBusDxeDriverBindingStop (
>    XENBUS_DEVICE *Dev = mMyDevice;
>  
>    gBS->CloseEvent (Dev->ExitBootEvent);
> +  XenGrantTableDeinit (Dev);
>  
>    gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid,
>           This->DriverBindingHandle, ControllerHandle);
> diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
> index 612c3db..1eca168 100644
> --- a/OvmfPkg/XenBusDxe/XenBusDxe.inf
> +++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
> @@ -34,6 +34,8 @@
>    XenHypercall.c
>    XenHypercall.h
>    InterlockedCompareExchange16.h
> +  GrantTable.c
> +  GrantTable.h
>  
>  [Sources.X64]
>    X64/hypercall.S
> -- 
> Anthony PERARD
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxx
> http://lists.xen.org/xen-devel

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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