--- /dev/null
+/** @file\r
+ Grant Table function implementation.\r
+\r
+ Grant Table are used to grant access to certain page of the current\r
+ VM to an other VM.\r
+\r
+ Author: Steven Smith (sos22@cam.ac.uk)\r
+ Changes: Grzegorz Milos (gm281@cam.ac.uk)\r
+ Copyright (C) 2006, Cambridge University\r
+ Copyright (C) 2014, Citrix Ltd.\r
+\r
+ Redistribution and use in source and binary forms, with or without\r
+ modification, are permitted provided that the following conditions\r
+ are met:\r
+ 1. Redistributions of source code must retain the above copyright\r
+ notice, this list of conditions and the following disclaimer.\r
+ 2. Redistributions in binary form must reproduce the above copyright\r
+ notice, this list of conditions and the following disclaimer in the\r
+ documentation and/or other materials provided with the distribution.\r
+\r
+ THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND\r
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE\r
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
+ SUCH DAMAGE.\r
+**/\r
+#include "XenBusDxe.h"\r
+\r
+#include <IndustryStandard/Xen/memory.h>\r
+\r
+#include "XenHypercall.h"\r
+\r
+#include "GrantTable.h"\r
+#include "InterlockedCompareExchange16.h"\r
+\r
+#define NR_RESERVED_ENTRIES 8\r
+\r
+/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */\r
+#define NR_GRANT_FRAMES 4\r
+#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * EFI_PAGE_SIZE / sizeof(grant_entry_v1_t))\r
+\r
+STATIC grant_entry_v1_t *GrantTable = NULL;\r
+STATIC grant_ref_t GrantList[NR_GRANT_ENTRIES];\r
+STATIC EFI_LOCK mGrantListLock;\r
+#ifdef GNT_DEBUG\r
+STATIC BOOLEAN GrantInUseList[NR_GRANT_ENTRIES];\r
+#endif\r
+\r
+STATIC\r
+VOID\r
+XenGrantTablePutFreeEntry (\r
+ grant_ref_t Ref\r
+ )\r
+{\r
+ EfiAcquireLock (&mGrantListLock);\r
+#ifdef GNT_DEBUG\r
+ ASSERT (GrantInUseList[Ref]);\r
+ GrantInUseList[Ref] = FALSE;\r
+#endif\r
+ GrantList[Ref] = GrantList[0];\r
+ GrantList[0] = Ref;\r
+ EfiReleaseLock (&mGrantListLock);\r
+}\r
+\r
+STATIC\r
+grant_ref_t\r
+XenGrantTableGetFreeEntry (\r
+ VOID\r
+ )\r
+{\r
+ UINTN Ref;\r
+\r
+ EfiAcquireLock (&mGrantListLock);\r
+ Ref = GrantList[0];\r
+ ASSERT (Ref >= NR_RESERVED_ENTRIES && Ref < NR_GRANT_ENTRIES);\r
+ GrantList[0] = GrantList[Ref];\r
+#ifdef GNT_DEBUG\r
+ ASSERT (!GrantInUseList[Ref]);\r
+ GrantInUseList[Ref] = TRUE;\r
+#endif\r
+ EfiReleaseLock (&mGrantListLock);\r
+ return Ref;\r
+}\r
+\r
+STATIC\r
+grant_ref_t\r
+XenGrantTableGrantAccess (\r
+ IN domid_t DomainId,\r
+ IN UINTN Frame,\r
+ IN BOOLEAN ReadOnly\r
+ )\r
+{\r
+ grant_ref_t Ref;\r
+ UINT32 Flags;\r
+\r
+ ASSERT (GrantTable != NULL);\r
+ Ref = XenGrantTableGetFreeEntry ();\r
+ GrantTable[Ref].frame = Frame;\r
+ GrantTable[Ref].domid = DomainId;\r
+ MemoryFence ();\r
+ Flags = GTF_permit_access;\r
+ if (ReadOnly) {\r
+ Flags |= GTF_readonly;\r
+ }\r
+ GrantTable[Ref].flags = Flags;\r
+\r
+ return Ref;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+XenGrantTableEndAccess (\r
+ grant_ref_t Ref\r
+ )\r
+{\r
+ UINT16 Flags, OldFlags;\r
+\r
+ ASSERT (GrantTable != NULL);\r
+ ASSERT (Ref >= NR_RESERVED_ENTRIES && Ref < NR_GRANT_ENTRIES);\r
+\r
+ OldFlags = GrantTable[Ref].flags;\r
+ do {\r
+ if ((Flags = OldFlags) & (GTF_reading | GTF_writing)) {\r
+ DEBUG ((EFI_D_WARN, "WARNING: g.e. still in use! (%x)\n", Flags));\r
+ return EFI_NOT_READY;\r
+ }\r
+ OldFlags = InterlockedCompareExchange16 (&GrantTable[Ref].flags, Flags, 0);\r
+ } while (OldFlags != Flags);\r
+\r
+ XenGrantTablePutFreeEntry (Ref);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+XenGrantTableInit (\r
+ IN XENBUS_DEVICE *Dev,\r
+ IN UINT64 MmioAddr\r
+ )\r
+{\r
+ xen_add_to_physmap_t Parameters;\r
+ INTN Index;\r
+ INTN ReturnCode;\r
+\r
+#ifdef GNT_DEBUG\r
+ SetMem(GrantInUseList, sizeof (GrantInUseList), 1);\r
+#endif\r
+ EfiInitializeLock (&mGrantListLock, TPL_NOTIFY);\r
+ for (Index = NR_RESERVED_ENTRIES; Index < NR_GRANT_ENTRIES; Index++) {\r
+ XenGrantTablePutFreeEntry (Index);\r
+ }\r
+\r
+ GrantTable = (VOID*)(UINTN) MmioAddr;\r
+ for (Index = 0; Index < NR_GRANT_FRAMES; Index++) {\r
+ Parameters.domid = DOMID_SELF;\r
+ Parameters.idx = Index;\r
+ Parameters.space = XENMAPSPACE_grant_table;\r
+ Parameters.gpfn = (((xen_pfn_t) GrantTable) >> EFI_PAGE_SHIFT) + Index;\r
+ ReturnCode = XenHypercallMemoryOp (Dev, XENMEM_add_to_physmap, &Parameters);\r
+ if (ReturnCode != 0) {\r
+ DEBUG ((EFI_D_ERROR, "Xen GrantTable, add_to_physmap hypercall error: %d\n", ReturnCode));\r
+ }\r
+ }\r
+}\r
+\r
+VOID\r
+XenGrantTableDeinit (\r
+ XENBUS_DEVICE *Dev\r
+ )\r
+{\r
+ INTN ReturnCode, Index;\r
+ xen_remove_from_physmap_t Parameters;\r
+\r
+ if (GrantTable == NULL) {\r
+ return;\r
+ }\r
+\r
+ for (Index = NR_GRANT_FRAMES - 1; Index >= 0; Index--) {\r
+ Parameters.domid = DOMID_SELF;\r
+ Parameters.gpfn = (((xen_pfn_t) GrantTable) >> EFI_PAGE_SHIFT) + Index;\r
+ DEBUG ((EFI_D_INFO, "Xen GrantTable, removing %X\n", Parameters.gpfn));\r
+ ReturnCode = XenHypercallMemoryOp (Dev, XENMEM_remove_from_physmap, &Parameters);\r
+ if (ReturnCode != 0) {\r
+ DEBUG ((EFI_D_ERROR, "Xen GrantTable, remove_from_physmap hypercall error: %d\n", ReturnCode));\r
+ }\r
+ }\r
+ GrantTable = NULL;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+XenBusGrantAccess (\r
+ IN XENBUS_PROTOCOL *This,\r
+ IN domid_t DomainId,\r
+ IN UINTN Frame, // MFN\r
+ IN BOOLEAN ReadOnly,\r
+ OUT grant_ref_t *RefPtr\r
+ )\r
+{\r
+ *RefPtr = XenGrantTableGrantAccess (DomainId, Frame, ReadOnly);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+XenBusGrantEndAccess (\r
+ IN XENBUS_PROTOCOL *This,\r
+ IN grant_ref_t Ref\r
+ )\r
+{\r
+ return XenGrantTableEndAccess (Ref);\r
+}\r
--- /dev/null
+/** @file\r
+ Grant Table function declaration.\r
+\r
+ Grant Table are used to grant access to certain page of the current\r
+ VM to an other VM.\r
+\r
+ Copyright (C) 2014, Citrix Ltd.\r
+\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#ifndef __GNTTAB_H__\r
+#define __GNTTAB_H__\r
+\r
+#include <IndustryStandard/Xen/grant_table.h>\r
+\r
+/**\r
+ Initialize the Grant Table at the address MmioAddr.\r
+\r
+ @param Dev A pointer to XENBUS_DEVICE.\r
+ @param MmioAddr An address where the grant table can be mapped into\r
+ the guest.\r
+**/\r
+VOID\r
+XenGrantTableInit (\r
+ IN XENBUS_DEVICE *Dev,\r
+ IN UINT64 MmioAddr\r
+ );\r
+\r
+/**\r
+ Desinitilize the Grant Table.\r
+**/\r
+VOID\r
+XenGrantTableDeinit (\r
+ IN XENBUS_DEVICE *Dev\r
+ );\r
+\r
+/**\r
+ Grant access to the page Frame to the domain DomainId.\r
+\r
+ @param This A pointer to XENBUS_PROTOCOL instance.\r
+ @param DomainId ID of the domain to grant acces to.\r
+ @param Frame Frame Number of the page to grant access to.\r
+ @param ReadOnly Provide read-only or read-write access.\r
+ @param RefPtr Reference number of the grant will be writen to this pointer.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XenBusGrantAccess (\r
+ IN XENBUS_PROTOCOL *This,\r
+ IN domid_t DomainId,\r
+ IN UINTN Frame, // MFN\r
+ IN BOOLEAN ReadOnly,\r
+ OUT grant_ref_t *RefPtr\r
+ );\r
+\r
+/**\r
+ End access to grant Ref, previously return by XenBusGrantAccess.\r
+\r
+ @param This A pointer to XENBUS_PROTOCOL instance.\r
+ @param Ref Reference numeber of a grant previously returned by\r
+ XenBusGrantAccess.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+XenBusGrantEndAccess (\r
+ IN XENBUS_PROTOCOL *This,\r
+ IN grant_ref_t Ref\r
+ );\r
+\r
+#endif /* !__GNTTAB_H__ */\r
#include "XenBusDxe.h"\r
\r
#include "XenHypercall.h"\r
+#include "GrantTable.h"\r
\r
\r
///\r
EFI_STATUS Status;\r
XENBUS_DEVICE *Dev;\r
EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;\r
+ UINT64 MmioAddr;\r
\r
Status = gBS->OpenProtocol (\r
ControllerHandle,\r
mMyDevice = Dev;\r
EfiReleaseLock (&mMyDeviceLock);\r
\r
+ //\r
+ // The BAR1 of this PCI device is used for shared memory and is supposed to\r
+ // look like MMIO. The address space of the BAR1 will be used to map the\r
+ // Grant Table.\r
+ //\r
+ Status = PciIo->GetBarAttributes (PciIo, PCI_BAR_IDX1, NULL, (VOID**) &BarDesc);\r
+ ASSERT_EFI_ERROR (Status);\r
+ ASSERT (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM);\r
+\r
+ /* Get a Memory address for mapping the Grant Table. */\r
+ DEBUG ((EFI_D_INFO, "XenBus: BAR at %LX\n", BarDesc->AddrRangeMin));\r
+ MmioAddr = BarDesc->AddrRangeMin;\r
+ FreePool (BarDesc);\r
+\r
Status = XenHyperpageInit (Dev);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((EFI_D_ERROR, "XenBus: Unable to retrieve the hyperpage.\n"));\r
goto ErrorAllocated;\r
}\r
\r
+ XenGrantTableInit (Dev, MmioAddr);\r
+\r
Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,\r
NotifyExitBoot,\r
(VOID*) Dev,\r
XENBUS_DEVICE *Dev = mMyDevice;\r
\r
gBS->CloseEvent (Dev->ExitBootEvent);\r
+ XenGrantTableDeinit (Dev);\r
\r
gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid,\r
This->DriverBindingHandle, ControllerHandle);\r