]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - OvmfPkg/XenBusDxe/GrantTable.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / XenBusDxe / GrantTable.c
... / ...
CommitLineData
1/** @file\r
2 Grant Table function implementation.\r
3\r
4 Grant Table are used to grant access to certain page of the current\r
5 VM to an other VM.\r
6\r
7 Author: Steven Smith (sos22@cam.ac.uk)\r
8 Changes: Grzegorz Milos (gm281@cam.ac.uk)\r
9 Copyright (C) 2006, Cambridge University\r
10 Copyright (C) 2014, Citrix Ltd.\r
11\r
12 SPDX-License-Identifier: BSD-2-Clause-Patent\r
13**/\r
14#include "XenBusDxe.h"\r
15\r
16#include <IndustryStandard/Xen/memory.h>\r
17\r
18#include <Library/XenHypercallLib.h>\r
19#include <Library/SynchronizationLib.h>\r
20\r
21#include "GrantTable.h"\r
22\r
23#define NR_RESERVED_ENTRIES 8\r
24\r
25#define NR_GRANT_FRAMES (FixedPcdGet32 (PcdXenGrantFrames))\r
26#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * EFI_PAGE_SIZE / sizeof(grant_entry_v1_t))\r
27\r
28STATIC grant_entry_v1_t *GrantTable = NULL;\r
29STATIC grant_ref_t GrantList[NR_GRANT_ENTRIES];\r
30STATIC EFI_LOCK mGrantListLock;\r
31#ifdef GNT_DEBUG\r
32STATIC BOOLEAN GrantInUseList[NR_GRANT_ENTRIES];\r
33#endif\r
34\r
35STATIC\r
36VOID\r
37XenGrantTablePutFreeEntry (\r
38 grant_ref_t Ref\r
39 )\r
40{\r
41 EfiAcquireLock (&mGrantListLock);\r
42 #ifdef GNT_DEBUG\r
43 ASSERT (GrantInUseList[Ref]);\r
44 GrantInUseList[Ref] = FALSE;\r
45 #endif\r
46 GrantList[Ref] = GrantList[0];\r
47 GrantList[0] = Ref;\r
48 EfiReleaseLock (&mGrantListLock);\r
49}\r
50\r
51STATIC\r
52grant_ref_t\r
53XenGrantTableGetFreeEntry (\r
54 VOID\r
55 )\r
56{\r
57 grant_ref_t Ref;\r
58\r
59 EfiAcquireLock (&mGrantListLock);\r
60 Ref = GrantList[0];\r
61 ASSERT (Ref >= NR_RESERVED_ENTRIES && Ref < NR_GRANT_ENTRIES);\r
62 GrantList[0] = GrantList[Ref];\r
63 #ifdef GNT_DEBUG\r
64 ASSERT (!GrantInUseList[Ref]);\r
65 GrantInUseList[Ref] = TRUE;\r
66 #endif\r
67 EfiReleaseLock (&mGrantListLock);\r
68 return Ref;\r
69}\r
70\r
71STATIC\r
72grant_ref_t\r
73XenGrantTableGrantAccess (\r
74 IN domid_t DomainId,\r
75 IN UINTN Frame,\r
76 IN BOOLEAN ReadOnly\r
77 )\r
78{\r
79 grant_ref_t Ref;\r
80 UINT16 Flags;\r
81\r
82 ASSERT (GrantTable != NULL);\r
83 Ref = XenGrantTableGetFreeEntry ();\r
84 GrantTable[Ref].frame = (UINT32)Frame;\r
85 GrantTable[Ref].domid = DomainId;\r
86 MemoryFence ();\r
87 Flags = GTF_permit_access;\r
88 if (ReadOnly) {\r
89 Flags |= GTF_readonly;\r
90 }\r
91\r
92 GrantTable[Ref].flags = Flags;\r
93\r
94 return Ref;\r
95}\r
96\r
97STATIC\r
98EFI_STATUS\r
99XenGrantTableEndAccess (\r
100 grant_ref_t Ref\r
101 )\r
102{\r
103 UINT16 Flags, OldFlags;\r
104\r
105 ASSERT (GrantTable != NULL);\r
106 ASSERT (Ref >= NR_RESERVED_ENTRIES && Ref < NR_GRANT_ENTRIES);\r
107\r
108 OldFlags = GrantTable[Ref].flags;\r
109 do {\r
110 if ((Flags = OldFlags) & (GTF_reading | GTF_writing)) {\r
111 DEBUG ((DEBUG_WARN, "WARNING: g.e. still in use! (%x)\n", Flags));\r
112 return EFI_NOT_READY;\r
113 }\r
114\r
115 OldFlags = InterlockedCompareExchange16 (&GrantTable[Ref].flags, Flags, 0);\r
116 } while (OldFlags != Flags);\r
117\r
118 XenGrantTablePutFreeEntry (Ref);\r
119 return EFI_SUCCESS;\r
120}\r
121\r
122VOID\r
123XenGrantTableInit (\r
124 IN XENBUS_DEVICE *Dev\r
125 )\r
126{\r
127 xen_add_to_physmap_t Parameters;\r
128 INTN Index;\r
129 INTN ReturnCode;\r
130\r
131 #ifdef GNT_DEBUG\r
132 SetMem (GrantInUseList, sizeof (GrantInUseList), 1);\r
133 #endif\r
134 EfiInitializeLock (&mGrantListLock, TPL_NOTIFY);\r
135 for (Index = NR_RESERVED_ENTRIES; Index < NR_GRANT_ENTRIES; Index++) {\r
136 XenGrantTablePutFreeEntry ((grant_ref_t)Index);\r
137 }\r
138\r
139 GrantTable = (VOID *)(UINTN)Dev->XenIo->GrantTableAddress;\r
140 for (Index = 0; Index < NR_GRANT_FRAMES; Index++) {\r
141 Parameters.domid = DOMID_SELF;\r
142 Parameters.idx = Index;\r
143 Parameters.space = XENMAPSPACE_grant_table;\r
144 Parameters.gpfn = (xen_pfn_t)((UINTN)GrantTable >> EFI_PAGE_SHIFT) + Index;\r
145 ReturnCode = XenHypercallMemoryOp (XENMEM_add_to_physmap, &Parameters);\r
146 if (ReturnCode != 0) {\r
147 DEBUG ((\r
148 DEBUG_ERROR,\r
149 "Xen GrantTable, add_to_physmap hypercall error: %Ld\n",\r
150 (INT64)ReturnCode\r
151 ));\r
152 }\r
153 }\r
154}\r
155\r
156VOID\r
157XenGrantTableDeinit (\r
158 XENBUS_DEVICE *Dev\r
159 )\r
160{\r
161 INTN ReturnCode, Index;\r
162 xen_remove_from_physmap_t Parameters;\r
163\r
164 if (GrantTable == NULL) {\r
165 return;\r
166 }\r
167\r
168 for (Index = NR_GRANT_FRAMES - 1; Index >= 0; Index--) {\r
169 Parameters.domid = DOMID_SELF;\r
170 Parameters.gpfn = (xen_pfn_t)((UINTN)GrantTable >> EFI_PAGE_SHIFT) + Index;\r
171 DEBUG ((\r
172 DEBUG_INFO,\r
173 "Xen GrantTable, removing %Lx\n",\r
174 (UINT64)Parameters.gpfn\r
175 ));\r
176 ReturnCode = XenHypercallMemoryOp (XENMEM_remove_from_physmap, &Parameters);\r
177 if (ReturnCode != 0) {\r
178 DEBUG ((\r
179 DEBUG_ERROR,\r
180 "Xen GrantTable, remove_from_physmap hypercall error: %Ld\n",\r
181 (INT64)ReturnCode\r
182 ));\r
183 }\r
184 }\r
185\r
186 GrantTable = NULL;\r
187}\r
188\r
189EFI_STATUS\r
190EFIAPI\r
191XenBusGrantAccess (\r
192 IN XENBUS_PROTOCOL *This,\r
193 IN domid_t DomainId,\r
194 IN UINTN Frame, // MFN\r
195 IN BOOLEAN ReadOnly,\r
196 OUT grant_ref_t *RefPtr\r
197 )\r
198{\r
199 *RefPtr = XenGrantTableGrantAccess (DomainId, Frame, ReadOnly);\r
200 return EFI_SUCCESS;\r
201}\r
202\r
203EFI_STATUS\r
204EFIAPI\r
205XenBusGrantEndAccess (\r
206 IN XENBUS_PROTOCOL *This,\r
207 IN grant_ref_t Ref\r
208 )\r
209{\r
210 return XenGrantTableEndAccess (Ref);\r
211}\r