]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/XenBusDxe/GrantTable.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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 #define NR_GRANT_FRAMES (FixedPcdGet32 (PcdXenGrantFrames))
26 #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * EFI_PAGE_SIZE / sizeof(grant_entry_v1_t))
27
28 STATIC grant_entry_v1_t *GrantTable = NULL;
29 STATIC grant_ref_t GrantList[NR_GRANT_ENTRIES];
30 STATIC EFI_LOCK mGrantListLock;
31 #ifdef GNT_DEBUG
32 STATIC BOOLEAN GrantInUseList[NR_GRANT_ENTRIES];
33 #endif
34
35 STATIC
36 VOID
37 XenGrantTablePutFreeEntry (
38 grant_ref_t Ref
39 )
40 {
41 EfiAcquireLock (&mGrantListLock);
42 #ifdef GNT_DEBUG
43 ASSERT (GrantInUseList[Ref]);
44 GrantInUseList[Ref] = FALSE;
45 #endif
46 GrantList[Ref] = GrantList[0];
47 GrantList[0] = Ref;
48 EfiReleaseLock (&mGrantListLock);
49 }
50
51 STATIC
52 grant_ref_t
53 XenGrantTableGetFreeEntry (
54 VOID
55 )
56 {
57 grant_ref_t Ref;
58
59 EfiAcquireLock (&mGrantListLock);
60 Ref = GrantList[0];
61 ASSERT (Ref >= NR_RESERVED_ENTRIES && Ref < NR_GRANT_ENTRIES);
62 GrantList[0] = GrantList[Ref];
63 #ifdef GNT_DEBUG
64 ASSERT (!GrantInUseList[Ref]);
65 GrantInUseList[Ref] = TRUE;
66 #endif
67 EfiReleaseLock (&mGrantListLock);
68 return Ref;
69 }
70
71 STATIC
72 grant_ref_t
73 XenGrantTableGrantAccess (
74 IN domid_t DomainId,
75 IN UINTN Frame,
76 IN BOOLEAN ReadOnly
77 )
78 {
79 grant_ref_t Ref;
80 UINT16 Flags;
81
82 ASSERT (GrantTable != NULL);
83 Ref = XenGrantTableGetFreeEntry ();
84 GrantTable[Ref].frame = (UINT32)Frame;
85 GrantTable[Ref].domid = DomainId;
86 MemoryFence ();
87 Flags = GTF_permit_access;
88 if (ReadOnly) {
89 Flags |= GTF_readonly;
90 }
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 ((DEBUG_WARN, "WARNING: g.e. still in use! (%x)\n", Flags));
112 return EFI_NOT_READY;
113 }
114
115 OldFlags = InterlockedCompareExchange16 (&GrantTable[Ref].flags, Flags, 0);
116 } while (OldFlags != Flags);
117
118 XenGrantTablePutFreeEntry (Ref);
119 return EFI_SUCCESS;
120 }
121
122 VOID
123 XenGrantTableInit (
124 IN XENBUS_DEVICE *Dev
125 )
126 {
127 xen_add_to_physmap_t Parameters;
128 INTN Index;
129 INTN ReturnCode;
130
131 #ifdef GNT_DEBUG
132 SetMem (GrantInUseList, sizeof (GrantInUseList), 1);
133 #endif
134 EfiInitializeLock (&mGrantListLock, TPL_NOTIFY);
135 for (Index = NR_RESERVED_ENTRIES; Index < NR_GRANT_ENTRIES; Index++) {
136 XenGrantTablePutFreeEntry ((grant_ref_t)Index);
137 }
138
139 GrantTable = (VOID *)(UINTN)Dev->XenIo->GrantTableAddress;
140 for (Index = 0; Index < NR_GRANT_FRAMES; Index++) {
141 Parameters.domid = DOMID_SELF;
142 Parameters.idx = Index;
143 Parameters.space = XENMAPSPACE_grant_table;
144 Parameters.gpfn = (xen_pfn_t)((UINTN)GrantTable >> EFI_PAGE_SHIFT) + Index;
145 ReturnCode = XenHypercallMemoryOp (XENMEM_add_to_physmap, &Parameters);
146 if (ReturnCode != 0) {
147 DEBUG ((
148 DEBUG_ERROR,
149 "Xen GrantTable, add_to_physmap hypercall error: %Ld\n",
150 (INT64)ReturnCode
151 ));
152 }
153 }
154 }
155
156 VOID
157 XenGrantTableDeinit (
158 XENBUS_DEVICE *Dev
159 )
160 {
161 INTN ReturnCode, Index;
162 xen_remove_from_physmap_t Parameters;
163
164 if (GrantTable == NULL) {
165 return;
166 }
167
168 for (Index = NR_GRANT_FRAMES - 1; Index >= 0; Index--) {
169 Parameters.domid = DOMID_SELF;
170 Parameters.gpfn = (xen_pfn_t)((UINTN)GrantTable >> EFI_PAGE_SHIFT) + Index;
171 DEBUG ((
172 DEBUG_INFO,
173 "Xen GrantTable, removing %Lx\n",
174 (UINT64)Parameters.gpfn
175 ));
176 ReturnCode = XenHypercallMemoryOp (XENMEM_remove_from_physmap, &Parameters);
177 if (ReturnCode != 0) {
178 DEBUG ((
179 DEBUG_ERROR,
180 "Xen GrantTable, remove_from_physmap hypercall error: %Ld\n",
181 (INT64)ReturnCode
182 ));
183 }
184 }
185
186 GrantTable = NULL;
187 }
188
189 EFI_STATUS
190 EFIAPI
191 XenBusGrantAccess (
192 IN XENBUS_PROTOCOL *This,
193 IN domid_t DomainId,
194 IN UINTN Frame, // MFN
195 IN BOOLEAN ReadOnly,
196 OUT grant_ref_t *RefPtr
197 )
198 {
199 *RefPtr = XenGrantTableGrantAccess (DomainId, Frame, ReadOnly);
200 return EFI_SUCCESS;
201 }
202
203 EFI_STATUS
204 EFIAPI
205 XenBusGrantEndAccess (
206 IN XENBUS_PROTOCOL *This,
207 IN grant_ref_t Ref
208 )
209 {
210 return XenGrantTableEndAccess (Ref);
211 }