UefiCpuPkg/CpuExceptionHandler: Add base support for the #VC exception
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2198 Add base support to handle #VC exceptions. Update the common exception handlers to invoke the VmgExitHandleVc () function of the VmgExitLib library when a #VC is encountered. A non-zero return code will propagate to the targeted exception handler. Under SEV-ES, a DR7 read or write intercept generates a #VC exception. 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 the saved context and the exception processing exit code does not attempt to restore the debug register values. Cc: Eric Dong <eric.dong@intel.com> Cc: Ray Ni <ray.ni@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Eric Dong <eric.dong@intel.com> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
committed by
mergify[bot]
parent
3a4a6ead32
commit
5277540e37
@ -14,7 +14,7 @@
|
|||||||
//
|
//
|
||||||
// 1 means an error code will be pushed, otherwise 0
|
// 1 means an error code will be pushed, otherwise 0
|
||||||
//
|
//
|
||||||
CONST UINT32 mErrorCodeFlag = 0x00227d00;
|
CONST UINT32 mErrorCodeFlag = 0x20227d00;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Define the maximum message length
|
// Define the maximum message length
|
||||||
@ -45,6 +45,14 @@ CONST CHAR8 *mExceptionNameStr[] = {
|
|||||||
"#XM - SIMD floating-point",
|
"#XM - SIMD floating-point",
|
||||||
"#VE - Virtualization",
|
"#VE - Virtualization",
|
||||||
"#CP - Control Protection"
|
"#CP - Control Protection"
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"#VC - VMM Communication",
|
||||||
};
|
};
|
||||||
|
|
||||||
#define EXCEPTION_KNOWN_NAME_NUM (sizeof (mExceptionNameStr) / sizeof (CHAR8 *))
|
#define EXCEPTION_KNOWN_NAME_NUM (sizeof (mExceptionNameStr) / sizeof (CHAR8 *))
|
||||||
|
@ -57,3 +57,4 @@
|
|||||||
PeCoffGetEntryPointLib
|
PeCoffGetEntryPointLib
|
||||||
MemoryAllocationLib
|
MemoryAllocationLib
|
||||||
DebugLib
|
DebugLib
|
||||||
|
VmgExitLib
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
HobLib
|
HobLib
|
||||||
MemoryAllocationLib
|
MemoryAllocationLib
|
||||||
SynchronizationLib
|
SynchronizationLib
|
||||||
|
VmgExitLib
|
||||||
|
|
||||||
[Pcd]
|
[Pcd]
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard # CONSUMES
|
gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard # CONSUMES
|
||||||
|
@ -6,8 +6,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
|||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#include "CpuExceptionCommon.h"
|
|
||||||
#include <Library/DebugLib.h>
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/VmgExitLib.h>
|
||||||
|
#include "CpuExceptionCommon.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Internal worker function for common exception handler.
|
Internal worker function for common exception handler.
|
||||||
@ -27,6 +28,23 @@ CommonExceptionHandlerWorker (
|
|||||||
RESERVED_VECTORS_DATA *ReservedVectors;
|
RESERVED_VECTORS_DATA *ReservedVectors;
|
||||||
EFI_CPU_INTERRUPT_HANDLER *ExternalInterruptHandler;
|
EFI_CPU_INTERRUPT_HANDLER *ExternalInterruptHandler;
|
||||||
|
|
||||||
|
if (ExceptionType == VC_EXCEPTION) {
|
||||||
|
EFI_STATUS Status;
|
||||||
|
//
|
||||||
|
// #VC needs to be handled immediately upon enabling exception handling
|
||||||
|
// and therefore can't use the RegisterCpuInterruptHandler() interface.
|
||||||
|
//
|
||||||
|
// Handle the #VC:
|
||||||
|
// On EFI_SUCCESS - Exception has been handled, return
|
||||||
|
// On other - ExceptionType contains (possibly new) exception
|
||||||
|
// value
|
||||||
|
//
|
||||||
|
Status = VmgExitHandleVc (&ExceptionType, SystemContext);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ExceptionHandlerContext = (EXCEPTION_HANDLER_CONTEXT *) (UINTN) (SystemContext.SystemContextIa32);
|
ExceptionHandlerContext = (EXCEPTION_HANDLER_CONTEXT *) (UINTN) (SystemContext.SystemContextIa32);
|
||||||
ReservedVectors = ExceptionHandlerData->ReservedVectors;
|
ReservedVectors = ExceptionHandlerData->ReservedVectors;
|
||||||
ExternalInterruptHandler = ExceptionHandlerData->ExternalInterruptHandler;
|
ExternalInterruptHandler = ExceptionHandlerData->ExternalInterruptHandler;
|
||||||
|
@ -7,6 +7,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
#include <PiPei.h>
|
#include <PiPei.h>
|
||||||
|
#include <Library/VmgExitLib.h>
|
||||||
#include "CpuExceptionCommon.h"
|
#include "CpuExceptionCommon.h"
|
||||||
|
|
||||||
CONST UINTN mDoFarReturnFlag = 0;
|
CONST UINTN mDoFarReturnFlag = 0;
|
||||||
@ -24,6 +25,24 @@ CommonExceptionHandler (
|
|||||||
IN EFI_SYSTEM_CONTEXT SystemContext
|
IN EFI_SYSTEM_CONTEXT SystemContext
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
if (ExceptionType == VC_EXCEPTION) {
|
||||||
|
EFI_STATUS Status;
|
||||||
|
//
|
||||||
|
// #VC needs to be handled immediately upon enabling exception handling
|
||||||
|
// and therefore can't use the RegisterCpuInterruptHandler() interface
|
||||||
|
// (which isn't supported under Sec and Pei anyway).
|
||||||
|
//
|
||||||
|
// Handle the #VC:
|
||||||
|
// On EFI_SUCCESS - Exception has been handled, return
|
||||||
|
// On other - ExceptionType contains (possibly new) exception
|
||||||
|
// value
|
||||||
|
//
|
||||||
|
Status = VmgExitHandleVc (&ExceptionType, SystemContext);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Initialize the serial port before dumping.
|
// Initialize the serial port before dumping.
|
||||||
//
|
//
|
||||||
|
@ -48,3 +48,4 @@
|
|||||||
PrintLib
|
PrintLib
|
||||||
LocalApicLib
|
LocalApicLib
|
||||||
PeCoffGetEntryPointLib
|
PeCoffGetEntryPointLib
|
||||||
|
VmgExitLib
|
||||||
|
@ -51,4 +51,5 @@
|
|||||||
LocalApicLib
|
LocalApicLib
|
||||||
PeCoffGetEntryPointLib
|
PeCoffGetEntryPointLib
|
||||||
DebugLib
|
DebugLib
|
||||||
|
VmgExitLib
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
; CommonExceptionHandler()
|
; CommonExceptionHandler()
|
||||||
;
|
;
|
||||||
|
|
||||||
|
%define VC_EXCEPTION 29
|
||||||
|
|
||||||
extern ASM_PFX(mErrorCodeFlag) ; Error code flags for exceptions
|
extern ASM_PFX(mErrorCodeFlag) ; Error code flags for exceptions
|
||||||
extern ASM_PFX(mDoFarReturnFlag) ; Do far return flag
|
extern ASM_PFX(mDoFarReturnFlag) ; Do far return flag
|
||||||
extern ASM_PFX(CommonExceptionHandler)
|
extern ASM_PFX(CommonExceptionHandler)
|
||||||
@ -224,6 +226,9 @@ HasErrorCode:
|
|||||||
push rax
|
push rax
|
||||||
|
|
||||||
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||||
|
cmp qword [rbp + 8], VC_EXCEPTION
|
||||||
|
je VcDebugRegs ; For SEV-ES (#VC) Debug registers ignored
|
||||||
|
|
||||||
mov rax, dr7
|
mov rax, dr7
|
||||||
push rax
|
push rax
|
||||||
mov rax, dr6
|
mov rax, dr6
|
||||||
@ -236,7 +241,19 @@ HasErrorCode:
|
|||||||
push rax
|
push rax
|
||||||
mov rax, dr0
|
mov rax, dr0
|
||||||
push rax
|
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;
|
;; FX_SAVE_STATE_X64 FxSaveState;
|
||||||
sub rsp, 512
|
sub rsp, 512
|
||||||
mov rdi, rsp
|
mov rdi, rsp
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
; CommonExceptionHandler()
|
; CommonExceptionHandler()
|
||||||
;
|
;
|
||||||
|
|
||||||
|
%define VC_EXCEPTION 29
|
||||||
|
|
||||||
extern ASM_PFX(mErrorCodeFlag) ; Error code flags for exceptions
|
extern ASM_PFX(mErrorCodeFlag) ; Error code flags for exceptions
|
||||||
extern ASM_PFX(mDoFarReturnFlag) ; Do far return flag
|
extern ASM_PFX(mDoFarReturnFlag) ; Do far return flag
|
||||||
extern ASM_PFX(CommonExceptionHandler)
|
extern ASM_PFX(CommonExceptionHandler)
|
||||||
@ -225,6 +227,9 @@ HasErrorCode:
|
|||||||
push rax
|
push rax
|
||||||
|
|
||||||
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||||
|
cmp qword [rbp + 8], VC_EXCEPTION
|
||||||
|
je VcDebugRegs ; For SEV-ES (#VC) Debug registers ignored
|
||||||
|
|
||||||
mov rax, dr7
|
mov rax, dr7
|
||||||
push rax
|
push rax
|
||||||
mov rax, dr6
|
mov rax, dr6
|
||||||
@ -237,7 +242,19 @@ HasErrorCode:
|
|||||||
push rax
|
push rax
|
||||||
mov rax, dr0
|
mov rax, dr0
|
||||||
push rax
|
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;
|
;; FX_SAVE_STATE_X64 FxSaveState;
|
||||||
sub rsp, 512
|
sub rsp, 512
|
||||||
mov rdi, rsp
|
mov rdi, rsp
|
||||||
|
@ -53,3 +53,4 @@
|
|||||||
PrintLib
|
PrintLib
|
||||||
LocalApicLib
|
LocalApicLib
|
||||||
PeCoffGetEntryPointLib
|
PeCoffGetEntryPointLib
|
||||||
|
VmgExitLib
|
||||||
|
Reference in New Issue
Block a user