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

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



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>

---
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


 


Rackspace

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