aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/OvmfPkg/XenBusDxe/GrantTable.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/edk2/OvmfPkg/XenBusDxe/GrantTable.c')
-rw-r--r--roms/edk2/OvmfPkg/XenBusDxe/GrantTable.c201
1 files changed, 201 insertions, 0 deletions
diff --git a/roms/edk2/OvmfPkg/XenBusDxe/GrantTable.c b/roms/edk2/OvmfPkg/XenBusDxe/GrantTable.c
new file mode 100644
index 000000000..58d687aba
--- /dev/null
+++ b/roms/edk2/OvmfPkg/XenBusDxe/GrantTable.c
@@ -0,0 +1,201 @@
+/** @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@cam.ac.uk)
+ Changes: Grzegorz Milos (gm281@cam.ac.uk)
+ Copyright (C) 2006, Cambridge University
+ Copyright (C) 2014, Citrix Ltd.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "XenBusDxe.h"
+
+#include <IndustryStandard/Xen/memory.h>
+
+#include <Library/XenHypercallLib.h>
+#include <Library/SynchronizationLib.h>
+
+#include "GrantTable.h"
+
+#define NR_RESERVED_ENTRIES 8
+
+#define NR_GRANT_FRAMES (FixedPcdGet32 (PcdXenGrantFrames))
+#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
+ )
+{
+ grant_ref_t 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;
+ UINT16 Flags;
+
+ ASSERT (GrantTable != NULL);
+ Ref = XenGrantTableGetFreeEntry ();
+ GrantTable[Ref].frame = (UINT32)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 ((DEBUG_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
+ )
+{
+ 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 ((grant_ref_t)Index);
+ }
+
+ GrantTable = (VOID*)(UINTN) Dev->XenIo->GrantTableAddress;
+ 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) ((UINTN) GrantTable >> EFI_PAGE_SHIFT) + Index;
+ ReturnCode = XenHypercallMemoryOp (XENMEM_add_to_physmap, &Parameters);
+ if (ReturnCode != 0) {
+ DEBUG ((DEBUG_ERROR,
+ "Xen GrantTable, add_to_physmap hypercall error: %Ld\n",
+ (INT64)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) ((UINTN) GrantTable >> EFI_PAGE_SHIFT) + Index;
+ DEBUG ((DEBUG_INFO, "Xen GrantTable, removing %Lx\n",
+ (UINT64)Parameters.gpfn));
+ ReturnCode = XenHypercallMemoryOp (XENMEM_remove_from_physmap, &Parameters);
+ if (ReturnCode != 0) {
+ DEBUG ((DEBUG_ERROR,
+ "Xen GrantTable, remove_from_physmap hypercall error: %Ld\n",
+ (INT64)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);
+}