]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/VmgExitLib/VmgExitLib.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / Library / VmgExitLib / VmgExitLib.c
1 /** @file
2 VMGEXIT Support Library.
3
4 Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include <Base.h>
10 #include <Uefi.h>
11 #include <Library/BaseMemoryLib.h>
12 #include <Library/VmgExitLib.h>
13 #include <Register/Amd/Msr.h>
14
15 /**
16 Check for VMGEXIT error
17
18 Check if the hypervisor has returned an error after completion of the VMGEXIT
19 by examining the SwExitInfo1 field of the GHCB.
20
21 @param[in] Ghcb A pointer to the GHCB
22
23 @retval 0 VMGEXIT succeeded.
24 @return Exception number to be propagated, VMGEXIT processing
25 did not succeed.
26
27 **/
28 STATIC
29 UINT64
30 VmgExitErrorCheck (
31 IN GHCB *Ghcb
32 )
33 {
34 GHCB_EVENT_INJECTION Event;
35 GHCB_EXIT_INFO ExitInfo;
36 UINT64 Status;
37
38 ExitInfo.Uint64 = Ghcb->SaveArea.SwExitInfo1;
39 ASSERT (
40 (ExitInfo.Elements.Lower32Bits == 0) ||
41 (ExitInfo.Elements.Lower32Bits == 1)
42 );
43
44 Status = 0;
45 if (ExitInfo.Elements.Lower32Bits == 0) {
46 return Status;
47 }
48
49 if (ExitInfo.Elements.Lower32Bits == 1) {
50 ASSERT (Ghcb->SaveArea.SwExitInfo2 != 0);
51
52 //
53 // Check that the return event is valid
54 //
55 Event.Uint64 = Ghcb->SaveArea.SwExitInfo2;
56 if (Event.Elements.Valid &&
57 (Event.Elements.Type == GHCB_EVENT_INJECTION_TYPE_EXCEPTION))
58 {
59 switch (Event.Elements.Vector) {
60 case GP_EXCEPTION:
61 case UD_EXCEPTION:
62 //
63 // Use returned event as return code
64 //
65 Status = Event.Uint64;
66 }
67 }
68 }
69
70 if (Status == 0) {
71 GHCB_EVENT_INJECTION GpEvent;
72
73 GpEvent.Uint64 = 0;
74 GpEvent.Elements.Vector = GP_EXCEPTION;
75 GpEvent.Elements.Type = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;
76 GpEvent.Elements.Valid = 1;
77
78 Status = GpEvent.Uint64;
79 }
80
81 return Status;
82 }
83
84 /**
85 Perform VMGEXIT.
86
87 Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and
88 then handles the return actions.
89
90 @param[in, out] Ghcb A pointer to the GHCB
91 @param[in] ExitCode VMGEXIT code to be assigned to the SwExitCode
92 field of the GHCB.
93 @param[in] ExitInfo1 VMGEXIT information to be assigned to the
94 SwExitInfo1 field of the GHCB.
95 @param[in] ExitInfo2 VMGEXIT information to be assigned to the
96 SwExitInfo2 field of the GHCB.
97
98 @retval 0 VMGEXIT succeeded.
99 @return Exception number to be propagated, VMGEXIT
100 processing did not succeed.
101
102 **/
103 UINT64
104 EFIAPI
105 VmgExit (
106 IN OUT GHCB *Ghcb,
107 IN UINT64 ExitCode,
108 IN UINT64 ExitInfo1,
109 IN UINT64 ExitInfo2
110 )
111 {
112 Ghcb->SaveArea.SwExitCode = ExitCode;
113 Ghcb->SaveArea.SwExitInfo1 = ExitInfo1;
114 Ghcb->SaveArea.SwExitInfo2 = ExitInfo2;
115
116 VmgSetOffsetValid (Ghcb, GhcbSwExitCode);
117 VmgSetOffsetValid (Ghcb, GhcbSwExitInfo1);
118 VmgSetOffsetValid (Ghcb, GhcbSwExitInfo2);
119
120 //
121 // Guest memory is used for the guest-hypervisor communication, so fence
122 // the invocation of the VMGEXIT instruction to ensure GHCB accesses are
123 // synchronized properly.
124 //
125 MemoryFence ();
126 AsmVmgExit ();
127 MemoryFence ();
128
129 return VmgExitErrorCheck (Ghcb);
130 }
131
132 /**
133 Perform pre-VMGEXIT initialization/preparation.
134
135 Performs the necessary steps in preparation for invoking VMGEXIT. Must be
136 called before setting any fields within the GHCB.
137
138 @param[in, out] Ghcb A pointer to the GHCB
139 @param[in, out] InterruptState A pointer to hold the current interrupt
140 state, used for restoring in VmgDone ()
141
142 **/
143 VOID
144 EFIAPI
145 VmgInit (
146 IN OUT GHCB *Ghcb,
147 IN OUT BOOLEAN *InterruptState
148 )
149 {
150 //
151 // Be sure that an interrupt can't cause a #VC while the GHCB is
152 // being used.
153 //
154 *InterruptState = GetInterruptState ();
155 if (*InterruptState) {
156 DisableInterrupts ();
157 }
158
159 SetMem (&Ghcb->SaveArea, sizeof (Ghcb->SaveArea), 0);
160 }
161
162 /**
163 Perform post-VMGEXIT cleanup.
164
165 Performs the necessary steps to cleanup after invoking VMGEXIT. Must be
166 called after obtaining needed fields within the GHCB.
167
168 @param[in, out] Ghcb A pointer to the GHCB
169 @param[in] InterruptState An indicator to conditionally (re)enable
170 interrupts
171
172 **/
173 VOID
174 EFIAPI
175 VmgDone (
176 IN OUT GHCB *Ghcb,
177 IN BOOLEAN InterruptState
178 )
179 {
180 if (InterruptState) {
181 EnableInterrupts ();
182 }
183 }
184
185 /**
186 Marks a field at the specified offset as valid in the GHCB.
187
188 The ValidBitmap area represents the areas of the GHCB that have been marked
189 valid. Set the bit in ValidBitmap for the input offset.
190
191 @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication Block
192 @param[in] Offset Qword offset in the GHCB to mark valid
193
194 **/
195 VOID
196 EFIAPI
197 VmgSetOffsetValid (
198 IN OUT GHCB *Ghcb,
199 IN GHCB_REGISTER Offset
200 )
201 {
202 UINT32 OffsetIndex;
203 UINT32 OffsetBit;
204
205 OffsetIndex = Offset / 8;
206 OffsetBit = Offset % 8;
207
208 Ghcb->SaveArea.ValidBitmap[OffsetIndex] |= (1 << OffsetBit);
209 }
210
211 /**
212 Checks if a specified offset is valid in the GHCB.
213
214 The ValidBitmap area represents the areas of the GHCB that have been marked
215 valid. Return whether the bit in the ValidBitmap is set for the input offset.
216
217 @param[in] Ghcb A pointer to the GHCB
218 @param[in] Offset Qword offset in the GHCB to mark valid
219
220 @retval TRUE Offset is marked valid in the GHCB
221 @retval FALSE Offset is not marked valid in the GHCB
222
223 **/
224 BOOLEAN
225 EFIAPI
226 VmgIsOffsetValid (
227 IN GHCB *Ghcb,
228 IN GHCB_REGISTER Offset
229 )
230 {
231 UINT32 OffsetIndex;
232 UINT32 OffsetBit;
233
234 OffsetIndex = Offset / 8;
235 OffsetBit = Offset % 8;
236
237 return ((Ghcb->SaveArea.ValidBitmap[OffsetIndex] & (1 << OffsetBit)) != 0);
238 }