[edk2-devel] [RFC PATCH v3 22/43] UefiCpuPkg/CpuExceptionHandler: Add support for DR7 Read/Write NAE events
Ni, Ray
ray.ni at intel.com
Thu Dec 12 06:53:57 UTC 2019
Tom,
Why all DR registers are not pushed to stack in VC handler?
I thought only DR7 pushing is skipped.
Thanks,
Ray
> -----Original Message-----
> From: Tom Lendacky <thomas.lendacky at amd.com>
> Sent: Thursday, November 21, 2019 4:07 AM
> To: devel at edk2.groups.io
> Cc: Justen, Jordan L <jordan.l.justen at intel.com>; Laszlo Ersek <lersek at redhat.com>; Ard Biesheuvel
> <ard.biesheuvel at linaro.org>; Kinney, Michael D <michael.d.kinney at intel.com>; Gao, Liming <liming.gao at intel.com>; Dong,
> Eric <eric.dong at intel.com>; Ni, Ray <ray.ni at intel.com>; Brijesh Singh <brijesh.singh at amd.com>
> Subject: [RFC PATCH v3 22/43] UefiCpuPkg/CpuExceptionHandler: Add support for DR7 Read/Write NAE events
>
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2198
>
> Under SEV-ES, a DR7 read or write intercept generates a #VC exception.
> The #VC handler must provide special support to the guest for this. On
> a DR7 write, the #VC handler must cache the value and issue a VMGEXIT
> to notify the hypervisor of the write. However, the #VC handler must
> not actually set the value of the DR7 register. On a DR7 read, the #VC
> handler must return the cached value of the DR7 register to the guest.
> VMGEXIT is not invoked for a DR7 register read.
>
> To avoid exception recursion, a #VC exception will not try to read and
> push the actual debug registers into the EFI_SYSTEM_CONTEXT_X64 struct
> and instead push zeroes. The #VC exception handler does not make use of
> the debug registers from saved context.
>
> Cc: Eric Dong <eric.dong at intel.com>
> Cc: Ray Ni <ray.ni at intel.com>
> Cc: Laszlo Ersek <lersek at redhat.com>
> Signed-off-by: Tom Lendacky <thomas.lendacky at amd.com>
> ---
> .../X64/AMDSevVcCommon.c | 68 +++++++++++++++++++
> .../X64/ExceptionHandlerAsm.nasm | 15 ++++
> 2 files changed, 83 insertions(+)
>
> diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c
> index 1d7c34e7e442..22393f72d795 100644
> --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c
> +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c
> @@ -13,6 +13,12 @@
>
> #define CR4_OSXSAVE (1 << 18)
>
> +#define DR7_RESET_VALUE 0x400
> +typedef struct {
> + BOOLEAN Dr7Cached;
> + UINT64 Dr7;
> +} SEV_ES_PER_CPU_DATA;
> +
> typedef enum {
> LongMode64Bit = 0,
> LongModeCompat32Bit,
> @@ -1081,6 +1087,60 @@ RdtscExit (
> return 0;
> }
>
> +STATIC
> +UINTN
> +Dr7WriteExit (
> + GHCB *Ghcb,
> + EFI_SYSTEM_CONTEXT_X64 *Regs,
> + SEV_ES_INSTRUCTION_DATA *InstructionData
> + )
> +{
> + SEV_ES_INSTRUCTION_OPCODE_EXT *Ext = &InstructionData->Ext;
> + SEV_ES_PER_CPU_DATA *SevEsData = (SEV_ES_PER_CPU_DATA *) (Ghcb + 1);
> + INTN *Register;
> + UINTN Status;
> +
> + DecodeModRm (Regs, InstructionData);
> +
> + /* MOV DRn always treats MOD == 3 no matter how encoded */
> + Register = GetRegisterPointer (Regs, Ext->ModRm.Rm);
> +
> + /* Using a value of 0 for ExitInfo1 means RAX holds the value */
> + Ghcb->SaveArea.Rax = *Register;
> + GhcbSetRegValid (Ghcb, GhcbRax);
> +
> + Status = VmgExit (Ghcb, SvmExitDr7Write, 0, 0);
> + if (Status) {
> + return Status;
> + }
> +
> + SevEsData->Dr7 = *Register;
> + SevEsData->Dr7Cached = TRUE;
> +
> + return 0;
> +}
> +
> +STATIC
> +UINTN
> +Dr7ReadExit (
> + GHCB *Ghcb,
> + EFI_SYSTEM_CONTEXT_X64 *Regs,
> + SEV_ES_INSTRUCTION_DATA *InstructionData
> + )
> +{
> + SEV_ES_INSTRUCTION_OPCODE_EXT *Ext = &InstructionData->Ext;
> + SEV_ES_PER_CPU_DATA *SevEsData = (SEV_ES_PER_CPU_DATA *) (Ghcb + 1);
> + INTN *Register;
> +
> + DecodeModRm (Regs, InstructionData);
> +
> + /* MOV DRn always treats MOD == 3 no matter how encoded */
> + Register = GetRegisterPointer (Regs, Ext->ModRm.Rm);
> + *Register = (SevEsData->Dr7Cached) ? SevEsData->Dr7 : DR7_RESET_VALUE;
> +
> + return 0;
> +}
> +
> UINTN
> DoVcCommon (
> GHCB *Ghcb,
> @@ -1097,6 +1157,14 @@ DoVcCommon (
>
> ExitCode = Regs->ExceptionData;
> switch (ExitCode) {
> + case SvmExitDr7Read:
> + NaeExit = Dr7ReadExit;
> + break;
> +
> + case SvmExitDr7Write:
> + NaeExit = Dr7WriteExit;
> + break;
> +
> case SvmExitRdtsc:
> NaeExit = RdtscExit;
> break;
> diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm
> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm
> index 19198f273137..a0549f7ae6bd 100644
> --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm
> +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm
> @@ -225,6 +225,9 @@ HasErrorCode:
> push rax
>
> ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
> + cmp qword [rbp + 8], 29
> + je VcDebugRegs ; For SEV-ES (#VC) Debug registers ignored
> +
> mov rax, dr7
> push rax
> mov rax, dr6
> @@ -237,7 +240,19 @@ HasErrorCode:
> push rax
> mov rax, dr0
> push rax
> + jmp DrFinish
>
> +VcDebugRegs:
> +;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7 are skipped for #VC to avoid exception recursion
> + xor rax, rax
> + push rax
> + push rax
> + push rax
> + push rax
> + push rax
> + push rax
> +
> +DrFinish:
> ;; FX_SAVE_STATE_X64 FxSaveState;
> sub rsp, 512
> mov rdi, rsp
> --
> 2.17.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#52148): https://edk2.groups.io/g/devel/message/52148
Mute This Topic: https://groups.io/mt/60973119/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-
More information about the edk2-devel-archive
mailing list