VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/OvmfPkg/Library/CcExitLib/CcExitLib.c@ 99404

Last change on this file since 99404 was 99404, checked in by vboxsync, 2 years ago

Devices/EFI/FirmwareNew: Update to edk2-stable202302 and make it build, bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette