#include <Base.h>\r
#include <Uefi.h>\r
#include <Library/BaseMemoryLib.h>\r
+#include <Library/LocalApicLib.h>\r
#include <Library/MemEncryptSevLib.h>\r
#include <Library/VmgExitLib.h>\r
#include <Register/Amd/Msr.h>\r
return Status;\r
}\r
\r
+/**\r
+ Validate that the MMIO memory access is not to encrypted memory.\r
+\r
+ Examine the pagetable entry for the memory specified. MMIO should not be\r
+ performed against encrypted memory. MMIO to the APIC page is always allowed.\r
+\r
+ @param[in] Ghcb Pointer to the Guest-Hypervisor Communication Block\r
+ @param[in] MemoryAddress Memory address to validate\r
+ @param[in] MemoryLength Memory length to validate\r
+\r
+ @retval 0 Memory is not encrypted\r
+ @return New exception value to propogate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+ValidateMmioMemory (\r
+ IN GHCB *Ghcb,\r
+ IN UINTN MemoryAddress,\r
+ IN UINTN MemoryLength\r
+ )\r
+{\r
+ MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE State;\r
+ GHCB_EVENT_INJECTION GpEvent;\r
+ UINTN Address;\r
+\r
+ //\r
+ // Allow APIC accesses (which will have the encryption bit set during\r
+ // SEC and PEI phases).\r
+ //\r
+ Address = MemoryAddress & ~(SIZE_4KB - 1);\r
+ if (Address == GetLocalApicBaseAddress ()) {\r
+ return 0;\r
+ }\r
+\r
+ State = MemEncryptSevGetAddressRangeState (\r
+ 0,\r
+ MemoryAddress,\r
+ MemoryLength\r
+ );\r
+ if (State == MemEncryptSevAddressRangeUnencrypted) {\r
+ return 0;\r
+ }\r
+\r
+ //\r
+ // Any state other than unencrypted is an error, issue a #GP.\r
+ //\r
+ GpEvent.Uint64 = 0;\r
+ GpEvent.Elements.Vector = GP_EXCEPTION;\r
+ GpEvent.Elements.Type = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;\r
+ GpEvent.Elements.Valid = 1;\r
+\r
+ return GpEvent.Uint64;\r
+}\r
+\r
/**\r
Handle an MMIO event.\r
\r
return UnsupportedExit (Ghcb, Regs, InstructionData);\r
}\r
\r
+ Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
+ if (Status != 0) {\r
+ return Status;\r
+ }\r
+\r
ExitInfo1 = InstructionData->Ext.RmData;\r
ExitInfo2 = Bytes;\r
CopyMem (Ghcb->SharedBuffer, &InstructionData->Ext.RegData, Bytes);\r
InstructionData->ImmediateSize = Bytes;\r
InstructionData->End += Bytes;\r
\r
+ Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
+ if (Status != 0) {\r
+ return Status;\r
+ }\r
+\r
ExitInfo1 = InstructionData->Ext.RmData;\r
ExitInfo2 = Bytes;\r
CopyMem (Ghcb->SharedBuffer, InstructionData->Immediate, Bytes);\r
return UnsupportedExit (Ghcb, Regs, InstructionData);\r
}\r
\r
+ Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
+ if (Status != 0) {\r
+ return Status;\r
+ }\r
+\r
ExitInfo1 = InstructionData->Ext.RmData;\r
ExitInfo2 = Bytes;\r
\r
case 0xB7:\r
Bytes = (Bytes != 0) ? Bytes : 2;\r
\r
+ Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
+ if (Status != 0) {\r
+ return Status;\r
+ }\r
+\r
ExitInfo1 = InstructionData->Ext.RmData;\r
ExitInfo2 = Bytes;\r
\r
case 0xBF:\r
Bytes = (Bytes != 0) ? Bytes : 2;\r
\r
+ Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
+ if (Status != 0) {\r
+ return Status;\r
+ }\r
+\r
ExitInfo1 = InstructionData->Ext.RmData;\r
ExitInfo2 = Bytes;\r
\r