]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/XenBusDxe/GrantTable.c
OvmfPkg: replace old EFI_D_ debug levels with new DEBUG_ ones
[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 GrantTable[Ref].flags = Flags;
92
93 return Ref;
94 }
95
96 STATIC
97 EFI_STATUS
98 XenGrantTableEndAccess (
99 grant_ref_t Ref
100 )
101 {
102 UINT16 Flags, OldFlags;
103
104 ASSERT (GrantTable != NULL);
105 ASSERT (Ref >= NR_RESERVED_ENTRIES && Ref < NR_GRANT_ENTRIES);
106
107 OldFlags = GrantTable[Ref].flags;
108 do {
109 if ((Flags = OldFlags) & (GTF_reading | GTF_writing)) {
110 DEBUG ((DEBUG_WARN, "WARNING: g.e. still in use! (%x)\n", Flags));
111 return EFI_NOT_READY;
112 }
113 OldFlags = InterlockedCompareExchange16 (&GrantTable[Ref].flags, Flags, 0);
114 } while (OldFlags != Flags);
115
116 XenGrantTablePutFreeEntry (Ref);
117 return EFI_SUCCESS;
118 }
119
120 VOID
121 XenGrantTableInit (
122 IN XENBUS_DEVICE *Dev
123 )
124 {
125 xen_add_to_physmap_t Parameters;
126 INTN Index;
127 INTN ReturnCode;
128
129 #ifdef GNT_DEBUG
130 SetMem(GrantInUseList, sizeof (GrantInUseList), 1);
131 #endif
132 EfiInitializeLock (&mGrantListLock, TPL_NOTIFY);
133 for (Index = NR_RESERVED_ENTRIES; Index < NR_GRANT_ENTRIES; Index++) {
134 XenGrantTablePutFreeEntry ((grant_ref_t)Index);
135 }
136
137 GrantTable = (VOID*)(UINTN) Dev->XenIo->GrantTableAddress;
138 for (Index = 0; Index < NR_GRANT_FRAMES; Index++) {
139 Parameters.domid = DOMID_SELF;
140 Parameters.idx = Index;
141 Parameters.space = XENMAPSPACE_grant_table;
142 Parameters.gpfn = (xen_pfn_t) ((UINTN) GrantTable >> EFI_PAGE_SHIFT) + Index;
143 ReturnCode = XenHypercallMemoryOp (XENMEM_add_to_physmap, &Parameters);
144 if (ReturnCode != 0) {
145 DEBUG ((DEBUG_ERROR,
146 "Xen GrantTable, add_to_physmap hypercall error: %Ld\n",
147 (INT64)ReturnCode));
148 }
149 }
150 }
151
152 VOID
153 XenGrantTableDeinit (
154 XENBUS_DEVICE *Dev
155 )
156 {
157 INTN ReturnCode, Index;
158 xen_remove_from_physmap_t Parameters;
159
160 if (GrantTable == NULL) {
161 return;
162 }
163
164 for (Index = NR_GRANT_FRAMES - 1; Index >= 0; Index--) {
165 Parameters.domid = DOMID_SELF;
166 Parameters.gpfn = (xen_pfn_t) ((UINTN) GrantTable >> EFI_PAGE_SHIFT) + Index;
167 DEBUG ((DEBUG_INFO, "Xen GrantTable, removing %Lx\n",
168 (UINT64)Parameters.gpfn));
169 ReturnCode = XenHypercallMemoryOp (XENMEM_remove_from_physmap, &Parameters);
170 if (ReturnCode != 0) {
171 DEBUG ((DEBUG_ERROR,
172 "Xen GrantTable, remove_from_physmap hypercall error: %Ld\n",
173 (INT64)ReturnCode));
174 }
175 }
176 GrantTable = NULL;
177 }
178
179 EFI_STATUS
180 EFIAPI
181 XenBusGrantAccess (
182 IN XENBUS_PROTOCOL *This,
183 IN domid_t DomainId,
184 IN UINTN Frame, // MFN
185 IN BOOLEAN ReadOnly,
186 OUT grant_ref_t *RefPtr
187 )
188 {
189 *RefPtr = XenGrantTableGrantAccess (DomainId, Frame, ReadOnly);
190 return EFI_SUCCESS;
191 }
192
193 EFI_STATUS
194 EFIAPI
195 XenBusGrantEndAccess (
196 IN XENBUS_PROTOCOL *This,
197 IN grant_ref_t Ref
198 )
199 {
200 return XenGrantTableEndAccess (Ref);
201 }