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