]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/VmgExitLib/VmgExitLib.c
OvmfPkg/VmgExitLib: Implement new VmgExitLib interfaces
[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 ((ExitInfo.Elements.Lower32Bits == 0) ||
40 (ExitInfo.Elements.Lower32Bits == 1));
41
42 Status = 0;
43 if (ExitInfo.Elements.Lower32Bits == 0) {
44 return Status;
45 }
46
47 if (ExitInfo.Elements.Lower32Bits == 1) {
48 ASSERT (Ghcb->SaveArea.SwExitInfo2 != 0);
49
50 //
51 // Check that the return event is valid
52 //
53 Event.Uint64 = Ghcb->SaveArea.SwExitInfo2;
54 if (Event.Elements.Valid &&
55 Event.Elements.Type == GHCB_EVENT_INJECTION_TYPE_EXCEPTION) {
56 switch (Event.Elements.Vector) {
57 case GP_EXCEPTION:
58 case UD_EXCEPTION:
59 //
60 // Use returned event as return code
61 //
62 Status = Event.Uint64;
63 }
64 }
65 }
66
67 if (Status == 0) {
68 GHCB_EVENT_INJECTION GpEvent;
69
70 GpEvent.Uint64 = 0;
71 GpEvent.Elements.Vector = GP_EXCEPTION;
72 GpEvent.Elements.Type = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;
73 GpEvent.Elements.Valid = 1;
74
75 Status = GpEvent.Uint64;
76 }
77
78 return Status;
79 }
80
81 /**
82 Perform VMGEXIT.
83
84 Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and
85 then handles the return actions.
86
87 @param[in, out] Ghcb A pointer to the GHCB
88 @param[in] ExitCode VMGEXIT code to be assigned to the SwExitCode
89 field of the GHCB.
90 @param[in] ExitInfo1 VMGEXIT information to be assigned to the
91 SwExitInfo1 field of the GHCB.
92 @param[in] ExitInfo2 VMGEXIT information to be assigned to the
93 SwExitInfo2 field of the GHCB.
94
95 @retval 0 VMGEXIT succeeded.
96 @return Exception number to be propagated, VMGEXIT
97 processing did not succeed.
98
99 **/
100 UINT64
101 EFIAPI
102 VmgExit (
103 IN OUT GHCB *Ghcb,
104 IN UINT64 ExitCode,
105 IN UINT64 ExitInfo1,
106 IN UINT64 ExitInfo2
107 )
108 {
109 Ghcb->SaveArea.SwExitCode = ExitCode;
110 Ghcb->SaveArea.SwExitInfo1 = ExitInfo1;
111 Ghcb->SaveArea.SwExitInfo2 = ExitInfo2;
112
113 //
114 // Guest memory is used for the guest-hypervisor communication, so fence
115 // the invocation of the VMGEXIT instruction to ensure GHCB accesses are
116 // synchronized properly.
117 //
118 MemoryFence ();
119 AsmVmgExit ();
120 MemoryFence ();
121
122 return VmgExitErrorCheck (Ghcb);
123 }
124
125 /**
126 Perform pre-VMGEXIT initialization/preparation.
127
128 Performs the necessary steps in preparation for invoking VMGEXIT. Must be
129 called before setting any fields within the GHCB.
130
131 @param[in, out] Ghcb A pointer to the GHCB
132
133 **/
134 VOID
135 EFIAPI
136 VmgInit (
137 IN OUT GHCB *Ghcb
138 )
139 {
140 SetMem (&Ghcb->SaveArea, sizeof (Ghcb->SaveArea), 0);
141 }
142
143 /**
144 Perform post-VMGEXIT cleanup.
145
146 Performs the necessary steps to cleanup after invoking VMGEXIT. Must be
147 called after obtaining needed fields within the GHCB.
148
149 @param[in, out] Ghcb A pointer to the GHCB
150
151 **/
152 VOID
153 EFIAPI
154 VmgDone (
155 IN OUT GHCB *Ghcb
156 )
157 {
158 }
159
160 /**
161 Marks a field at the specified offset as valid in the GHCB.
162
163 The ValidBitmap area represents the areas of the GHCB that have been marked
164 valid. Set the bit in ValidBitmap for the input offset.
165
166 @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication Block
167 @param[in] Offset Qword offset in the GHCB to mark valid
168
169 **/
170 VOID
171 EFIAPI
172 VmgSetOffsetValid (
173 IN OUT GHCB *Ghcb,
174 IN GHCB_REGISTER Offset
175 )
176 {
177 UINT32 OffsetIndex;
178 UINT32 OffsetBit;
179
180 OffsetIndex = Offset / 8;
181 OffsetBit = Offset % 8;
182
183 Ghcb->SaveArea.ValidBitmap[OffsetIndex] |= (1 << OffsetBit);
184 }
185
186 /**
187 Checks if a specified offset is valid in the GHCB.
188
189 The ValidBitmap area represents the areas of the GHCB that have been marked
190 valid. Return whether the bit in the ValidBitmap is set for the input offset.
191
192 @param[in] Ghcb A pointer to the GHCB
193 @param[in] Offset Qword offset in the GHCB to mark valid
194
195 @retval TRUE Offset is marked valid in the GHCB
196 @retval FALSE Offset is not marked valid in the GHCB
197
198 **/
199 BOOLEAN
200 EFIAPI
201 VmgIsOffsetValid (
202 IN GHCB *Ghcb,
203 IN GHCB_REGISTER Offset
204 )
205 {
206 UINT32 OffsetIndex;
207 UINT32 OffsetBit;
208
209 OffsetIndex = Offset / 8;
210 OffsetBit = Offset % 8;
211
212 return ((Ghcb->SaveArea.ValidBitmap[OffsetIndex] & (1 << OffsetBit)) != 0);
213 }