SEV_ES_INSTRUCTION_DATA *InstructionData\r
);\r
\r
+//\r
+// Per-CPU data mapping structure\r
+//\r
+typedef struct {\r
+ BOOLEAN Dr7Cached;\r
+ UINT64 Dr7;\r
+} SEV_ES_PER_CPU_DATA;\r
+\r
\r
/**\r
Checks the GHCB to determine if the specified register has been marked valid.\r
return 0;\r
}\r
\r
+/**\r
+ Handle a DR7 register write event.\r
+\r
+ Use the VMGEXIT instruction to handle a DR7 write event.\r
+\r
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication\r
+ Block\r
+ @param[in, out] Regs x64 processor context\r
+ @param[in] InstructionData Instruction parsing context\r
+\r
+ @retval 0 Event handled successfully\r
+ @return New exception value to propagate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+Dr7WriteExit (\r
+ IN OUT GHCB *Ghcb,\r
+ IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,\r
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData\r
+ )\r
+{\r
+ SEV_ES_INSTRUCTION_OPCODE_EXT *Ext;\r
+ SEV_ES_PER_CPU_DATA *SevEsData;\r
+ UINT64 *Register;\r
+ UINT64 Status;\r
+\r
+ Ext = &InstructionData->Ext;\r
+ SevEsData = (SEV_ES_PER_CPU_DATA *) (Ghcb + 1);\r
+\r
+ DecodeModRm (Regs, InstructionData);\r
+\r
+ //\r
+ // MOV DRn always treats MOD == 3 no matter how encoded\r
+ //\r
+ Register = GetRegisterPointer (Regs, Ext->ModRm.Rm);\r
+\r
+ //\r
+ // Using a value of 0 for ExitInfo1 means RAX holds the value\r
+ //\r
+ Ghcb->SaveArea.Rax = *Register;\r
+ GhcbSetRegValid (Ghcb, GhcbRax);\r
+\r
+ Status = VmgExit (Ghcb, SVM_EXIT_DR7_WRITE, 0, 0);\r
+ if (Status != 0) {\r
+ return Status;\r
+ }\r
+\r
+ SevEsData->Dr7 = *Register;\r
+ SevEsData->Dr7Cached = TRUE;\r
+\r
+ return 0;\r
+}\r
+\r
+/**\r
+ Handle a DR7 register read event.\r
+\r
+ Use the VMGEXIT instruction to handle a DR7 read event.\r
+\r
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication\r
+ Block\r
+ @param[in, out] Regs x64 processor context\r
+ @param[in] InstructionData Instruction parsing context\r
+\r
+ @retval 0 Event handled successfully\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+Dr7ReadExit (\r
+ IN OUT GHCB *Ghcb,\r
+ IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,\r
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData\r
+ )\r
+{\r
+ SEV_ES_INSTRUCTION_OPCODE_EXT *Ext;\r
+ SEV_ES_PER_CPU_DATA *SevEsData;\r
+ UINT64 *Register;\r
+\r
+ Ext = &InstructionData->Ext;\r
+ SevEsData = (SEV_ES_PER_CPU_DATA *) (Ghcb + 1);\r
+\r
+ DecodeModRm (Regs, InstructionData);\r
+\r
+ //\r
+ // MOV DRn always treats MOD == 3 no matter how encoded\r
+ //\r
+ Register = GetRegisterPointer (Regs, Ext->ModRm.Rm);\r
+\r
+ //\r
+ // If there is a cached valued for DR7, return that. Otherwise return the\r
+ // DR7 standard reset value of 0x400 (no debug breakpoints set).\r
+ //\r
+ *Register = (SevEsData->Dr7Cached) ? SevEsData->Dr7 : 0x400;\r
+\r
+ return 0;\r
+}\r
+\r
/**\r
Handle a #VC exception.\r
\r
\r
ExitCode = Regs->ExceptionData;\r
switch (ExitCode) {\r
+ case SVM_EXIT_DR7_READ:\r
+ NaeExit = Dr7ReadExit;\r
+ break;\r
+\r
+ case SVM_EXIT_DR7_WRITE:\r
+ NaeExit = Dr7WriteExit;\r
+ break;\r
+\r
case SVM_EXIT_RDTSC:\r
NaeExit = RdtscExit;\r
break;\r