Steven Smith | 0fd1424 | 2014-10-29 06:50:14 +0000 | [diff] [blame] | 1 | /** @file
|
| 2 | Grant Table function implementation.
|
| 3 |
|
| 4 | Grant Table are used to grant access to certain page of the current
|
| 5 | VM to an other VM.
|
| 6 |
|
| 7 | Author: Steven Smith (sos22@cam.ac.uk)
|
| 8 | Changes: Grzegorz Milos (gm281@cam.ac.uk)
|
| 9 | Copyright (C) 2006, Cambridge University
|
| 10 | Copyright (C) 2014, Citrix Ltd.
|
| 11 |
|
| 12 | Redistribution and use in source and binary forms, with or without
|
| 13 | modification, are permitted provided that the following conditions
|
| 14 | are met:
|
| 15 | 1. Redistributions of source code must retain the above copyright
|
| 16 | notice, this list of conditions and the following disclaimer.
|
| 17 | 2. Redistributions in binary form must reproduce the above copyright
|
| 18 | notice, this list of conditions and the following disclaimer in the
|
| 19 | documentation and/or other materials provided with the distribution.
|
| 20 |
|
| 21 | THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
| 22 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
| 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
| 24 | ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
| 25 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
| 26 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
| 27 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
| 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
| 29 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
| 30 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
| 31 | SUCH DAMAGE.
|
| 32 | **/
|
| 33 | #include "XenBusDxe.h"
|
| 34 |
|
| 35 | #include <IndustryStandard/Xen/memory.h>
|
| 36 |
|
| 37 | #include "XenHypercall.h"
|
| 38 |
|
| 39 | #include "GrantTable.h"
|
| 40 | #include "InterlockedCompareExchange16.h"
|
| 41 |
|
| 42 | #define NR_RESERVED_ENTRIES 8
|
| 43 |
|
| 44 | /* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
|
| 45 | #define NR_GRANT_FRAMES 4
|
| 46 | #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * EFI_PAGE_SIZE / sizeof(grant_entry_v1_t))
|
| 47 |
|
| 48 | STATIC grant_entry_v1_t *GrantTable = NULL;
|
| 49 | STATIC grant_ref_t GrantList[NR_GRANT_ENTRIES];
|
| 50 | STATIC EFI_LOCK mGrantListLock;
|
| 51 | #ifdef GNT_DEBUG
|
| 52 | STATIC BOOLEAN GrantInUseList[NR_GRANT_ENTRIES];
|
| 53 | #endif
|
| 54 |
|
| 55 | STATIC
|
| 56 | VOID
|
| 57 | XenGrantTablePutFreeEntry (
|
| 58 | grant_ref_t Ref
|
| 59 | )
|
| 60 | {
|
| 61 | EfiAcquireLock (&mGrantListLock);
|
| 62 | #ifdef GNT_DEBUG
|
| 63 | ASSERT (GrantInUseList[Ref]);
|
| 64 | GrantInUseList[Ref] = FALSE;
|
| 65 | #endif
|
| 66 | GrantList[Ref] = GrantList[0];
|
| 67 | GrantList[0] = Ref;
|
| 68 | EfiReleaseLock (&mGrantListLock);
|
| 69 | }
|
| 70 |
|
| 71 | STATIC
|
| 72 | grant_ref_t
|
| 73 | XenGrantTableGetFreeEntry (
|
| 74 | VOID
|
| 75 | )
|
| 76 | {
|
Anthony PERARD | cec6ad0 | 2014-11-14 17:35:29 +0000 | [diff] [blame] | 77 | grant_ref_t Ref;
|
Steven Smith | 0fd1424 | 2014-10-29 06:50:14 +0000 | [diff] [blame] | 78 |
|
| 79 | EfiAcquireLock (&mGrantListLock);
|
| 80 | Ref = GrantList[0];
|
| 81 | ASSERT (Ref >= NR_RESERVED_ENTRIES && Ref < NR_GRANT_ENTRIES);
|
| 82 | GrantList[0] = GrantList[Ref];
|
| 83 | #ifdef GNT_DEBUG
|
| 84 | ASSERT (!GrantInUseList[Ref]);
|
| 85 | GrantInUseList[Ref] = TRUE;
|
| 86 | #endif
|
| 87 | EfiReleaseLock (&mGrantListLock);
|
| 88 | return Ref;
|
| 89 | }
|
| 90 |
|
| 91 | STATIC
|
| 92 | grant_ref_t
|
| 93 | XenGrantTableGrantAccess (
|
| 94 | IN domid_t DomainId,
|
| 95 | IN UINTN Frame,
|
| 96 | IN BOOLEAN ReadOnly
|
| 97 | )
|
| 98 | {
|
| 99 | grant_ref_t Ref;
|
Anthony PERARD | cec6ad0 | 2014-11-14 17:35:29 +0000 | [diff] [blame] | 100 | UINT16 Flags;
|
Steven Smith | 0fd1424 | 2014-10-29 06:50:14 +0000 | [diff] [blame] | 101 |
|
| 102 | ASSERT (GrantTable != NULL);
|
| 103 | Ref = XenGrantTableGetFreeEntry ();
|
Scott Duplichan | 017a486 | 2014-11-14 17:35:35 +0000 | [diff] [blame^] | 104 | GrantTable[Ref].frame = (UINT32)Frame;
|
Steven Smith | 0fd1424 | 2014-10-29 06:50:14 +0000 | [diff] [blame] | 105 | GrantTable[Ref].domid = DomainId;
|
| 106 | MemoryFence ();
|
| 107 | Flags = GTF_permit_access;
|
| 108 | if (ReadOnly) {
|
| 109 | Flags |= GTF_readonly;
|
| 110 | }
|
| 111 | GrantTable[Ref].flags = Flags;
|
| 112 |
|
| 113 | return Ref;
|
| 114 | }
|
| 115 |
|
| 116 | STATIC
|
| 117 | EFI_STATUS
|
| 118 | XenGrantTableEndAccess (
|
| 119 | grant_ref_t Ref
|
| 120 | )
|
| 121 | {
|
| 122 | UINT16 Flags, OldFlags;
|
| 123 |
|
| 124 | ASSERT (GrantTable != NULL);
|
| 125 | ASSERT (Ref >= NR_RESERVED_ENTRIES && Ref < NR_GRANT_ENTRIES);
|
| 126 |
|
| 127 | OldFlags = GrantTable[Ref].flags;
|
| 128 | do {
|
| 129 | if ((Flags = OldFlags) & (GTF_reading | GTF_writing)) {
|
| 130 | DEBUG ((EFI_D_WARN, "WARNING: g.e. still in use! (%x)\n", Flags));
|
| 131 | return EFI_NOT_READY;
|
| 132 | }
|
| 133 | OldFlags = InterlockedCompareExchange16 (&GrantTable[Ref].flags, Flags, 0);
|
| 134 | } while (OldFlags != Flags);
|
| 135 |
|
| 136 | XenGrantTablePutFreeEntry (Ref);
|
| 137 | return EFI_SUCCESS;
|
| 138 | }
|
| 139 |
|
| 140 | VOID
|
| 141 | XenGrantTableInit (
|
| 142 | IN XENBUS_DEVICE *Dev,
|
| 143 | IN UINT64 MmioAddr
|
| 144 | )
|
| 145 | {
|
| 146 | xen_add_to_physmap_t Parameters;
|
| 147 | INTN Index;
|
| 148 | INTN ReturnCode;
|
| 149 |
|
| 150 | #ifdef GNT_DEBUG
|
| 151 | SetMem(GrantInUseList, sizeof (GrantInUseList), 1);
|
| 152 | #endif
|
| 153 | EfiInitializeLock (&mGrantListLock, TPL_NOTIFY);
|
| 154 | for (Index = NR_RESERVED_ENTRIES; Index < NR_GRANT_ENTRIES; Index++) {
|
Scott Duplichan | 017a486 | 2014-11-14 17:35:35 +0000 | [diff] [blame^] | 155 | XenGrantTablePutFreeEntry ((grant_ref_t)Index);
|
Steven Smith | 0fd1424 | 2014-10-29 06:50:14 +0000 | [diff] [blame] | 156 | }
|
| 157 |
|
| 158 | GrantTable = (VOID*)(UINTN) MmioAddr;
|
| 159 | for (Index = 0; Index < NR_GRANT_FRAMES; Index++) {
|
| 160 | Parameters.domid = DOMID_SELF;
|
| 161 | Parameters.idx = Index;
|
| 162 | Parameters.space = XENMAPSPACE_grant_table;
|
| 163 | Parameters.gpfn = (((xen_pfn_t) GrantTable) >> EFI_PAGE_SHIFT) + Index;
|
| 164 | ReturnCode = XenHypercallMemoryOp (Dev, XENMEM_add_to_physmap, &Parameters);
|
| 165 | if (ReturnCode != 0) {
|
| 166 | DEBUG ((EFI_D_ERROR, "Xen GrantTable, add_to_physmap hypercall error: %d\n", ReturnCode));
|
| 167 | }
|
| 168 | }
|
| 169 | }
|
| 170 |
|
| 171 | VOID
|
| 172 | XenGrantTableDeinit (
|
| 173 | XENBUS_DEVICE *Dev
|
| 174 | )
|
| 175 | {
|
| 176 | INTN ReturnCode, Index;
|
| 177 | xen_remove_from_physmap_t Parameters;
|
| 178 |
|
| 179 | if (GrantTable == NULL) {
|
| 180 | return;
|
| 181 | }
|
| 182 |
|
| 183 | for (Index = NR_GRANT_FRAMES - 1; Index >= 0; Index--) {
|
| 184 | Parameters.domid = DOMID_SELF;
|
| 185 | Parameters.gpfn = (((xen_pfn_t) GrantTable) >> EFI_PAGE_SHIFT) + Index;
|
| 186 | DEBUG ((EFI_D_INFO, "Xen GrantTable, removing %X\n", Parameters.gpfn));
|
| 187 | ReturnCode = XenHypercallMemoryOp (Dev, XENMEM_remove_from_physmap, &Parameters);
|
| 188 | if (ReturnCode != 0) {
|
| 189 | DEBUG ((EFI_D_ERROR, "Xen GrantTable, remove_from_physmap hypercall error: %d\n", ReturnCode));
|
| 190 | }
|
| 191 | }
|
| 192 | GrantTable = NULL;
|
| 193 | }
|
| 194 |
|
| 195 | EFI_STATUS
|
| 196 | EFIAPI
|
| 197 | XenBusGrantAccess (
|
| 198 | IN XENBUS_PROTOCOL *This,
|
| 199 | IN domid_t DomainId,
|
| 200 | IN UINTN Frame, // MFN
|
| 201 | IN BOOLEAN ReadOnly,
|
| 202 | OUT grant_ref_t *RefPtr
|
| 203 | )
|
| 204 | {
|
| 205 | *RefPtr = XenGrantTableGrantAccess (DomainId, Frame, ReadOnly);
|
| 206 | return EFI_SUCCESS;
|
| 207 | }
|
| 208 |
|
| 209 | EFI_STATUS
|
| 210 | EFIAPI
|
| 211 | XenBusGrantEndAccess (
|
| 212 | IN XENBUS_PROTOCOL *This,
|
| 213 | IN grant_ref_t Ref
|
| 214 | )
|
| 215 | {
|
| 216 | return XenGrantTableEndAccess (Ref);
|
| 217 | }
|