VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/OvmfPkg/Library/CcExitLib/CcExitVeHandler.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: 20.1 KB
Line 
1/** @file
2
3 Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
4
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7**/
8
9#include <Library/BaseLib.h>
10#include <Library/DebugLib.h>
11#include "CcExitTd.h"
12#include <Library/CcExitLib.h>
13#include <Library/BaseMemoryLib.h>
14#include <IndustryStandard/Tdx.h>
15#include <IndustryStandard/InstructionParsing.h>
16#include "CcInstruction.h"
17
18#define TDX_MMIO_READ 0
19#define TDX_MMIO_WRITE 1
20
21typedef union {
22 struct {
23 UINT32 Eax;
24 UINT32 Edx;
25 } Regs;
26 UINT64 Val;
27} MSR_DATA;
28
29typedef union {
30 UINT8 Val;
31 struct {
32 UINT8 B : 1;
33 UINT8 X : 1;
34 UINT8 R : 1;
35 UINT8 W : 1;
36 } Bits;
37} REX;
38
39typedef union {
40 UINT8 Val;
41 struct {
42 UINT8 Rm : 3;
43 UINT8 Reg : 3;
44 UINT8 Mod : 2;
45 } Bits;
46} MODRM;
47
48typedef struct {
49 UINT64 Regs[4];
50} CPUID_DATA;
51
52/**
53 Handle an CPUID event.
54
55 Use the TDVMCALL instruction to handle cpuid #ve
56
57 @param[in, out] Regs x64 processor context
58 @param[in] Veinfo VE Info
59
60 @retval 0 Event handled successfully
61 @return New exception value to propagate
62**/
63STATIC
64UINT64
65EFIAPI
66CpuIdExit (
67 IN EFI_SYSTEM_CONTEXT_X64 *Regs,
68 IN TDCALL_VEINFO_RETURN_DATA *Veinfo
69 )
70{
71 CPUID_DATA CpuIdData;
72 UINT64 Status;
73
74 Status = TdVmCallCpuid (Regs->Rax, Regs->Rcx, &CpuIdData);
75
76 if (Status == 0) {
77 Regs->Rax = CpuIdData.Regs[0];
78 Regs->Rbx = CpuIdData.Regs[1];
79 Regs->Rcx = CpuIdData.Regs[2];
80 Regs->Rdx = CpuIdData.Regs[3];
81 }
82
83 return Status;
84}
85
86/**
87 Handle an IO event.
88
89 Use the TDVMCALL instruction to handle either an IO read or an IO write.
90
91 @param[in, out] Regs x64 processor context
92 @param[in] Veinfo VE Info
93
94 @retval 0 Event handled successfully
95 @return New exception value to propagate
96**/
97STATIC
98UINT64
99EFIAPI
100IoExit (
101 IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
102 IN TDCALL_VEINFO_RETURN_DATA *Veinfo
103 )
104{
105 BOOLEAN Write;
106 UINTN Size;
107 UINTN Port;
108 UINT64 Val;
109 UINT64 RepCnt;
110 UINT64 Status;
111
112 Val = 0;
113 Status = 0;
114 Write = Veinfo->ExitQualification.Io.Direction ? FALSE : TRUE;
115 Size = Veinfo->ExitQualification.Io.Size + 1;
116 Port = Veinfo->ExitQualification.Io.Port;
117
118 if (Veinfo->ExitQualification.Io.String) {
119 //
120 // If REP is set, get rep-cnt from Rcx
121 //
122 RepCnt = Veinfo->ExitQualification.Io.Rep ? Regs->Rcx : 1;
123
124 while (RepCnt) {
125 Val = 0;
126 if (Write == TRUE) {
127 CopyMem (&Val, (VOID *)Regs->Rsi, Size);
128 Regs->Rsi += Size;
129 }
130
131 Status = TdVmCall (EXIT_REASON_IO_INSTRUCTION, Size, Write, Port, Val, (Write ? NULL : &Val));
132 if (Status != 0) {
133 break;
134 }
135
136 if (Write == FALSE) {
137 CopyMem ((VOID *)Regs->Rdi, &Val, Size);
138 Regs->Rdi += Size;
139 }
140
141 if (Veinfo->ExitQualification.Io.Rep) {
142 Regs->Rcx -= 1;
143 }
144
145 RepCnt -= 1;
146 }
147 } else {
148 if (Write == TRUE) {
149 CopyMem (&Val, (VOID *)&Regs->Rax, Size);
150 }
151
152 Status = TdVmCall (EXIT_REASON_IO_INSTRUCTION, Size, Write, Port, Val, (Write ? NULL : &Val));
153 if ((Status == 0) && (Write == FALSE)) {
154 CopyMem ((VOID *)&Regs->Rax, &Val, Size);
155 }
156 }
157
158 return Status;
159}
160
161/**
162 Handle an READ MSR event.
163
164 Use the TDVMCALL instruction to handle msr read
165
166 @param[in, out] Regs x64 processor context
167 @param[in] Veinfo VE Info
168
169 @retval 0 Event handled successfully
170 @return New exception value to propagate
171**/
172STATIC
173UINT64
174ReadMsrExit (
175 IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
176 IN TDCALL_VEINFO_RETURN_DATA *Veinfo
177 )
178{
179 MSR_DATA Data;
180 UINT64 Status;
181
182 Status = TdVmCall (EXIT_REASON_MSR_READ, Regs->Rcx, 0, 0, 0, &Data);
183 if (Status == 0) {
184 Regs->Rax = Data.Regs.Eax;
185 Regs->Rdx = Data.Regs.Edx;
186 }
187
188 return Status;
189}
190
191/**
192 Handle an WRITE MSR event.
193
194 Use the TDVMCALL instruction to handle msr write
195
196 @param[in, out] Regs x64 processor context
197 @param[in] Veinfo VE Info
198
199 @retval 0 Event handled successfully
200 @return New exception value to propagate
201**/
202STATIC
203UINT64
204WriteMsrExit (
205 IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
206 IN TDCALL_VEINFO_RETURN_DATA *Veinfo
207 )
208{
209 UINT64 Status;
210 MSR_DATA Data;
211
212 Data.Regs.Eax = (UINT32)Regs->Rax;
213 Data.Regs.Edx = (UINT32)Regs->Rdx;
214
215 Status = TdVmCall (EXIT_REASON_MSR_WRITE, Regs->Rcx, Data.Val, 0, 0, NULL);
216
217 return Status;
218}
219
220STATIC
221VOID
222EFIAPI
223TdxDecodeInstruction (
224 IN UINT8 *Rip,
225 IN UINT32 Length
226 )
227{
228 UINTN i;
229
230 DEBUG ((DEBUG_INFO, "TDX: #TD[EPT] instruction (%p):", Rip));
231 for (i = 0; i < MIN (15, Length); i++) {
232 DEBUG ((DEBUG_INFO, "%02x ", Rip[i]));
233 }
234
235 DEBUG ((DEBUG_INFO, "\n"));
236}
237
238#define TDX_DECODER_BUG_ON(x) \
239 if ((x)) { \
240 TdxDecodeInstruction(Rip); \
241 TdVmCall(TDVMCALL_HALT, 0, 0, 0, 0, 0); \
242 CpuDeadLoop (); \
243 }
244
245/**
246 * Tdx MMIO access via TdVmcall.
247 *
248 * @param MmioSize Size of the MMIO access
249 * @param ReadOrWrite Read or write operation
250 * @param GuestPA Guest physical address
251 * @param Val Pointer to the value which is read or written
252
253 * @retval EFI_SUCCESS Successfully access the mmio
254 * @retval Others Other errors as indicated
255 */
256STATIC
257EFI_STATUS
258TdxMmioReadWrite (
259 IN UINT32 MmioSize,
260 IN UINT32 ReadOrWrite,
261 IN UINT64 GuestPA,
262 IN UINT64 *Val
263 )
264{
265 UINT64 TdStatus;
266
267 if ((MmioSize != 1) && (MmioSize != 2) && (MmioSize != 4) && (MmioSize != 8)) {
268 DEBUG ((DEBUG_ERROR, "%a: Invalid MmioSize - %d\n", __FUNCTION__, MmioSize));
269 return EFI_INVALID_PARAMETER;
270 }
271
272 if (Val == NULL) {
273 return EFI_INVALID_PARAMETER;
274 }
275
276 TdStatus = 0;
277 if (ReadOrWrite == TDX_MMIO_READ) {
278 TdStatus = TdVmCall (TDVMCALL_MMIO, MmioSize, TDX_MMIO_READ, GuestPA, 0, Val);
279 } else if (ReadOrWrite == TDX_MMIO_WRITE) {
280 TdStatus = TdVmCall (TDVMCALL_MMIO, MmioSize, TDX_MMIO_WRITE, GuestPA, *Val, 0);
281 } else {
282 return EFI_INVALID_PARAMETER;
283 }
284
285 if (TdStatus != 0) {
286 DEBUG ((DEBUG_ERROR, "%a: TdVmcall failed with %llx\n", __FUNCTION__, TdStatus));
287 return EFI_ABORTED;
288 }
289
290 return EFI_SUCCESS;
291}
292
293typedef struct {
294 UINT8 OpCode;
295 UINT32 Bytes;
296 EFI_PHYSICAL_ADDRESS Address;
297 UINT64 Val;
298 UINT64 *Register;
299 UINT32 ReadOrWrite;
300} MMIO_EXIT_PARSED_INSTRUCTION;
301
302/**
303 * Parse the MMIO instructions.
304 *
305 * @param Regs Pointer to the EFI_SYSTEM_CONTEXT_X64 which includes the instructions
306 * @param InstructionData Pointer to the CC_INSTRUCTION_DATA
307 * @param ParsedInstruction Pointer to the parsed instruction data
308 *
309 * @retval EFI_SUCCESS Successfully parsed the instructions
310 * @retval Others Other error as indicated
311 */
312STATIC
313EFI_STATUS
314ParseMmioExitInstructions (
315 IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
316 IN OUT CC_INSTRUCTION_DATA *InstructionData,
317 OUT MMIO_EXIT_PARSED_INSTRUCTION *ParsedInstruction
318 )
319{
320 EFI_STATUS Status;
321 UINT8 OpCode;
322 UINT8 SignByte;
323 UINT32 Bytes;
324 EFI_PHYSICAL_ADDRESS Address;
325 UINT64 Val;
326 UINT64 *Register;
327 UINT32 ReadOrWrite;
328
329 Address = 0;
330 Bytes = 0;
331 Register = NULL;
332 Status = EFI_SUCCESS;
333 Val = 0;
334
335 Status = CcInitInstructionData (InstructionData, NULL, Regs);
336 if (EFI_ERROR (Status)) {
337 DEBUG ((DEBUG_ERROR, "%a: Initialize InstructionData failed! (%r)\n", __FUNCTION__, Status));
338 return Status;
339 }
340
341 OpCode = *(InstructionData->OpCodes);
342 if (OpCode == TWO_BYTE_OPCODE_ESCAPE) {
343 OpCode = *(InstructionData->OpCodes + 1);
344 }
345
346 switch (OpCode) {
347 //
348 // MMIO write (MOV reg/memX, regX)
349 //
350 case 0x88:
351 Bytes = 1;
352 //
353 // fall through
354 //
355 case 0x89:
356 CcDecodeModRm (Regs, InstructionData);
357 Bytes = ((Bytes != 0) ? Bytes :
358 (InstructionData->DataSize == Size16Bits) ? 2 :
359 (InstructionData->DataSize == Size32Bits) ? 4 :
360 (InstructionData->DataSize == Size64Bits) ? 8 :
361 0);
362
363 if (InstructionData->Ext.ModRm.Mod == 3) {
364 DEBUG ((DEBUG_ERROR, "%a: Parse Ext.ModRm.Mod error! (OpCode: 0x%x)\n", __FUNCTION__, OpCode));
365 return EFI_UNSUPPORTED;
366 }
367
368 Address = InstructionData->Ext.RmData;
369 Val = InstructionData->Ext.RegData;
370 ReadOrWrite = TDX_MMIO_WRITE;
371
372 break;
373
374 //
375 // MMIO write (MOV moffsetX, aX)
376 //
377 case 0xA2:
378 Bytes = 1;
379 //
380 // fall through
381 //
382 case 0xA3:
383 Bytes = ((Bytes != 0) ? Bytes :
384 (InstructionData->DataSize == Size16Bits) ? 2 :
385 (InstructionData->DataSize == Size32Bits) ? 4 :
386 (InstructionData->DataSize == Size64Bits) ? 8 :
387 0);
388
389 InstructionData->ImmediateSize = (UINTN)(1 << InstructionData->AddrSize);
390 InstructionData->End += InstructionData->ImmediateSize;
391 CopyMem (&Address, InstructionData->Immediate, InstructionData->ImmediateSize);
392
393 Val = Regs->Rax;
394 ReadOrWrite = TDX_MMIO_WRITE;
395 break;
396
397 //
398 // MMIO write (MOV reg/memX, immX)
399 //
400 case 0xC6:
401 Bytes = 1;
402 //
403 // fall through
404 //
405 case 0xC7:
406 CcDecodeModRm (Regs, InstructionData);
407 Bytes = ((Bytes != 0) ? Bytes :
408 (InstructionData->DataSize == Size16Bits) ? 2 :
409 (InstructionData->DataSize == Size32Bits) ? 4 :
410 (InstructionData->DataSize == Size64Bits) ? 8 :
411 0);
412
413 InstructionData->ImmediateSize = Bytes;
414 InstructionData->End += Bytes;
415
416 Val = 0;
417 CopyMem (&Val, InstructionData->Immediate, InstructionData->ImmediateSize);
418
419 Address = InstructionData->Ext.RmData;
420 ReadOrWrite = TDX_MMIO_WRITE;
421
422 break;
423
424 //
425 // MMIO read (MOV regX, reg/memX)
426 //
427 case 0x8A:
428 Bytes = 1;
429 //
430 // fall through
431 //
432 case 0x8B:
433 CcDecodeModRm (Regs, InstructionData);
434 Bytes = ((Bytes != 0) ? Bytes :
435 (InstructionData->DataSize == Size16Bits) ? 2 :
436 (InstructionData->DataSize == Size32Bits) ? 4 :
437 (InstructionData->DataSize == Size64Bits) ? 8 :
438 0);
439 if (InstructionData->Ext.ModRm.Mod == 3) {
440 //
441 // NPF on two register operands???
442 //
443 DEBUG ((DEBUG_ERROR, "%a: Parse Ext.ModRm.Mod error! (OpCode: 0x%x)\n", __FUNCTION__, OpCode));
444 return EFI_UNSUPPORTED;
445 }
446
447 Address = InstructionData->Ext.RmData;
448 ReadOrWrite = TDX_MMIO_READ;
449
450 Register = CcGetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);
451 if (Register == NULL) {
452 return EFI_ABORTED;
453 }
454
455 if (Bytes == 4) {
456 //
457 // Zero-extend for 32-bit operation
458 //
459 *Register = 0;
460 }
461
462 break;
463
464 //
465 // MMIO read (MOV aX, moffsetX)
466 //
467 case 0xA0:
468 Bytes = 1;
469 //
470 // fall through
471 //
472 case 0xA1:
473 Bytes = ((Bytes != 0) ? Bytes :
474 (InstructionData->DataSize == Size16Bits) ? 2 :
475 (InstructionData->DataSize == Size32Bits) ? 4 :
476 (InstructionData->DataSize == Size64Bits) ? 8 :
477 0);
478
479 InstructionData->ImmediateSize = (UINTN)(1 << InstructionData->AddrSize);
480 InstructionData->End += InstructionData->ImmediateSize;
481
482 Address = 0;
483 CopyMem (
484 &Address,
485 InstructionData->Immediate,
486 InstructionData->ImmediateSize
487 );
488
489 if (Bytes == 4) {
490 //
491 // Zero-extend for 32-bit operation
492 //
493 Regs->Rax = 0;
494 }
495
496 Register = &Regs->Rax;
497 ReadOrWrite = TDX_MMIO_READ;
498
499 break;
500
501 //
502 // MMIO read w/ zero-extension ((MOVZX regX, reg/memX)
503 //
504 case 0xB6:
505 Bytes = 1;
506 //
507 // fall through
508 //
509 case 0xB7:
510 CcDecodeModRm (Regs, InstructionData);
511 Bytes = (Bytes != 0) ? Bytes : 2;
512 Address = InstructionData->Ext.RmData;
513
514 Register = CcGetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);
515 if (Register == NULL) {
516 return EFI_ABORTED;
517 }
518
519 SetMem (Register, (UINTN)(1 << InstructionData->DataSize), 0);
520
521 ReadOrWrite = TDX_MMIO_READ;
522
523 break;
524
525 //
526 // MMIO read w/ sign-extension (MOVSX regX, reg/memX)
527 //
528 case 0xBE:
529 Bytes = 1;
530 //
531 // fall through
532 //
533 case 0xBF:
534 CcDecodeModRm (Regs, InstructionData);
535 Bytes = (Bytes != 0) ? Bytes : 2;
536
537 Address = InstructionData->Ext.RmData;
538
539 if (Bytes == 1) {
540 UINT8 *Data;
541 Data = (UINT8 *)&Val;
542 SignByte = ((*Data & BIT7) != 0) ? 0xFF : 0x00;
543 } else {
544 UINT16 *Data;
545 Data = (UINT16 *)&Val;
546 SignByte = ((*Data & BIT15) != 0) ? 0xFF : 0x00;
547 }
548
549 Register = CcGetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);
550 if (Register == NULL) {
551 return EFI_ABORTED;
552 }
553
554 SetMem (Register, (UINTN)(1 << InstructionData->DataSize), SignByte);
555
556 ReadOrWrite = TDX_MMIO_READ;
557
558 break;
559
560 default:
561 DEBUG ((DEBUG_ERROR, "%a: Invalid MMIO opcode (%x)\n", __FUNCTION__, OpCode));
562 Status = EFI_UNSUPPORTED;
563 }
564
565 if (!EFI_ERROR (Status)) {
566 ParsedInstruction->OpCode = OpCode;
567 ParsedInstruction->Address = Address;
568 ParsedInstruction->Bytes = Bytes;
569 ParsedInstruction->Register = Register;
570 ParsedInstruction->Val = Val;
571 ParsedInstruction->ReadOrWrite = ReadOrWrite;
572 }
573
574 return Status;
575}
576
577/**
578 Handle an MMIO event.
579
580 Use the TDVMCALL instruction to handle either an mmio read or an mmio write.
581
582 @param[in, out] Regs x64 processor context
583 @param[in] Veinfo VE Info
584
585 @retval 0 Event handled successfully
586**/
587STATIC
588UINT64
589EFIAPI
590MmioExit (
591 IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
592 IN TDCALL_VEINFO_RETURN_DATA *Veinfo
593 )
594{
595 UINT64 TdStatus;
596 EFI_STATUS Status;
597 TD_RETURN_DATA TdReturnData;
598 UINT8 Gpaw;
599 UINT64 Val;
600 UINT64 TdSharedPageMask;
601 CC_INSTRUCTION_DATA InstructionData;
602 MMIO_EXIT_PARSED_INSTRUCTION ParsedInstruction;
603
604 TdStatus = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData);
605 if (TdStatus == TDX_EXIT_REASON_SUCCESS) {
606 Gpaw = (UINT8)(TdReturnData.TdInfo.Gpaw & 0x3f);
607 TdSharedPageMask = 1ULL << (Gpaw - 1);
608 } else {
609 DEBUG ((DEBUG_ERROR, "%a: TDCALL failed with status=%llx\n", __FUNCTION__, TdStatus));
610 goto FatalError;
611 }
612
613 if ((Veinfo->GuestPA & TdSharedPageMask) == 0) {
614 DEBUG ((DEBUG_ERROR, "%a: EPT-violation #VE on private memory is not allowed!", __FUNCTION__));
615 goto FatalError;
616 }
617
618 Status = ParseMmioExitInstructions (Regs, &InstructionData, &ParsedInstruction);
619 if (EFI_ERROR (Status)) {
620 goto FatalError;
621 }
622
623 if (Veinfo->GuestPA != (ParsedInstruction.Address | TdSharedPageMask)) {
624 DEBUG ((
625 DEBUG_ERROR,
626 "%a: Address is not correct! (%d: 0x%llx != 0x%llx)\n",
627 __FUNCTION__,
628 ParsedInstruction.OpCode,
629 Veinfo->GuestPA,
630 ParsedInstruction.Address
631 ));
632 goto FatalError;
633 }
634
635 if (ParsedInstruction.ReadOrWrite == TDX_MMIO_WRITE ) {
636 Status = TdxMmioReadWrite (ParsedInstruction.Bytes, TDX_MMIO_WRITE, Veinfo->GuestPA, &ParsedInstruction.Val);
637 } else if (ParsedInstruction.ReadOrWrite == TDX_MMIO_READ) {
638 Val = 0;
639 Status = TdxMmioReadWrite (ParsedInstruction.Bytes, TDX_MMIO_READ, Veinfo->GuestPA, &Val);
640 if (!EFI_ERROR (Status)) {
641 CopyMem (ParsedInstruction.Register, &Val, ParsedInstruction.Bytes);
642 }
643 } else {
644 goto FatalError;
645 }
646
647 if (EFI_ERROR (Status)) {
648 goto FatalError;
649 }
650
651 //
652 // We change instruction length to reflect true size so handler can
653 // bump rip
654 //
655 Veinfo->ExitInstructionLength = (UINT32)(CcInstructionLength (&InstructionData));
656 TdxDecodeInstruction ((UINT8 *)Regs->Rip, Veinfo->ExitInstructionLength);
657
658 return 0;
659
660FatalError:
661 TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);
662 CpuDeadLoop ();
663 return 0;
664}
665
666/**
667 Handle a #VE exception.
668
669 Performs the necessary processing to handle a #VE exception.
670
671 @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be set
672 as value to use on error.
673 @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT
674
675 @retval EFI_SUCCESS Exception handled
676 @retval EFI_UNSUPPORTED #VE not supported, (new) exception value to
677 propagate provided
678 @retval EFI_PROTOCOL_ERROR #VE handling failed, (new) exception value to
679 propagate provided
680
681**/
682EFI_STATUS
683EFIAPI
684CcExitHandleVe (
685 IN OUT EFI_EXCEPTION_TYPE *ExceptionType,
686 IN OUT EFI_SYSTEM_CONTEXT SystemContext
687 )
688{
689 UINT64 Status;
690 TD_RETURN_DATA ReturnData;
691 EFI_SYSTEM_CONTEXT_X64 *Regs;
692
693 Regs = SystemContext.SystemContextX64;
694 Status = TdCall (TDCALL_TDGETVEINFO, 0, 0, 0, &ReturnData);
695 ASSERT (Status == 0);
696 if (Status != 0) {
697 DEBUG ((DEBUG_ERROR, "#VE happened. TDGETVEINFO failed with Status = 0x%llx\n", Status));
698 TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);
699 CpuDeadLoop ();
700 }
701
702 switch (ReturnData.VeInfo.ExitReason) {
703 case EXIT_REASON_CPUID:
704 Status = CpuIdExit (Regs, &ReturnData.VeInfo);
705 DEBUG ((
706 DEBUG_VERBOSE,
707 "CPUID #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",
708 ReturnData.VeInfo.ExitReason,
709 ReturnData.VeInfo.ExitQualification.Val
710 ));
711 break;
712
713 case EXIT_REASON_HLT:
714 Status = TdVmCall (EXIT_REASON_HLT, 0, 0, 0, 0, 0);
715 break;
716
717 case EXIT_REASON_IO_INSTRUCTION:
718 Status = IoExit (Regs, &ReturnData.VeInfo);
719 DEBUG ((
720 DEBUG_VERBOSE,
721 "IO_Instruction #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",
722 ReturnData.VeInfo.ExitReason,
723 ReturnData.VeInfo.ExitQualification.Val
724 ));
725 break;
726
727 case EXIT_REASON_MSR_READ:
728 Status = ReadMsrExit (Regs, &ReturnData.VeInfo);
729 DEBUG ((
730 DEBUG_VERBOSE,
731 "RDMSR #VE happened, ExitReasion is %d, ExitQualification = 0x%x. Regs->Rcx=0x%llx, Status = 0x%llx\n",
732 ReturnData.VeInfo.ExitReason,
733 ReturnData.VeInfo.ExitQualification.Val,
734 Regs->Rcx,
735 Status
736 ));
737 break;
738
739 case EXIT_REASON_MSR_WRITE:
740 Status = WriteMsrExit (Regs, &ReturnData.VeInfo);
741 DEBUG ((
742 DEBUG_VERBOSE,
743 "WRMSR #VE happened, ExitReasion is %d, ExitQualification = 0x%x. Regs->Rcx=0x%llx, Status = 0x%llx\n",
744 ReturnData.VeInfo.ExitReason,
745 ReturnData.VeInfo.ExitQualification.Val,
746 Regs->Rcx,
747 Status
748 ));
749 break;
750
751 case EXIT_REASON_EPT_VIOLATION:
752 Status = MmioExit (Regs, &ReturnData.VeInfo);
753 DEBUG ((
754 DEBUG_VERBOSE,
755 "MMIO #VE happened, ExitReasion is %d, ExitQualification = 0x%x.\n",
756 ReturnData.VeInfo.ExitReason,
757 ReturnData.VeInfo.ExitQualification.Val
758 ));
759 break;
760
761 case EXIT_REASON_VMCALL:
762 case EXIT_REASON_MWAIT_INSTRUCTION:
763 case EXIT_REASON_MONITOR_INSTRUCTION:
764 case EXIT_REASON_WBINVD:
765 case EXIT_REASON_RDPMC:
766 case EXIT_REASON_INVD:
767 /* Handle as nops. */
768 break;
769
770 default:
771 DEBUG ((
772 DEBUG_ERROR,
773 "Unsupported #VE happened, ExitReason is %d, ExitQualification = 0x%x.\n",
774 ReturnData.VeInfo.ExitReason,
775 ReturnData.VeInfo.ExitQualification.Val
776 ));
777
778 ASSERT (FALSE);
779 CpuDeadLoop ();
780 }
781
782 if (Status) {
783 DEBUG ((
784 DEBUG_ERROR,
785 "#VE Error (0x%llx) returned from host, ExitReason is %d, ExitQualification = 0x%x.\n",
786 Status,
787 ReturnData.VeInfo.ExitReason,
788 ReturnData.VeInfo.ExitQualification.Val
789 ));
790
791 TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);
792 CpuDeadLoop ();
793 }
794
795 SystemContext.SystemContextX64->Rip += ReturnData.VeInfo.ExitInstructionLength;
796 return EFI_SUCCESS;
797}
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