TianoCore EDK2 master
Loading...
Searching...
No Matches
CcExitVcHandler.c
Go to the documentation of this file.
1
9#include <Base.h>
10#include <Uefi.h>
14#include <Library/CcExitLib.h>
15#include <Library/AmdSvsmLib.h>
16#include <Register/Amd/Msr.h>
19
20#include "CcExitVcHandler.h"
21#include "CcInstruction.h"
22
23//
24// Non-automatic Exit function prototype
25//
26typedef
27UINT64
28(*NAE_EXIT) (
29 GHCB *Ghcb,
31 CC_INSTRUCTION_DATA *InstructionData
32 );
33
34//
35// SEV-SNP Cpuid table entry/function
36//
37typedef PACKED struct {
38 UINT32 EaxIn;
39 UINT32 EcxIn;
40 UINT64 Unused;
41 UINT64 Unused2;
42 UINT32 Eax;
43 UINT32 Ebx;
44 UINT32 Ecx;
45 UINT32 Edx;
46 UINT64 Reserved;
47} SEV_SNP_CPUID_FUNCTION;
48
49//
50// SEV-SNP Cpuid page format
51//
52typedef PACKED struct {
53 UINT32 Count;
54 UINT32 Reserved1;
55 UINT64 Reserved2;
56 SEV_SNP_CPUID_FUNCTION function[0];
57} SEV_SNP_CPUID_INFO;
58
73UINT64
75 IN GHCB *Ghcb,
77 IN CC_INSTRUCTION_DATA *InstructionData
78 )
79{
80 UINT64 Status;
81
82 Status = CcExitVmgExit (Ghcb, SVM_EXIT_UNSUPPORTED, Regs->ExceptionData, 0);
83 if (Status == 0) {
85
86 Event.Uint64 = 0;
87 Event.Elements.Vector = GP_EXCEPTION;
88 Event.Elements.Type = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;
89 Event.Elements.Valid = 1;
90
91 Status = Event.Uint64;
92 }
93
94 return Status;
95}
96
111STATIC
112UINT64
114 IN GHCB *Ghcb,
115 IN UINTN MemoryAddress,
116 IN UINTN MemoryLength
117 )
118{
119 MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE State;
120 GHCB_EVENT_INJECTION GpEvent;
121
123 0,
124 MemoryAddress,
125 MemoryLength
126 );
127 if (State == MemEncryptSevAddressRangeUnencrypted) {
128 return 0;
129 }
130
131 //
132 // Any state other than unencrypted is an error, issue a #GP.
133 //
134 DEBUG ((
135 DEBUG_ERROR,
136 "MMIO using encrypted memory: %lx\n",
137 (UINT64)MemoryAddress
138 ));
139 GpEvent.Uint64 = 0;
140 GpEvent.Elements.Vector = GP_EXCEPTION;
141 GpEvent.Elements.Type = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;
142 GpEvent.Elements.Valid = 1;
143
144 return GpEvent.Uint64;
145}
146
161STATIC
162UINT64
164 IN OUT GHCB *Ghcb,
166 IN OUT CC_INSTRUCTION_DATA *InstructionData
167 )
168{
169 UINT64 ExitInfo1, ExitInfo2, Status;
170 UINTN Bytes;
171 UINT64 *Register;
172 UINT8 OpCode, SignByte;
173 UINTN Address;
174
175 Bytes = 0;
176
177 OpCode = *(InstructionData->OpCodes);
178 if (OpCode == TWO_BYTE_OPCODE_ESCAPE) {
179 OpCode = *(InstructionData->OpCodes + 1);
180 }
181
182 switch (OpCode) {
183 //
184 // MMIO write (MOV reg/memX, regX)
185 //
186 case 0x88:
187 Bytes = 1;
188 //
189 // fall through
190 //
191 case 0x89:
192 CcDecodeModRm (Regs, InstructionData);
193 Bytes = ((Bytes != 0) ? Bytes :
194 (InstructionData->DataSize == Size16Bits) ? 2 :
195 (InstructionData->DataSize == Size32Bits) ? 4 :
196 (InstructionData->DataSize == Size64Bits) ? 8 :
197 0);
198
199 if (InstructionData->Ext.ModRm.Mod == 3) {
200 //
201 // NPF on two register operands???
202 //
203 return UnsupportedExit (Ghcb, Regs, InstructionData);
204 }
205
206 Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
207 if (Status != 0) {
208 return Status;
209 }
210
211 ExitInfo1 = InstructionData->Ext.RmData;
212 ExitInfo2 = Bytes;
213 CopyMem (Ghcb->SharedBuffer, &InstructionData->Ext.RegData, Bytes);
214
215 Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
216 CcExitVmgSetOffsetValid (Ghcb, GhcbSwScratch);
217 Status = CcExitVmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);
218 if (Status != 0) {
219 return Status;
220 }
221
222 break;
223
224 //
225 // MMIO write (MOV moffsetX, aX)
226 //
227 case 0xA2:
228 Bytes = 1;
229 //
230 // fall through
231 //
232 case 0xA3:
233 Bytes = ((Bytes != 0) ? Bytes :
234 (InstructionData->DataSize == Size16Bits) ? 2 :
235 (InstructionData->DataSize == Size32Bits) ? 4 :
236 (InstructionData->DataSize == Size64Bits) ? 8 :
237 0);
238
239 InstructionData->ImmediateSize = (UINTN)(1 << InstructionData->AddrSize);
240 InstructionData->End += InstructionData->ImmediateSize;
241
242 //
243 // This code is X64 only, so a possible 8-byte copy to a UINTN is ok.
244 // Use a STATIC_ASSERT to be certain the code is being built as X64.
245 //
246 STATIC_ASSERT (
247 sizeof (UINTN) == sizeof (UINT64),
248 "sizeof (UINTN) != sizeof (UINT64), this file must be built as X64"
249 );
250
251 Address = 0;
252 CopyMem (
253 &Address,
254 InstructionData->Immediate,
255 InstructionData->ImmediateSize
256 );
257
258 Status = ValidateMmioMemory (Ghcb, Address, Bytes);
259 if (Status != 0) {
260 return Status;
261 }
262
263 ExitInfo1 = Address;
264 ExitInfo2 = Bytes;
265 CopyMem (Ghcb->SharedBuffer, &Regs->Rax, Bytes);
266
267 Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
268 CcExitVmgSetOffsetValid (Ghcb, GhcbSwScratch);
269 Status = CcExitVmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);
270 if (Status != 0) {
271 return Status;
272 }
273
274 break;
275
276 //
277 // MMIO write (MOV reg/memX, immX)
278 //
279 case 0xC6:
280 Bytes = 1;
281 //
282 // fall through
283 //
284 case 0xC7:
285 CcDecodeModRm (Regs, InstructionData);
286 Bytes = ((Bytes != 0) ? Bytes :
287 (InstructionData->DataSize == Size16Bits) ? 2 :
288 (InstructionData->DataSize == Size32Bits) ? 4 :
289 0);
290
291 InstructionData->ImmediateSize = Bytes;
292 InstructionData->End += Bytes;
293
294 Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
295 if (Status != 0) {
296 return Status;
297 }
298
299 ExitInfo1 = InstructionData->Ext.RmData;
300 ExitInfo2 = Bytes;
301 CopyMem (Ghcb->SharedBuffer, InstructionData->Immediate, Bytes);
302
303 Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
304 CcExitVmgSetOffsetValid (Ghcb, GhcbSwScratch);
305 Status = CcExitVmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);
306 if (Status != 0) {
307 return Status;
308 }
309
310 break;
311
312 //
313 // MMIO read (MOV regX, reg/memX)
314 //
315 case 0x8A:
316 Bytes = 1;
317 //
318 // fall through
319 //
320 case 0x8B:
321 CcDecodeModRm (Regs, InstructionData);
322 Bytes = ((Bytes != 0) ? Bytes :
323 (InstructionData->DataSize == Size16Bits) ? 2 :
324 (InstructionData->DataSize == Size32Bits) ? 4 :
325 (InstructionData->DataSize == Size64Bits) ? 8 :
326 0);
327 if (InstructionData->Ext.ModRm.Mod == 3) {
328 //
329 // NPF on two register operands???
330 //
331 return UnsupportedExit (Ghcb, Regs, InstructionData);
332 }
333
334 Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
335 if (Status != 0) {
336 return Status;
337 }
338
339 ExitInfo1 = InstructionData->Ext.RmData;
340 ExitInfo2 = Bytes;
341
342 Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
343 CcExitVmgSetOffsetValid (Ghcb, GhcbSwScratch);
344 Status = CcExitVmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);
345 if (Status != 0) {
346 return Status;
347 }
348
349 Register = CcGetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);
350 if (Bytes == 4) {
351 //
352 // Zero-extend for 32-bit operation
353 //
354 *Register = 0;
355 }
356
357 CopyMem (Register, Ghcb->SharedBuffer, Bytes);
358 break;
359
360 //
361 // MMIO read (MOV aX, moffsetX)
362 //
363 case 0xA0:
364 Bytes = 1;
365 //
366 // fall through
367 //
368 case 0xA1:
369 Bytes = ((Bytes != 0) ? Bytes :
370 (InstructionData->DataSize == Size16Bits) ? 2 :
371 (InstructionData->DataSize == Size32Bits) ? 4 :
372 (InstructionData->DataSize == Size64Bits) ? 8 :
373 0);
374
375 InstructionData->ImmediateSize = (UINTN)(1 << InstructionData->AddrSize);
376 InstructionData->End += InstructionData->ImmediateSize;
377
378 //
379 // This code is X64 only, so a possible 8-byte copy to a UINTN is ok.
380 // Use a STATIC_ASSERT to be certain the code is being built as X64.
381 //
382 STATIC_ASSERT (
383 sizeof (UINTN) == sizeof (UINT64),
384 "sizeof (UINTN) != sizeof (UINT64), this file must be built as X64"
385 );
386
387 Address = 0;
388 CopyMem (
389 &Address,
390 InstructionData->Immediate,
391 InstructionData->ImmediateSize
392 );
393
394 Status = ValidateMmioMemory (Ghcb, Address, Bytes);
395 if (Status != 0) {
396 return Status;
397 }
398
399 ExitInfo1 = Address;
400 ExitInfo2 = Bytes;
401
402 Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
403 CcExitVmgSetOffsetValid (Ghcb, GhcbSwScratch);
404 Status = CcExitVmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);
405 if (Status != 0) {
406 return Status;
407 }
408
409 if (Bytes == 4) {
410 //
411 // Zero-extend for 32-bit operation
412 //
413 Regs->Rax = 0;
414 }
415
416 CopyMem (&Regs->Rax, Ghcb->SharedBuffer, Bytes);
417 break;
418
419 //
420 // MMIO read w/ zero-extension ((MOVZX regX, reg/memX)
421 //
422 case 0xB6:
423 Bytes = 1;
424 //
425 // fall through
426 //
427 case 0xB7:
428 CcDecodeModRm (Regs, InstructionData);
429 Bytes = (Bytes != 0) ? Bytes : 2;
430
431 Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
432 if (Status != 0) {
433 return Status;
434 }
435
436 ExitInfo1 = InstructionData->Ext.RmData;
437 ExitInfo2 = Bytes;
438
439 Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
440 CcExitVmgSetOffsetValid (Ghcb, GhcbSwScratch);
441 Status = CcExitVmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);
442 if (Status != 0) {
443 return Status;
444 }
445
446 Register = CcGetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);
447 SetMem (Register, (UINTN)(1 << InstructionData->DataSize), 0);
448 CopyMem (Register, Ghcb->SharedBuffer, Bytes);
449 break;
450
451 //
452 // MMIO read w/ sign-extension (MOVSX regX, reg/memX)
453 //
454 case 0xBE:
455 Bytes = 1;
456 //
457 // fall through
458 //
459 case 0xBF:
460 CcDecodeModRm (Regs, InstructionData);
461 Bytes = (Bytes != 0) ? Bytes : 2;
462
463 Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
464 if (Status != 0) {
465 return Status;
466 }
467
468 ExitInfo1 = InstructionData->Ext.RmData;
469 ExitInfo2 = Bytes;
470
471 Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
472 CcExitVmgSetOffsetValid (Ghcb, GhcbSwScratch);
473 Status = CcExitVmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);
474 if (Status != 0) {
475 return Status;
476 }
477
478 if (Bytes == 1) {
479 UINT8 *Data;
480
481 Data = (UINT8 *)Ghcb->SharedBuffer;
482 SignByte = ((*Data & BIT7) != 0) ? 0xFF : 0x00;
483 } else {
484 UINT16 *Data;
485
486 Data = (UINT16 *)Ghcb->SharedBuffer;
487 SignByte = ((*Data & BIT15) != 0) ? 0xFF : 0x00;
488 }
489
490 Register = CcGetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);
491 SetMem (Register, (UINTN)(1 << InstructionData->DataSize), SignByte);
492 CopyMem (Register, Ghcb->SharedBuffer, Bytes);
493 break;
494
495 default:
496 DEBUG ((DEBUG_ERROR, "Invalid MMIO opcode (%x)\n", OpCode));
497 Status = GP_EXCEPTION;
498 ASSERT (FALSE);
499 }
500
501 return Status;
502}
503
518STATIC
519UINT64
521 IN OUT GHCB *Ghcb,
523 IN CC_INSTRUCTION_DATA *InstructionData
524 )
525{
526 Ghcb->SaveArea.Rax = Regs->Rax;
527 CcExitVmgSetOffsetValid (Ghcb, GhcbRax);
528 Ghcb->SaveArea.Rcx = Regs->Rcx;
529 CcExitVmgSetOffsetValid (Ghcb, GhcbRcx);
530
531 return CcExitVmgExit (Ghcb, SVM_EXIT_MWAIT, 0, 0);
532}
533
548STATIC
549UINT64
551 IN OUT GHCB *Ghcb,
553 IN CC_INSTRUCTION_DATA *InstructionData
554 )
555{
556 Ghcb->SaveArea.Rax = Regs->Rax; // Identity mapped, so VA = PA
557 CcExitVmgSetOffsetValid (Ghcb, GhcbRax);
558 Ghcb->SaveArea.Rcx = Regs->Rcx;
559 CcExitVmgSetOffsetValid (Ghcb, GhcbRcx);
560 Ghcb->SaveArea.Rdx = Regs->Rdx;
561 CcExitVmgSetOffsetValid (Ghcb, GhcbRdx);
562
563 return CcExitVmgExit (Ghcb, SVM_EXIT_MONITOR, 0, 0);
564}
565
580STATIC
581UINT64
583 IN OUT GHCB *Ghcb,
585 IN CC_INSTRUCTION_DATA *InstructionData
586 )
587{
588 return CcExitVmgExit (Ghcb, SVM_EXIT_WBINVD, 0, 0);
589}
590
605STATIC
606UINT64
608 IN OUT GHCB *Ghcb,
610 IN CC_INSTRUCTION_DATA *InstructionData
611 )
612{
613 UINT64 Status;
614
615 CcDecodeModRm (Regs, InstructionData);
616
617 Status = CcExitVmgExit (Ghcb, SVM_EXIT_RDTSCP, 0, 0);
618 if (Status != 0) {
619 return Status;
620 }
621
622 if (!CcExitVmgIsOffsetValid (Ghcb, GhcbRax) ||
623 !CcExitVmgIsOffsetValid (Ghcb, GhcbRcx) ||
624 !CcExitVmgIsOffsetValid (Ghcb, GhcbRdx))
625 {
626 return UnsupportedExit (Ghcb, Regs, InstructionData);
627 }
628
629 Regs->Rax = Ghcb->SaveArea.Rax;
630 Regs->Rcx = Ghcb->SaveArea.Rcx;
631 Regs->Rdx = Ghcb->SaveArea.Rdx;
632
633 return 0;
634}
635
650STATIC
651UINT64
653 IN OUT GHCB *Ghcb,
655 IN CC_INSTRUCTION_DATA *InstructionData
656 )
657{
658 UINT64 Status;
659
660 Ghcb->SaveArea.Rax = Regs->Rax;
661 CcExitVmgSetOffsetValid (Ghcb, GhcbRax);
662 Ghcb->SaveArea.Cpl = (UINT8)(Regs->Cs & 0x3);
663 CcExitVmgSetOffsetValid (Ghcb, GhcbCpl);
664
665 Status = CcExitVmgExit (Ghcb, SVM_EXIT_VMMCALL, 0, 0);
666 if (Status != 0) {
667 return Status;
668 }
669
670 if (!CcExitVmgIsOffsetValid (Ghcb, GhcbRax)) {
671 return UnsupportedExit (Ghcb, Regs, InstructionData);
672 }
673
674 Regs->Rax = Ghcb->SaveArea.Rax;
675
676 return 0;
677}
678
693STATIC
694UINT64
696 IN OUT GHCB *Ghcb,
698 IN CC_INSTRUCTION_DATA *InstructionData
699 )
700{
702 UINT64 ExitInfo1;
703 UINT64 Status;
704 UINT32 EcxIn;
705
706 ExitInfo1 = 0;
707
708 //
709 // The SVSM CAA MSR is a software implemented MSR and not supported
710 // by the hardware, handle it directly.
711 //
712 EcxIn = (UINT32)(UINTN)Regs->Rcx;
713 if (EcxIn == MSR_SVSM_CAA) {
714 // Writes to the SVSM CAA MSR are ignored
715 if (*(InstructionData->OpCodes + 1) == 0x30) {
716 return 0;
717 }
718
719 Msr.Uint64 = AmdSvsmSnpGetCaa ();
720 Regs->Rax = Msr.Bits.Lower32Bits;
721 Regs->Rdx = Msr.Bits.Upper32Bits;
722
723 return 0;
724 }
725
726 switch (*(InstructionData->OpCodes + 1)) {
727 case 0x30: // WRMSR
728 ExitInfo1 = 1;
729 Ghcb->SaveArea.Rax = Regs->Rax;
730 CcExitVmgSetOffsetValid (Ghcb, GhcbRax);
731 Ghcb->SaveArea.Rdx = Regs->Rdx;
732 CcExitVmgSetOffsetValid (Ghcb, GhcbRdx);
733 //
734 // fall through
735 //
736 case 0x32: // RDMSR
737 Ghcb->SaveArea.Rcx = Regs->Rcx;
738 CcExitVmgSetOffsetValid (Ghcb, GhcbRcx);
739 break;
740 default:
741 return UnsupportedExit (Ghcb, Regs, InstructionData);
742 }
743
744 Status = CcExitVmgExit (Ghcb, SVM_EXIT_MSR, ExitInfo1, 0);
745 if (Status != 0) {
746 return Status;
747 }
748
749 if (ExitInfo1 == 0) {
750 if (!CcExitVmgIsOffsetValid (Ghcb, GhcbRax) ||
751 !CcExitVmgIsOffsetValid (Ghcb, GhcbRdx))
752 {
753 return UnsupportedExit (Ghcb, Regs, InstructionData);
754 }
755
756 Regs->Rax = Ghcb->SaveArea.Rax;
757 Regs->Rdx = Ghcb->SaveArea.Rdx;
758 }
759
760 return 0;
761}
762
775STATIC
776UINT64
779 IN OUT CC_INSTRUCTION_DATA *InstructionData
780 )
781{
782 UINT64 ExitInfo;
783
784 ExitInfo = 0;
785
786 switch (*(InstructionData->OpCodes)) {
787 //
788 // INS opcodes
789 //
790 case 0x6C:
791 case 0x6D:
792 ExitInfo |= IOIO_TYPE_INS;
793 ExitInfo |= IOIO_SEG_ES;
794 ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
795 break;
796
797 //
798 // OUTS opcodes
799 //
800 case 0x6E:
801 case 0x6F:
802 ExitInfo |= IOIO_TYPE_OUTS;
803 ExitInfo |= IOIO_SEG_DS;
804 ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
805 break;
806
807 //
808 // IN immediate opcodes
809 //
810 case 0xE4:
811 case 0xE5:
812 InstructionData->ImmediateSize = 1;
813 InstructionData->End++;
814 ExitInfo |= IOIO_TYPE_IN;
815 ExitInfo |= ((*(InstructionData->OpCodes + 1)) << 16);
816 break;
817
818 //
819 // OUT immediate opcodes
820 //
821 case 0xE6:
822 case 0xE7:
823 InstructionData->ImmediateSize = 1;
824 InstructionData->End++;
825 ExitInfo |= IOIO_TYPE_OUT;
826 ExitInfo |= ((*(InstructionData->OpCodes + 1)) << 16) | IOIO_TYPE_OUT;
827 break;
828
829 //
830 // IN register opcodes
831 //
832 case 0xEC:
833 case 0xED:
834 ExitInfo |= IOIO_TYPE_IN;
835 ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
836 break;
837
838 //
839 // OUT register opcodes
840 //
841 case 0xEE:
842 case 0xEF:
843 ExitInfo |= IOIO_TYPE_OUT;
844 ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
845 break;
846
847 default:
848 return 0;
849 }
850
851 switch (*(InstructionData->OpCodes)) {
852 //
853 // Single-byte opcodes
854 //
855 case 0x6C:
856 case 0x6E:
857 case 0xE4:
858 case 0xE6:
859 case 0xEC:
860 case 0xEE:
861 ExitInfo |= IOIO_DATA_8;
862 break;
863
864 //
865 // Length determined by instruction parsing
866 //
867 default:
868 ExitInfo |= (InstructionData->DataSize == Size16Bits) ? IOIO_DATA_16
869 : IOIO_DATA_32;
870 }
871
872 switch (InstructionData->AddrSize) {
873 case Size16Bits:
874 ExitInfo |= IOIO_ADDR_16;
875 break;
876
877 case Size32Bits:
878 ExitInfo |= IOIO_ADDR_32;
879 break;
880
881 case Size64Bits:
882 ExitInfo |= IOIO_ADDR_64;
883 break;
884
885 default:
886 break;
887 }
888
889 if (InstructionData->RepMode != 0) {
890 ExitInfo |= IOIO_REP;
891 }
892
893 return ExitInfo;
894}
895
910STATIC
911UINT64
913 IN OUT GHCB *Ghcb,
915 IN CC_INSTRUCTION_DATA *InstructionData
916 )
917{
918 UINT64 ExitInfo1, ExitInfo2, Status;
919 BOOLEAN IsString;
920
921 ExitInfo1 = IoioExitInfo (Regs, InstructionData);
922 if (ExitInfo1 == 0) {
923 return UnsupportedExit (Ghcb, Regs, InstructionData);
924 }
925
926 IsString = ((ExitInfo1 & IOIO_TYPE_STR) != 0) ? TRUE : FALSE;
927 if (IsString) {
928 UINTN IoBytes, VmgExitBytes;
929 UINTN GhcbCount, OpCount;
930
931 Status = 0;
932
933 IoBytes = IOIO_DATA_BYTES (ExitInfo1);
934 GhcbCount = sizeof (Ghcb->SharedBuffer) / IoBytes;
935
936 OpCount = ((ExitInfo1 & IOIO_REP) != 0) ? Regs->Rcx : 1;
937 while (OpCount != 0) {
938 ExitInfo2 = MIN (OpCount, GhcbCount);
939 VmgExitBytes = ExitInfo2 * IoBytes;
940
941 if ((ExitInfo1 & IOIO_TYPE_IN) == 0) {
942 CopyMem (Ghcb->SharedBuffer, (VOID *)Regs->Rsi, VmgExitBytes);
943 Regs->Rsi += VmgExitBytes;
944 }
945
946 Ghcb->SaveArea.SwScratch = (UINT64)Ghcb->SharedBuffer;
947 CcExitVmgSetOffsetValid (Ghcb, GhcbSwScratch);
948 Status = CcExitVmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, ExitInfo2);
949 if (Status != 0) {
950 return Status;
951 }
952
953 if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {
954 CopyMem ((VOID *)Regs->Rdi, Ghcb->SharedBuffer, VmgExitBytes);
955 Regs->Rdi += VmgExitBytes;
956 }
957
958 if ((ExitInfo1 & IOIO_REP) != 0) {
959 Regs->Rcx -= ExitInfo2;
960 }
961
962 OpCount -= ExitInfo2;
963 }
964 } else {
965 if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {
966 Ghcb->SaveArea.Rax = 0;
967 } else {
968 CopyMem (&Ghcb->SaveArea.Rax, &Regs->Rax, IOIO_DATA_BYTES (ExitInfo1));
969 }
970
971 CcExitVmgSetOffsetValid (Ghcb, GhcbRax);
972
973 Status = CcExitVmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, 0);
974 if (Status != 0) {
975 return Status;
976 }
977
978 if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {
979 if (!CcExitVmgIsOffsetValid (Ghcb, GhcbRax)) {
980 return UnsupportedExit (Ghcb, Regs, InstructionData);
981 }
982
983 CopyMem (&Regs->Rax, &Ghcb->SaveArea.Rax, IOIO_DATA_BYTES (ExitInfo1));
984 }
985 }
986
987 return 0;
988}
989
1004STATIC
1005UINT64
1007 IN OUT GHCB *Ghcb,
1009 IN CC_INSTRUCTION_DATA *InstructionData
1010 )
1011{
1012 return CcExitVmgExit (Ghcb, SVM_EXIT_INVD, 0, 0);
1013}
1014
1040STATIC
1041BOOLEAN
1043 IN OUT GHCB *Ghcb,
1044 IN UINT32 EaxIn,
1045 IN UINT32 EcxIn,
1046 IN UINT64 XCr0,
1047 IN OUT UINT32 *Eax,
1048 IN OUT UINT32 *Ebx,
1049 IN OUT UINT32 *Ecx,
1050 IN OUT UINT32 *Edx,
1051 IN OUT UINT64 *Status,
1052 IN OUT BOOLEAN *UnsupportedExit
1053 )
1054{
1056 Ghcb->SaveArea.Rax = EaxIn;
1057 CcExitVmgSetOffsetValid (Ghcb, GhcbRax);
1058 Ghcb->SaveArea.Rcx = EcxIn;
1059 CcExitVmgSetOffsetValid (Ghcb, GhcbRcx);
1060 if (EaxIn == CPUID_EXTENDED_STATE) {
1061 Ghcb->SaveArea.XCr0 = XCr0;
1062 CcExitVmgSetOffsetValid (Ghcb, GhcbXCr0);
1063 }
1064
1065 *Status = CcExitVmgExit (Ghcb, SVM_EXIT_CPUID, 0, 0);
1066 if (*Status != 0) {
1067 return FALSE;
1068 }
1069
1070 if (!CcExitVmgIsOffsetValid (Ghcb, GhcbRax) ||
1071 !CcExitVmgIsOffsetValid (Ghcb, GhcbRbx) ||
1072 !CcExitVmgIsOffsetValid (Ghcb, GhcbRcx) ||
1073 !CcExitVmgIsOffsetValid (Ghcb, GhcbRdx))
1074 {
1076 return FALSE;
1077 }
1078
1079 if (Eax) {
1080 *Eax = (UINT32)(UINTN)Ghcb->SaveArea.Rax;
1081 }
1082
1083 if (Ebx) {
1084 *Ebx = (UINT32)(UINTN)Ghcb->SaveArea.Rbx;
1085 }
1086
1087 if (Ecx) {
1088 *Ecx = (UINT32)(UINTN)Ghcb->SaveArea.Rcx;
1089 }
1090
1091 if (Edx) {
1092 *Edx = (UINT32)(UINTN)Ghcb->SaveArea.Rdx;
1093 }
1094
1095 return TRUE;
1096}
1097
1105STATIC
1106BOOLEAN
1108 VOID
1109 )
1110{
1112
1113 Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS);
1114
1115 return !!Msr.Bits.SevSnpBit;
1116}
1117
1133STATIC
1134BOOLEAN
1136 IN UINT64 XFeaturesEnabled,
1137 IN OUT UINT32 *XSaveSize,
1138 IN BOOLEAN Compacted
1139 )
1140{
1141 SEV_SNP_CPUID_INFO *CpuidInfo;
1142 UINT64 XFeaturesFound = 0;
1143 UINT32 Idx;
1144
1145 //
1146 // The base/legacy XSave size is documented to be 0x240 in the APM.
1147 //
1148 *XSaveSize = 0x240;
1149 CpuidInfo = (SEV_SNP_CPUID_INFO *)(UINT64)PcdGet32 (PcdOvmfCpuidBase);
1150
1151 for (Idx = 0; Idx < CpuidInfo->Count; Idx++) {
1152 SEV_SNP_CPUID_FUNCTION *CpuidFn = &CpuidInfo->function[Idx];
1153
1154 if (!((CpuidFn->EaxIn == 0xD) && (CpuidFn->EcxIn > 1))) {
1155 continue;
1156 }
1157
1158 if (XFeaturesFound & (1ULL << CpuidFn->EcxIn) ||
1159 !(XFeaturesEnabled & (1ULL << CpuidFn->EcxIn)))
1160 {
1161 continue;
1162 }
1163
1164 XFeaturesFound |= (1ULL << CpuidFn->EcxIn);
1165 if (Compacted) {
1166 *XSaveSize += CpuidFn->Eax;
1167 } else {
1168 *XSaveSize = MAX (*XSaveSize, CpuidFn->Eax + CpuidFn->Ebx);
1169 }
1170 }
1171
1172 /*
1173 * Either the guest set unsupported XCR0/XSS bits, or the corresponding
1174 * entries in the CPUID table were not present. This is an invalid state.
1175 */
1176 if (XFeaturesFound != (XFeaturesEnabled & ~3UL)) {
1177 return FALSE;
1178 }
1179
1180 return TRUE;
1181}
1182
1192STATIC
1193BOOLEAN
1195 IN UINT32 EaxIn
1196 )
1197{
1198 switch (EaxIn) {
1199 case CPUID_CACHE_PARAMS:
1205 case CPUID_INTEL_SGX:
1209 case 0x8000001D: /* Cache Topology Information */
1210 return TRUE;
1211 }
1212
1213 return FALSE;
1214}
1215
1241STATIC
1242BOOLEAN
1244 IN OUT GHCB *Ghcb,
1245 IN UINT32 EaxIn,
1246 IN UINT32 EcxIn,
1247 IN UINT64 XCr0,
1248 IN OUT UINT32 *Eax,
1249 IN OUT UINT32 *Ebx,
1250 IN OUT UINT32 *Ecx,
1251 IN OUT UINT32 *Edx,
1252 IN OUT UINT64 *Status,
1253 IN OUT BOOLEAN *Unsupported
1254 )
1255{
1256 SEV_SNP_CPUID_INFO *CpuidInfo;
1257 BOOLEAN Found;
1258 UINT32 Idx;
1259
1260 CpuidInfo = (SEV_SNP_CPUID_INFO *)(UINT64)PcdGet32 (PcdOvmfCpuidBase);
1261 Found = FALSE;
1262
1263 for (Idx = 0; Idx < CpuidInfo->Count; Idx++) {
1264 SEV_SNP_CPUID_FUNCTION *CpuidFn = &CpuidInfo->function[Idx];
1265
1266 if (CpuidFn->EaxIn != EaxIn) {
1267 continue;
1268 }
1269
1270 if (IsFunctionIndexed (CpuidFn->EaxIn) && (CpuidFn->EcxIn != EcxIn)) {
1271 continue;
1272 }
1273
1274 *Eax = CpuidFn->Eax;
1275 *Ebx = CpuidFn->Ebx;
1276 *Ecx = CpuidFn->Ecx;
1277 *Edx = CpuidFn->Edx;
1278
1279 Found = TRUE;
1280 break;
1281 }
1282
1283 if (!Found) {
1284 *Eax = *Ebx = *Ecx = *Edx = 0;
1285 goto Out;
1286 }
1287
1288 if (EaxIn == CPUID_VERSION_INFO) {
1289 IA32_CR4 Cr4;
1290 UINT32 Ebx2;
1291 UINT32 Edx2;
1292
1293 if (!GetCpuidHyp (
1294 Ghcb,
1295 EaxIn,
1296 EcxIn,
1297 XCr0,
1298 NULL,
1299 &Ebx2,
1300 NULL,
1301 &Edx2,
1302 Status,
1303 Unsupported
1304 ))
1305 {
1306 return FALSE;
1307 }
1308
1309 /* initial APIC ID */
1310 *Ebx = (*Ebx & 0x00FFFFFF) | (Ebx2 & 0xFF000000);
1311 /* APIC enabled bit */
1312 *Edx = (*Edx & ~BIT9) | (Edx2 & BIT9);
1313 /* OSXSAVE enabled bit */
1314 Cr4.UintN = AsmReadCr4 ();
1315 *Ecx = (Cr4.Bits.OSXSAVE) ? (*Ecx & ~BIT27) | (*Ecx & BIT27)
1316 : (*Ecx & ~BIT27);
1317 } else if (EaxIn == CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS) {
1318 IA32_CR4 Cr4;
1319
1320 Cr4.UintN = AsmReadCr4 ();
1321 /* OSPKE enabled bit */
1322 *Ecx = (Cr4.Bits.PKE) ? (*Ecx | BIT4) : (*Ecx & ~BIT4);
1323 } else if (EaxIn == CPUID_EXTENDED_TOPOLOGY) {
1324 if (!GetCpuidHyp (
1325 Ghcb,
1326 EaxIn,
1327 EcxIn,
1328 XCr0,
1329 NULL,
1330 NULL,
1331 NULL,
1332 Edx,
1333 Status,
1334 Unsupported
1335 ))
1336 {
1337 return FALSE;
1338 }
1339 } else if ((EaxIn == CPUID_EXTENDED_STATE) && ((EcxIn == 0) || (EcxIn == 1))) {
1340 MSR_IA32_XSS_REGISTER XssMsr;
1341 BOOLEAN Compacted;
1342 UINT32 XSaveSize;
1343
1344 XssMsr.Uint64 = 0;
1345 Compacted = FALSE;
1346 if (EcxIn == 1) {
1347 /*
1348 * The PPR and APM aren't clear on what size should be encoded in
1349 * 0xD:0x1:EBX when compaction is not enabled by either XSAVEC or
1350 * XSAVES, as these are generally fixed to 1 on real CPUs. Report
1351 * this undefined case as an error.
1352 */
1353 if (!(*Eax & (BIT3 | BIT1))) {
1354 /* (XSAVES | XSAVEC) */
1355 return FALSE;
1356 }
1357
1358 Compacted = TRUE;
1359 XssMsr.Uint64 = AsmReadMsr64 (MSR_IA32_XSS);
1360 }
1361
1362 if (!GetCpuidXSaveSize (
1363 XCr0 | XssMsr.Uint64,
1364 &XSaveSize,
1365 Compacted
1366 ))
1367 {
1368 return FALSE;
1369 }
1370
1371 *Ebx = XSaveSize;
1372 } else if (EaxIn == 0x8000001E) {
1373 UINT32 Ebx2;
1374 UINT32 Ecx2;
1375
1376 /* extended APIC ID */
1377 if (!GetCpuidHyp (
1378 Ghcb,
1379 EaxIn,
1380 EcxIn,
1381 XCr0,
1382 Eax,
1383 &Ebx2,
1384 &Ecx2,
1385 NULL,
1386 Status,
1387 Unsupported
1388 ))
1389 {
1390 return FALSE;
1391 }
1392
1393 /* compute ID */
1394 *Ebx = (*Ebx & 0xFFFFFF00) | (Ebx2 & 0x000000FF);
1395 /* node ID */
1396 *Ecx = (*Ecx & 0xFFFFFF00) | (Ecx2 & 0x000000FF);
1397 } else if (EaxIn == 0x8000001F) {
1398 /* Set the SVSM feature bit if running under an SVSM */
1399 if (AmdSvsmIsSvsmPresent ()) {
1400 *Eax |= BIT28;
1401 }
1402 }
1403
1404Out:
1405 *Status = 0;
1406 *Unsupported = FALSE;
1407 return TRUE;
1408}
1409
1424STATIC
1425UINT64
1427 IN OUT GHCB *Ghcb,
1429 IN CC_INSTRUCTION_DATA *InstructionData
1430 )
1431{
1432 BOOLEAN Unsupported;
1433 UINT64 Status;
1434 UINT32 EaxIn;
1435 UINT32 EcxIn;
1436 UINT64 XCr0;
1437 UINT32 Eax;
1438 UINT32 Ebx;
1439 UINT32 Ecx;
1440 UINT32 Edx;
1441
1442 EaxIn = (UINT32)(UINTN)Regs->Rax;
1443 EcxIn = (UINT32)(UINTN)Regs->Rcx;
1444
1445 if (EaxIn == CPUID_EXTENDED_STATE) {
1446 IA32_CR4 Cr4;
1447
1448 Cr4.UintN = AsmReadCr4 ();
1449 Ghcb->SaveArea.XCr0 = (Cr4.Bits.OSXSAVE == 1) ? AsmXGetBv (0) : 1;
1450 XCr0 = (Cr4.Bits.OSXSAVE == 1) ? AsmXGetBv (0) : 1;
1451 }
1452
1453 if (SnpEnabled ()) {
1454 if (!GetCpuidFw (
1455 Ghcb,
1456 EaxIn,
1457 EcxIn,
1458 XCr0,
1459 &Eax,
1460 &Ebx,
1461 &Ecx,
1462 &Edx,
1463 &Status,
1464 &Unsupported
1465 ))
1466 {
1467 goto CpuidFail;
1468 }
1469 } else {
1470 if (!GetCpuidHyp (
1471 Ghcb,
1472 EaxIn,
1473 EcxIn,
1474 XCr0,
1475 &Eax,
1476 &Ebx,
1477 &Ecx,
1478 &Edx,
1479 &Status,
1480 &Unsupported
1481 ))
1482 {
1483 goto CpuidFail;
1484 }
1485 }
1486
1487 Regs->Rax = Eax;
1488 Regs->Rbx = Ebx;
1489 Regs->Rcx = Ecx;
1490 Regs->Rdx = Edx;
1491
1492 return 0;
1493
1494CpuidFail:
1495 if (Unsupported) {
1496 return UnsupportedExit (Ghcb, Regs, InstructionData);
1497 }
1498
1499 return Status;
1500}
1501
1516STATIC
1517UINT64
1519 IN OUT GHCB *Ghcb,
1521 IN CC_INSTRUCTION_DATA *InstructionData
1522 )
1523{
1524 UINT64 Status;
1525
1526 Ghcb->SaveArea.Rcx = Regs->Rcx;
1527 CcExitVmgSetOffsetValid (Ghcb, GhcbRcx);
1528
1529 Status = CcExitVmgExit (Ghcb, SVM_EXIT_RDPMC, 0, 0);
1530 if (Status != 0) {
1531 return Status;
1532 }
1533
1534 if (!CcExitVmgIsOffsetValid (Ghcb, GhcbRax) ||
1535 !CcExitVmgIsOffsetValid (Ghcb, GhcbRdx))
1536 {
1537 return UnsupportedExit (Ghcb, Regs, InstructionData);
1538 }
1539
1540 Regs->Rax = Ghcb->SaveArea.Rax;
1541 Regs->Rdx = Ghcb->SaveArea.Rdx;
1542
1543 return 0;
1544}
1545
1560STATIC
1561UINT64
1563 IN OUT GHCB *Ghcb,
1565 IN CC_INSTRUCTION_DATA *InstructionData
1566 )
1567{
1568 UINT64 Status;
1569
1570 Status = CcExitVmgExit (Ghcb, SVM_EXIT_RDTSC, 0, 0);
1571 if (Status != 0) {
1572 return Status;
1573 }
1574
1575 if (!CcExitVmgIsOffsetValid (Ghcb, GhcbRax) ||
1576 !CcExitVmgIsOffsetValid (Ghcb, GhcbRdx))
1577 {
1578 return UnsupportedExit (Ghcb, Regs, InstructionData);
1579 }
1580
1581 Regs->Rax = Ghcb->SaveArea.Rax;
1582 Regs->Rdx = Ghcb->SaveArea.Rdx;
1583
1584 return 0;
1585}
1586
1601STATIC
1602UINT64
1604 IN OUT GHCB *Ghcb,
1606 IN CC_INSTRUCTION_DATA *InstructionData
1607 )
1608{
1610 SEV_ES_PER_CPU_DATA *SevEsData;
1611 UINT64 *Register;
1612 UINT64 Status;
1613
1615 return UnsupportedExit (Ghcb, Regs, InstructionData);
1616 }
1617
1618 Ext = &InstructionData->Ext;
1619 SevEsData = (SEV_ES_PER_CPU_DATA *)(Ghcb + 1);
1620
1621 //
1622 // MOV DRn always treats MOD == 3 no matter how encoded
1623 //
1624 Register = CcGetRegisterPointer (Regs, Ext->ModRm.Rm);
1625
1626 //
1627 // Using a value of 0 for ExitInfo1 means RAX holds the value
1628 //
1629 Ghcb->SaveArea.Rax = *Register;
1630 CcExitVmgSetOffsetValid (Ghcb, GhcbRax);
1631
1632 Status = CcExitVmgExit (Ghcb, SVM_EXIT_DR7_WRITE, 0, 0);
1633 if (Status != 0) {
1634 return Status;
1635 }
1636
1637 SevEsData->Dr7 = *Register;
1638 SevEsData->Dr7Cached = 1;
1639
1640 return 0;
1641}
1642
1656STATIC
1657UINT64
1659 IN OUT GHCB *Ghcb,
1661 IN CC_INSTRUCTION_DATA *InstructionData
1662 )
1663{
1665 SEV_ES_PER_CPU_DATA *SevEsData;
1666 UINT64 *Register;
1667
1669 return UnsupportedExit (Ghcb, Regs, InstructionData);
1670 }
1671
1672 Ext = &InstructionData->Ext;
1673 SevEsData = (SEV_ES_PER_CPU_DATA *)(Ghcb + 1);
1674
1675 //
1676 // MOV DRn always treats MOD == 3 no matter how encoded
1677 //
1678 Register = CcGetRegisterPointer (Regs, Ext->ModRm.Rm);
1679
1680 //
1681 // If there is a cached valued for DR7, return that. Otherwise return the
1682 // DR7 standard reset value of 0x400 (no debug breakpoints set).
1683 //
1684 *Register = (SevEsData->Dr7Cached == 1) ? SevEsData->Dr7 : 0x400;
1685
1686 return 0;
1687}
1688
1710STATIC
1711UINT64
1713 IN OUT GHCB *Ghcb,
1715 IN OUT CC_INSTRUCTION_DATA *InstructionData,
1716 IN UINT64 ExitCode
1717 )
1718{
1719 UINT8 OpCode;
1720
1721 //
1722 // Expected opcodes are either 1 or 2 bytes. If they are 2 bytes, they always
1723 // start with TWO_BYTE_OPCODE_ESCAPE (0x0f), so skip over that.
1724 //
1725 OpCode = *(InstructionData->OpCodes);
1726 if (OpCode == TWO_BYTE_OPCODE_ESCAPE) {
1727 OpCode = *(InstructionData->OpCodes + 1);
1728 }
1729
1730 switch (ExitCode) {
1731 case SVM_EXIT_IOIO_PROT:
1732 case SVM_EXIT_NPF:
1733 /* handled separately */
1734 return 0;
1735
1736 case SVM_EXIT_CPUID:
1737 if (OpCode == 0xa2) {
1738 return 0;
1739 }
1740
1741 break;
1742
1743 case SVM_EXIT_INVD:
1744 if (OpCode == 0x08) {
1745 return 0;
1746 }
1747
1748 break;
1749
1750 case SVM_EXIT_MONITOR:
1751 CcDecodeModRm (Regs, InstructionData);
1752
1753 if ((OpCode == 0x01) &&
1754 ( (InstructionData->ModRm.Uint8 == 0xc8) /* MONITOR */
1755 || (InstructionData->ModRm.Uint8 == 0xfa))) /* MONITORX */
1756 {
1757 return 0;
1758 }
1759
1760 break;
1761
1762 case SVM_EXIT_MWAIT:
1763 CcDecodeModRm (Regs, InstructionData);
1764
1765 if ((OpCode == 0x01) &&
1766 ( (InstructionData->ModRm.Uint8 == 0xc9) /* MWAIT */
1767 || (InstructionData->ModRm.Uint8 == 0xfb))) /* MWAITX */
1768 {
1769 return 0;
1770 }
1771
1772 break;
1773
1774 case SVM_EXIT_MSR:
1775 /* RDMSR */
1776 if ((OpCode == 0x32) ||
1777 /* WRMSR */
1778 (OpCode == 0x30))
1779 {
1780 return 0;
1781 }
1782
1783 break;
1784
1785 case SVM_EXIT_RDPMC:
1786 if (OpCode == 0x33) {
1787 return 0;
1788 }
1789
1790 break;
1791
1792 case SVM_EXIT_RDTSC:
1793 if (OpCode == 0x31) {
1794 return 0;
1795 }
1796
1797 break;
1798
1799 case SVM_EXIT_RDTSCP:
1800 CcDecodeModRm (Regs, InstructionData);
1801
1802 if ((OpCode == 0x01) && (InstructionData->ModRm.Uint8 == 0xf9)) {
1803 return 0;
1804 }
1805
1806 break;
1807
1808 case SVM_EXIT_DR7_READ:
1809 CcDecodeModRm (Regs, InstructionData);
1810
1811 if ((OpCode == 0x21) &&
1812 (InstructionData->Ext.ModRm.Reg == 7))
1813 {
1814 return 0;
1815 }
1816
1817 break;
1818
1819 case SVM_EXIT_VMMCALL:
1820 CcDecodeModRm (Regs, InstructionData);
1821
1822 if ((OpCode == 0x01) && (InstructionData->ModRm.Uint8 == 0xd9)) {
1823 return 0;
1824 }
1825
1826 break;
1827
1828 case SVM_EXIT_DR7_WRITE:
1829 CcDecodeModRm (Regs, InstructionData);
1830
1831 if ((OpCode == 0x23) &&
1832 (InstructionData->Ext.ModRm.Reg == 7))
1833 {
1834 return 0;
1835 }
1836
1837 break;
1838
1839 case SVM_EXIT_WBINVD:
1840 if (OpCode == 0x9) {
1841 return 0;
1842 }
1843
1844 break;
1845
1846 default:
1847 break;
1848 }
1849
1850 return UnsupportedExit (Ghcb, Regs, InstructionData);
1851}
1852
1871EFIAPI
1873 IN OUT GHCB *Ghcb,
1874 IN OUT EFI_EXCEPTION_TYPE *ExceptionType,
1875 IN OUT EFI_SYSTEM_CONTEXT SystemContext
1876 )
1877{
1879 NAE_EXIT NaeExit;
1880 CC_INSTRUCTION_DATA InstructionData;
1881 UINT64 ExitCode, Status;
1882 EFI_STATUS VcRet;
1883 BOOLEAN InterruptState;
1884
1885 VcRet = EFI_SUCCESS;
1886
1887 Regs = SystemContext.SystemContextX64;
1888
1889 CcExitVmgInit (Ghcb, &InterruptState);
1890
1891 ExitCode = Regs->ExceptionData;
1892 switch (ExitCode) {
1893 case SVM_EXIT_DR7_READ:
1894 NaeExit = Dr7ReadExit;
1895 break;
1896
1897 case SVM_EXIT_DR7_WRITE:
1898 NaeExit = Dr7WriteExit;
1899 break;
1900
1901 case SVM_EXIT_RDTSC:
1902 NaeExit = RdtscExit;
1903 break;
1904
1905 case SVM_EXIT_RDPMC:
1906 NaeExit = RdpmcExit;
1907 break;
1908
1909 case SVM_EXIT_CPUID:
1910 NaeExit = CpuidExit;
1911 break;
1912
1913 case SVM_EXIT_INVD:
1914 NaeExit = InvdExit;
1915 break;
1916
1917 case SVM_EXIT_IOIO_PROT:
1918 NaeExit = IoioExit;
1919 break;
1920
1921 case SVM_EXIT_MSR:
1922 NaeExit = MsrExit;
1923 break;
1924
1925 case SVM_EXIT_VMMCALL:
1926 NaeExit = VmmCallExit;
1927 break;
1928
1929 case SVM_EXIT_RDTSCP:
1930 NaeExit = RdtscpExit;
1931 break;
1932
1933 case SVM_EXIT_WBINVD:
1934 NaeExit = WbinvdExit;
1935 break;
1936
1937 case SVM_EXIT_MONITOR:
1938 NaeExit = MonitorExit;
1939 break;
1940
1941 case SVM_EXIT_MWAIT:
1942 NaeExit = MwaitExit;
1943 break;
1944
1945 case SVM_EXIT_NPF:
1946 NaeExit = MmioExit;
1947 break;
1948
1949 default:
1950 NaeExit = UnsupportedExit;
1951 }
1952
1953 CcInitInstructionData (&InstructionData, Ghcb, Regs);
1954
1955 Status = VcCheckOpcodeBytes (Ghcb, Regs, &InstructionData, ExitCode);
1956
1957 //
1958 // If the opcode does not match the exit code, do not process the exception
1959 //
1960 if (Status == 0) {
1961 Status = NaeExit (Ghcb, Regs, &InstructionData);
1962 }
1963
1964 if (Status == 0) {
1965 Regs->Rip += CcInstructionLength (&InstructionData);
1966 } else {
1968
1969 Event.Uint64 = Status;
1970 if (Event.Elements.ErrorCodeValid != 0) {
1971 Regs->ExceptionData = Event.Elements.ErrorCode;
1972 } else {
1973 Regs->ExceptionData = 0;
1974 }
1975
1976 *ExceptionType = Event.Elements.Vector;
1977
1978 VcRet = EFI_PROTOCOL_ERROR;
1979 }
1980
1981 CcExitVmgDone (Ghcb, InterruptState);
1982
1983 return VcRet;
1984}
1985
1992VOID
1993EFIAPI
1995 IN OUT SEV_ES_PER_CPU_DATA *SevEsData
1996 )
1997{
1998 //
1999 // Progress will be halted, so set VcCount to allow for ASSERT output
2000 // to be seen.
2001 //
2002 SevEsData->VcCount = 0;
2003
2004 ASSERT (FALSE);
2005 CpuDeadLoop ();
2006}
UINT64 UINTN
BOOLEAN EFIAPI AmdSvsmIsSvsmPresent(VOID)
Definition: AmdSvsmLib.c:130
UINT64 EFIAPI AmdSvsmSnpGetCaa(VOID)
Definition: AmdSvsmLib.c:174
VOID EFIAPI CpuDeadLoop(VOID)
Definition: CpuDeadLoop.c:25
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
Definition: SetMemWrapper.c:38
UINT64 EFIAPI CcExitVmgExit(IN OUT GHCB *Ghcb, IN UINT64 ExitCode, IN UINT64 ExitInfo1, IN UINT64 ExitInfo2)
Definition: CcExitLib.c:106
BOOLEAN EFIAPI CcExitVmgIsOffsetValid(IN GHCB *Ghcb, IN GHCB_REGISTER Offset)
Definition: CcExitLib.c:227
VOID EFIAPI CcExitVmgSetOffsetValid(IN OUT GHCB *Ghcb, IN GHCB_REGISTER Offset)
Definition: CcExitLib.c:198
VOID EFIAPI CcExitVmgInit(IN OUT GHCB *Ghcb, IN OUT BOOLEAN *InterruptState)
Definition: CcExitLib.c:146
VOID EFIAPI CcExitVmgDone(IN OUT GHCB *Ghcb, IN BOOLEAN InterruptState)
Definition: CcExitLib.c:176
STATIC UINT64 ValidateMmioMemory(IN GHCB *Ghcb, IN UINTN MemoryAddress, IN UINTN MemoryLength)
STATIC UINT64 MmioExit(IN OUT GHCB *Ghcb, IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN OUT CC_INSTRUCTION_DATA *InstructionData)
STATIC BOOLEAN SnpEnabled(VOID)
STATIC UINT64 VmmCallExit(IN OUT GHCB *Ghcb, IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN CC_INSTRUCTION_DATA *InstructionData)
STATIC BOOLEAN GetCpuidXSaveSize(IN UINT64 XFeaturesEnabled, IN OUT UINT32 *XSaveSize, IN BOOLEAN Compacted)
STATIC UINT64 Dr7ReadExit(IN OUT GHCB *Ghcb, IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN CC_INSTRUCTION_DATA *InstructionData)
STATIC UINT64 InvdExit(IN OUT GHCB *Ghcb, IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN CC_INSTRUCTION_DATA *InstructionData)
STATIC UINT64 Dr7WriteExit(IN OUT GHCB *Ghcb, IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN CC_INSTRUCTION_DATA *InstructionData)
STATIC BOOLEAN GetCpuidHyp(IN OUT GHCB *Ghcb, IN UINT32 EaxIn, IN UINT32 EcxIn, IN UINT64 XCr0, IN OUT UINT32 *Eax, IN OUT UINT32 *Ebx, IN OUT UINT32 *Ecx, IN OUT UINT32 *Edx, IN OUT UINT64 *Status, IN OUT BOOLEAN *UnsupportedExit)
STATIC UINT64 IoioExitInfo(IN EFI_SYSTEM_CONTEXT_X64 *Regs, IN OUT CC_INSTRUCTION_DATA *InstructionData)
EFI_STATUS EFIAPI InternalVmgExitHandleVc(IN OUT GHCB *Ghcb, IN OUT EFI_EXCEPTION_TYPE *ExceptionType, IN OUT EFI_SYSTEM_CONTEXT SystemContext)
STATIC UINT64 VcCheckOpcodeBytes(IN OUT GHCB *Ghcb, IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN OUT CC_INSTRUCTION_DATA *InstructionData, IN UINT64 ExitCode)
STATIC UINT64 IoioExit(IN OUT GHCB *Ghcb, IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN CC_INSTRUCTION_DATA *InstructionData)
STATIC UINT64 RdtscExit(IN OUT GHCB *Ghcb, IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN CC_INSTRUCTION_DATA *InstructionData)
STATIC UINT64 MwaitExit(IN OUT GHCB *Ghcb, IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN CC_INSTRUCTION_DATA *InstructionData)
STATIC UINT64 RdtscpExit(IN OUT GHCB *Ghcb, IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN CC_INSTRUCTION_DATA *InstructionData)
VOID EFIAPI VmgExitIssueAssert(IN OUT SEV_ES_PER_CPU_DATA *SevEsData)
STATIC UINT64 WbinvdExit(IN OUT GHCB *Ghcb, IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN CC_INSTRUCTION_DATA *InstructionData)
STATIC UINT64 MonitorExit(IN OUT GHCB *Ghcb, IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN CC_INSTRUCTION_DATA *InstructionData)
STATIC UINT64 UnsupportedExit(IN GHCB *Ghcb, IN EFI_SYSTEM_CONTEXT_X64 *Regs, IN CC_INSTRUCTION_DATA *InstructionData)
STATIC BOOLEAN IsFunctionIndexed(IN UINT32 EaxIn)
STATIC BOOLEAN GetCpuidFw(IN OUT GHCB *Ghcb, IN UINT32 EaxIn, IN UINT32 EcxIn, IN UINT64 XCr0, IN OUT UINT32 *Eax, IN OUT UINT32 *Ebx, IN OUT UINT32 *Ecx, IN OUT UINT32 *Edx, IN OUT UINT64 *Status, IN OUT BOOLEAN *Unsupported)
STATIC UINT64 RdpmcExit(IN OUT GHCB *Ghcb, IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN CC_INSTRUCTION_DATA *InstructionData)
STATIC UINT64 CpuidExit(IN OUT GHCB *Ghcb, IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN CC_INSTRUCTION_DATA *InstructionData)
STATIC UINT64 MsrExit(IN OUT GHCB *Ghcb, IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, IN CC_INSTRUCTION_DATA *InstructionData)
UINT64 * CcGetRegisterPointer(IN EFI_SYSTEM_CONTEXT_X64 *Regs, IN UINT8 Register)
Definition: CcInstruction.c:31
VOID CcDecodeModRm(IN EFI_SYSTEM_CONTEXT_X64 *Regs, IN OUT CC_INSTRUCTION_DATA *InstructionData)
EFI_STATUS CcInitInstructionData(IN OUT CC_INSTRUCTION_DATA *InstructionData, IN GHCB *Ghcb, IN EFI_SYSTEM_CONTEXT_X64 *Regs)
UINT64 CcInstructionLength(IN CC_INSTRUCTION_DATA *InstructionData)
UINT64 EFIAPI AsmReadMsr64(IN UINT32 Index)
Definition: GccInlinePriv.c:60
UINTN EFIAPI AsmReadCr4(VOID)
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#define MIN(a, b)
Definition: Base.h:1007
#define VOID
Definition: Base.h:269
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define MAX(a, b)
Definition: Base.h:992
#define DEBUG(Expression)
Definition: DebugLib.h:435
INTN EFI_EXCEPTION_TYPE
Definition: DebugSupport.h:35
#define MSR_IA32_XSS
#define CPUID_INTEL_PROCESSOR_TRACE
Definition: Cpuid.h:2924
#define CPUID_DETERMINISTIC_ADDRESS_TRANSLATION_PARAMETERS
Definition: Cpuid.h:3462
#define CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS
Definition: Cpuid.h:1301
#define CPUID_CACHE_PARAMS
Definition: Cpuid.h:802
#define CPUID_INTEL_RDT_MONITORING
Definition: Cpuid.h:2187
#define CPUID_VERSION_INFO
Definition: Cpuid.h:81
#define CPUID_EXTENDED_STATE
Definition: Cpuid.h:1918
#define CPUID_INTEL_SGX
Definition: Cpuid.h:2648
#define CPUID_EXTENDED_TOPOLOGY
Definition: Cpuid.h:1815
#define CPUID_V2_EXTENDED_TOPOLOGY
Definition: Cpuid.h:3685
#define CPUID_INTEL_RDT_ALLOCATION
Definition: Cpuid.h:2303
BOOLEAN EFIAPI MemEncryptSevEsDebugVirtualizationIsEnabled(VOID)
MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE EFIAPI MemEncryptSevGetAddressRangeState(IN PHYSICAL_ADDRESS Cr3BaseAddress, IN PHYSICAL_ADDRESS BaseAddress, IN UINTN Length)
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
EFI_STATUS EFIAPI Register(IN EFI_PEI_RSC_HANDLER_CALLBACK Callback)
#define MSR_SEV_STATUS
Definition: SevSnpMsr.h:116
#define MSR_SVSM_CAA
Definition: SvsmMsr.h:21
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
UINT32 EFIAPI AsmReadMsr32(IN UINT32 Index)
Definition: X86Msr.c:27