diff options
Diffstat (limited to 'OvmfPkg')
-rw-r--r-- | OvmfPkg/XenBusDxe/GrantTable.c | 217 | ||||
-rw-r--r-- | OvmfPkg/XenBusDxe/GrantTable.h | 77 | ||||
-rw-r--r-- | OvmfPkg/XenBusDxe/XenBusDxe.c | 20 | ||||
-rw-r--r-- | OvmfPkg/XenBusDxe/XenBusDxe.inf | 2 |
4 files changed, 316 insertions, 0 deletions
diff --git a/OvmfPkg/XenBusDxe/GrantTable.c b/OvmfPkg/XenBusDxe/GrantTable.c new file mode 100644 index 0000000000..b17fef3605 --- /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@cam.ac.uk)
+ Changes: Grzegorz Milos (gm281@cam.ac.uk)
+ 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 0000000000..5772c56662 --- /dev/null +++ b/OvmfPkg/XenBusDxe/GrantTable.h @@ -0,0 +1,77 @@ +/** @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.
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#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 776d896368..edeb20ef38 100644 --- a/OvmfPkg/XenBusDxe/XenBusDxe.c +++ b/OvmfPkg/XenBusDxe/XenBusDxe.c @@ -30,6 +30,7 @@ #include "XenBusDxe.h"
#include "XenHypercall.h"
+#include "GrantTable.h"
///
@@ -282,6 +283,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,
@@ -313,6 +316,20 @@ XenBusDxeDriverBindingStart ( mMyDevice = Dev;
EfiReleaseLock (&mMyDeviceLock);
+ //
+ // The BAR1 of this PCI device is used for shared memory and is supposed to
+ // look like MMIO. The address space of the BAR1 will be used to map the
+ // Grant Table.
+ //
+ 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.\n"));
@@ -327,6 +344,8 @@ XenBusDxeDriverBindingStart ( goto ErrorAllocated;
}
+ XenGrantTableInit (Dev, MmioAddr);
+
Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
NotifyExitBoot,
(VOID*) Dev,
@@ -380,6 +399,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 4e92a204f2..080e55a9bb 100644 --- a/OvmfPkg/XenBusDxe/XenBusDxe.inf +++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf @@ -38,6 +38,8 @@ XenHypercall.h
InterlockedCompareExchange16.c
InterlockedCompareExchange16.h
+ GrantTable.c
+ GrantTable.h
[Sources.IA32]
Ia32/hypercall.S
|