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