]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/XenBusDxe/GrantTable.c
IntelFsp2Pkg/SplitFspBin.py: Support rebasing 1.x binary.
[mirror_edk2.git] / OvmfPkg / XenBusDxe / GrantTable.c
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 SPDX-License-Identifier: BSD-2-Clause-Patent
13 **/
14 #include "XenBusDxe.h"
15
16 #include <IndustryStandard/Xen/memory.h>
17
18 #include <Library/XenHypercallLib.h>
19 #include <Library/SynchronizationLib.h>
20
21 #include "GrantTable.h"
22
23 #define NR_RESERVED_ENTRIES 8
24
25 /* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
26 #define NR_GRANT_FRAMES 4
27 #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * EFI_PAGE_SIZE / sizeof(grant_entry_v1_t))
28
29 STATIC grant_entry_v1_t *GrantTable = NULL;
30 STATIC grant_ref_t GrantList[NR_GRANT_ENTRIES];
31 STATIC EFI_LOCK mGrantListLock;
32 #ifdef GNT_DEBUG
33 STATIC BOOLEAN GrantInUseList[NR_GRANT_ENTRIES];
34 #endif
35
36 STATIC
37 VOID
38 XenGrantTablePutFreeEntry (
39 grant_ref_t Ref
40 )
41 {
42 EfiAcquireLock (&mGrantListLock);
43 #ifdef GNT_DEBUG
44 ASSERT (GrantInUseList[Ref]);
45 GrantInUseList[Ref] = FALSE;
46 #endif
47 GrantList[Ref] = GrantList[0];
48 GrantList[0] = Ref;
49 EfiReleaseLock (&mGrantListLock);
50 }
51
52 STATIC
53 grant_ref_t
54 XenGrantTableGetFreeEntry (
55 VOID
56 )
57 {
58 grant_ref_t Ref;
59
60 EfiAcquireLock (&mGrantListLock);
61 Ref = GrantList[0];
62 ASSERT (Ref >= NR_RESERVED_ENTRIES && Ref < NR_GRANT_ENTRIES);
63 GrantList[0] = GrantList[Ref];
64 #ifdef GNT_DEBUG
65 ASSERT (!GrantInUseList[Ref]);
66 GrantInUseList[Ref] = TRUE;
67 #endif
68 EfiReleaseLock (&mGrantListLock);
69 return Ref;
70 }
71
72 STATIC
73 grant_ref_t
74 XenGrantTableGrantAccess (
75 IN domid_t DomainId,
76 IN UINTN Frame,
77 IN BOOLEAN ReadOnly
78 )
79 {
80 grant_ref_t Ref;
81 UINT16 Flags;
82
83 ASSERT (GrantTable != NULL);
84 Ref = XenGrantTableGetFreeEntry ();
85 GrantTable[Ref].frame = (UINT32)Frame;
86 GrantTable[Ref].domid = DomainId;
87 MemoryFence ();
88 Flags = GTF_permit_access;
89 if (ReadOnly) {
90 Flags |= GTF_readonly;
91 }
92 GrantTable[Ref].flags = Flags;
93
94 return Ref;
95 }
96
97 STATIC
98 EFI_STATUS
99 XenGrantTableEndAccess (
100 grant_ref_t Ref
101 )
102 {
103 UINT16 Flags, OldFlags;
104
105 ASSERT (GrantTable != NULL);
106 ASSERT (Ref >= NR_RESERVED_ENTRIES && Ref < NR_GRANT_ENTRIES);
107
108 OldFlags = GrantTable[Ref].flags;
109 do {
110 if ((Flags = OldFlags) & (GTF_reading | GTF_writing)) {
111 DEBUG ((EFI_D_WARN, "WARNING: g.e. still in use! (%x)\n", Flags));
112 return EFI_NOT_READY;
113 }
114 OldFlags = InterlockedCompareExchange16 (&GrantTable[Ref].flags, Flags, 0);
115 } while (OldFlags != Flags);
116
117 XenGrantTablePutFreeEntry (Ref);
118 return EFI_SUCCESS;
119 }
120
121 VOID
122 XenGrantTableInit (
123 IN XENBUS_DEVICE *Dev
124 )
125 {
126 xen_add_to_physmap_t Parameters;
127 INTN Index;
128 INTN ReturnCode;
129
130 #ifdef GNT_DEBUG
131 SetMem(GrantInUseList, sizeof (GrantInUseList), 1);
132 #endif
133 EfiInitializeLock (&mGrantListLock, TPL_NOTIFY);
134 for (Index = NR_RESERVED_ENTRIES; Index < NR_GRANT_ENTRIES; Index++) {
135 XenGrantTablePutFreeEntry ((grant_ref_t)Index);
136 }
137
138 GrantTable = (VOID*)(UINTN) Dev->XenIo->GrantTableAddress;
139 for (Index = 0; Index < NR_GRANT_FRAMES; Index++) {
140 Parameters.domid = DOMID_SELF;
141 Parameters.idx = Index;
142 Parameters.space = XENMAPSPACE_grant_table;
143 Parameters.gpfn = (xen_pfn_t) ((UINTN) GrantTable >> EFI_PAGE_SHIFT) + Index;
144 ReturnCode = XenHypercallMemoryOp (XENMEM_add_to_physmap, &Parameters);
145 if (ReturnCode != 0) {
146 DEBUG ((EFI_D_ERROR,
147 "Xen GrantTable, add_to_physmap hypercall error: %Ld\n",
148 (INT64)ReturnCode));
149 }
150 }
151 }
152
153 VOID
154 XenGrantTableDeinit (
155 XENBUS_DEVICE *Dev
156 )
157 {
158 INTN ReturnCode, Index;
159 xen_remove_from_physmap_t Parameters;
160
161 if (GrantTable == NULL) {
162 return;
163 }
164
165 for (Index = NR_GRANT_FRAMES - 1; Index >= 0; Index--) {
166 Parameters.domid = DOMID_SELF;
167 Parameters.gpfn = (xen_pfn_t) ((UINTN) GrantTable >> EFI_PAGE_SHIFT) + Index;
168 DEBUG ((EFI_D_INFO, "Xen GrantTable, removing %Lx\n",
169 (UINT64)Parameters.gpfn));
170 ReturnCode = XenHypercallMemoryOp (XENMEM_remove_from_physmap, &Parameters);
171 if (ReturnCode != 0) {
172 DEBUG ((EFI_D_ERROR,
173 "Xen GrantTable, remove_from_physmap hypercall error: %Ld\n",
174 (INT64)ReturnCode));
175 }
176 }
177 GrantTable = NULL;
178 }
179
180 EFI_STATUS
181 EFIAPI
182 XenBusGrantAccess (
183 IN XENBUS_PROTOCOL *This,
184 IN domid_t DomainId,
185 IN UINTN Frame, // MFN
186 IN BOOLEAN ReadOnly,
187 OUT grant_ref_t *RefPtr
188 )
189 {
190 *RefPtr = XenGrantTableGrantAccess (DomainId, Frame, ReadOnly);
191 return EFI_SUCCESS;
192 }
193
194 EFI_STATUS
195 EFIAPI
196 XenBusGrantEndAccess (
197 IN XENBUS_PROTOCOL *This,
198 IN grant_ref_t Ref
199 )
200 {
201 return XenGrantTableEndAccess (Ref);
202 }