CpuException: Add InitializeSeparateExceptionStacks

Today InitializeCpuExceptionHandlersEx is called from three modules:
1. DxeCore (links to DxeCpuExceptionHandlerLib)
    DxeCore expects it initializes the IDT entries as well as
    assigning separate stacks for #DF and #PF.
2. CpuMpPei (links to PeiCpuExceptionHandlerLib)
   and CpuDxe (links to DxeCpuExceptionHandlerLib)
    It's called for each thread for only assigning separate stacks for
    #DF and #PF. The IDT entries initialization is skipped because
    caller sets InitData->X64.InitDefaultHandlers to FALSE.

Additionally, SecPeiCpuExceptionHandlerLib, SmmCpuExceptionHandlerLib
also implement such API and the behavior of the API is simply to initialize
IDT entries only.

Because it mixes the IDT entries initialization and separate stacks
assignment for certain exception handlers together, in order to know
whether the function call only initializes IDT entries, or assigns stacks,
we need to check:
1. value of InitData->X64.InitDefaultHandlers
2. library instance

This patch cleans up the code to separate the stack assignment to a new API:
InitializeSeparateExceptionStacks().

Only when caller calls the new API, the separate stacks are assigned.
With this change, the SecPei and Smm instance can return unsupported which
gives caller a very clear status.

The old API InitializeCpuExceptionHandlersEx() is removed in this patch.
Because no platform module is consuming the old API, the impact is none.

Signed-off-by: Ray Ni <ray.ni@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
This commit is contained in:
Ray Ni 2022-05-20 19:12:35 +08:00 committed by mergify[bot]
parent 2a09527ebc
commit e7abb94d1f
9 changed files with 74 additions and 184 deletions

View File

@ -253,7 +253,7 @@ DxeMain (
VectorInfoList = (EFI_VECTOR_HANDOFF_INFO *)(GET_GUID_HOB_DATA (GuidHob));
}
Status = InitializeCpuExceptionHandlersEx (VectorInfoList, NULL);
Status = InitializeCpuExceptionHandlers (VectorInfoList);
ASSERT_EFI_ERROR (Status);
//

View File

@ -103,32 +103,20 @@ InitializeCpuExceptionHandlers (
);
/**
Initializes all CPU exceptions entries with optional extra initializations.
Setup separate stacks for certain exception handlers.
By default, this method should include all functionalities implemented by
InitializeCpuExceptionHandlers(), plus extra initialization works, if any.
This could be done by calling InitializeCpuExceptionHandlers() directly
in this method besides the extra works.
InitData is optional and processor arch dependent.
InitData is optional and its use and content are processor arch dependent.
The typical usage of it is to convey resources which have to be reserved
elsewhere and are necessary for the extra initializations of exception.
@param[in] InitData Pointer to data optional for information about how
to assign stacks for certain exception handlers.
@param[in] VectorInfo Pointer to reserved vector list.
@param[in] InitData Pointer to data optional for extra initializations
of exception.
@retval EFI_SUCCESS The exceptions have been successfully
initialized.
@retval EFI_INVALID_PARAMETER VectorInfo or InitData contains invalid
content.
@retval EFI_SUCCESS The stacks are assigned successfully.
@retval EFI_UNSUPPORTED This function is not supported.
**/
EFI_STATUS
EFIAPI
InitializeCpuExceptionHandlersEx (
IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL,
InitializeSeparateExceptionStacks (
IN CPU_EXCEPTION_INIT_DATA *InitData OPTIONAL
);

View File

@ -82,34 +82,22 @@ DumpCpuContext (
}
/**
Initializes all CPU exceptions entries with optional extra initializations.
Setup separate stacks for certain exception handlers.
By default, this method should include all functionalities implemented by
InitializeCpuExceptionHandlers(), plus extra initialization works, if any.
This could be done by calling InitializeCpuExceptionHandlers() directly
in this method besides the extra works.
InitData is optional and processor arch dependent.
InitData is optional and its use and content are processor arch dependent.
The typical usage of it is to convey resources which have to be reserved
elsewhere and are necessary for the extra initializations of exception.
@param[in] InitData Pointer to data optional for information about how
to assign stacks for certain exception handlers.
@param[in] VectorInfo Pointer to reserved vector list.
@param[in] InitData Pointer to data optional for extra initializations
of exception.
@retval EFI_SUCCESS The exceptions have been successfully
initialized.
@retval EFI_INVALID_PARAMETER VectorInfo or InitData contains invalid
content.
@retval EFI_SUCCESS The stacks are assigned successfully.
@retval EFI_UNSUPPORTED This function is not supported.
**/
EFI_STATUS
EFIAPI
InitializeCpuExceptionHandlersEx (
IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL,
InitializeSeparateExceptionStacks (
IN CPU_EXCEPTION_INIT_DATA *InitData OPTIONAL
)
{
return InitializeCpuExceptionHandlers (VectorInfo);
return EFI_UNSUPPORTED;
}

View File

@ -1,7 +1,7 @@
/** @file
CPU DXE Module to produce CPU MP Protocol.
Copyright (c) 2008 - 2017, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2008 - 2022, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -617,7 +617,7 @@ GetGdtr (
/**
Initializes CPU exceptions handlers for the sake of stack switch requirement.
This function is a wrapper of InitializeCpuExceptionHandlersEx. It's mainly
This function is a wrapper of InitializeSeparateExceptionStacks. It's mainly
for the sake of AP's init because of EFI_AP_PROCEDURE API requirement.
@param[in,out] Buffer The pointer to private data buffer.
@ -641,7 +641,7 @@ InitializeExceptionStackSwitchHandlers (
AsmReadIdtr (&Idtr);
EssData->Ia32.IdtTable = (VOID *)Idtr.Base;
EssData->Ia32.IdtTableSize = Idtr.Limit + 1;
Status = InitializeCpuExceptionHandlersEx (NULL, EssData);
Status = InitializeSeparateExceptionStacks (EssData);
ASSERT_EFI_ERROR (Status);
}

View File

@ -432,7 +432,7 @@ GetGdtr (
/**
Initializes CPU exceptions handlers for the sake of stack switch requirement.
This function is a wrapper of InitializeCpuExceptionHandlersEx. It's mainly
This function is a wrapper of InitializeSeparateExceptionStacks. It's mainly
for the sake of AP's init because of EFI_AP_PROCEDURE API requirement.
@param[in,out] Buffer The pointer to private data buffer.
@ -456,7 +456,7 @@ InitializeExceptionStackSwitchHandlers (
AsmReadIdtr (&Idtr);
EssData->Ia32.IdtTable = (VOID *)Idtr.Base;
EssData->Ia32.IdtTableSize = Idtr.Limit + 1;
Status = InitializeCpuExceptionHandlersEx (NULL, EssData);
Status = InitializeSeparateExceptionStacks (EssData);
ASSERT_EFI_ERROR (Status);
}

View File

@ -103,82 +103,49 @@ RegisterCpuInterruptHandler (
}
/**
Initializes CPU exceptions entries and setup stack switch for given exceptions.
Setup separate stacks for certain exception handlers.
This method will call InitializeCpuExceptionHandlers() to setup default
exception handlers unless indicated not to do it explicitly.
InitData is optional and processor arch dependent.
If InitData is passed with NULL, this method will use the resource reserved
by global variables to initialize it; Otherwise it will use data in InitData
to setup stack switch. This is for the different use cases in DxeCore and
Cpu MP exception initialization.
@param[in] InitData Pointer to data optional for information about how
to assign stacks for certain exception handlers.
@param[in] VectorInfo Pointer to reserved vector list.
@param[in] InitData Pointer to data required to setup stack switch for
given exceptions.
@retval EFI_SUCCESS The exceptions have been successfully
initialized.
@retval EFI_INVALID_PARAMETER VectorInfo or InitData contains invalid
content.
@retval EFI_SUCCESS The stacks are assigned successfully.
@retval EFI_UNSUPPORTED This function is not supported.
**/
EFI_STATUS
EFIAPI
InitializeCpuExceptionHandlersEx (
IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL,
InitializeSeparateExceptionStacks (
IN CPU_EXCEPTION_INIT_DATA *InitData OPTIONAL
)
{
EFI_STATUS Status;
CPU_EXCEPTION_INIT_DATA EssData;
IA32_DESCRIPTOR Idtr;
IA32_DESCRIPTOR Gdtr;
//
// To avoid repeat initialization of default handlers, the caller should pass
// an extended init data with InitDefaultHandlers set to FALSE. There's no
// need to call this method to just initialize default handlers. Call non-ex
// version instead; or this method must be implemented as a simple wrapper of
// non-ex version of it, if this version has to be called.
//
if ((InitData == NULL) || InitData->X64.InitDefaultHandlers) {
Status = InitializeCpuExceptionHandlers (VectorInfo);
} else {
Status = EFI_SUCCESS;
if (InitData == NULL) {
SetMem (mNewGdt, sizeof (mNewGdt), 0);
AsmReadIdtr (&Idtr);
AsmReadGdtr (&Gdtr);
EssData.X64.Revision = CPU_EXCEPTION_INIT_DATA_REV;
EssData.X64.KnownGoodStackTop = (UINTN)mNewStack + sizeof (mNewStack);
EssData.X64.KnownGoodStackSize = CPU_KNOWN_GOOD_STACK_SIZE;
EssData.X64.StackSwitchExceptions = CPU_STACK_SWITCH_EXCEPTION_LIST;
EssData.X64.StackSwitchExceptionNumber = CPU_STACK_SWITCH_EXCEPTION_NUMBER;
EssData.X64.IdtTable = (VOID *)Idtr.Base;
EssData.X64.IdtTableSize = Idtr.Limit + 1;
EssData.X64.GdtTable = mNewGdt;
EssData.X64.GdtTableSize = sizeof (mNewGdt);
EssData.X64.ExceptionTssDesc = mNewGdt + Gdtr.Limit + 1;
EssData.X64.ExceptionTssDescSize = CPU_TSS_DESC_SIZE;
EssData.X64.ExceptionTss = mNewGdt + Gdtr.Limit + 1 + CPU_TSS_DESC_SIZE;
EssData.X64.ExceptionTssSize = CPU_TSS_SIZE;
InitData = &EssData;
}
if (!EFI_ERROR (Status)) {
//
// Initializing stack switch is only necessary for Stack Guard functionality.
//
if (PcdGetBool (PcdCpuStackGuard)) {
if (InitData == NULL) {
SetMem (mNewGdt, sizeof (mNewGdt), 0);
AsmReadIdtr (&Idtr);
AsmReadGdtr (&Gdtr);
EssData.X64.Revision = CPU_EXCEPTION_INIT_DATA_REV;
EssData.X64.KnownGoodStackTop = (UINTN)mNewStack + sizeof (mNewStack);
EssData.X64.KnownGoodStackSize = CPU_KNOWN_GOOD_STACK_SIZE;
EssData.X64.StackSwitchExceptions = CPU_STACK_SWITCH_EXCEPTION_LIST;
EssData.X64.StackSwitchExceptionNumber = CPU_STACK_SWITCH_EXCEPTION_NUMBER;
EssData.X64.IdtTable = (VOID *)Idtr.Base;
EssData.X64.IdtTableSize = Idtr.Limit + 1;
EssData.X64.GdtTable = mNewGdt;
EssData.X64.GdtTableSize = sizeof (mNewGdt);
EssData.X64.ExceptionTssDesc = mNewGdt + Gdtr.Limit + 1;
EssData.X64.ExceptionTssDescSize = CPU_TSS_DESC_SIZE;
EssData.X64.ExceptionTss = mNewGdt + Gdtr.Limit + 1 + CPU_TSS_DESC_SIZE;
EssData.X64.ExceptionTssSize = CPU_TSS_SIZE;
InitData = &EssData;
}
Status = ArchSetupExceptionStack (InitData);
}
}
return Status;
return ArchSetupExceptionStack (InitData);
}

View File

@ -150,57 +150,26 @@ InitializeCpuExceptionHandlers (
}
/**
Initializes all CPU exceptions entries with optional extra initializations.
Setup separate stacks for certain exception handlers.
By default, this method should include all functionalities implemented by
InitializeCpuExceptionHandlers(), plus extra initialization works, if any.
This could be done by calling InitializeCpuExceptionHandlers() directly
in this method besides the extra works.
InitData is optional and processor arch dependent.
InitData is optional and its use and content are processor arch dependent.
The typical usage of it is to convey resources which have to be reserved
elsewhere and are necessary for the extra initializations of exception.
@param[in] InitData Pointer to data optional for information about how
to assign stacks for certain exception handlers.
@param[in] VectorInfo Pointer to reserved vector list.
@param[in] InitData Pointer to data optional for extra initializations
of exception.
@retval EFI_SUCCESS The exceptions have been successfully
initialized.
@retval EFI_INVALID_PARAMETER VectorInfo or InitData contains invalid
content.
@retval EFI_SUCCESS The stacks are assigned successfully.
@retval EFI_UNSUPPORTED This function is not supported.
**/
EFI_STATUS
EFIAPI
InitializeCpuExceptionHandlersEx (
IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL,
InitializeSeparateExceptionStacks (
IN CPU_EXCEPTION_INIT_DATA *InitData OPTIONAL
)
{
EFI_STATUS Status;
//
// To avoid repeat initialization of default handlers, the caller should pass
// an extended init data with InitDefaultHandlers set to FALSE. There's no
// need to call this method to just initialize default handlers. Call non-ex
// version instead; or this method must be implemented as a simple wrapper of
// non-ex version of it, if this version has to be called.
//
if ((InitData == NULL) || InitData->Ia32.InitDefaultHandlers) {
Status = InitializeCpuExceptionHandlers (VectorInfo);
} else {
Status = EFI_SUCCESS;
if (InitData == NULL) {
return EFI_UNSUPPORTED;
}
if (!EFI_ERROR (Status)) {
//
// Initializing stack switch is only necessary for Stack Guard functionality.
//
if (PcdGetBool (PcdCpuStackGuard) && (InitData != NULL)) {
Status = ArchSetupExceptionStack (InitData);
}
}
return Status;
return ArchSetupExceptionStack (InitData);
}

View File

@ -200,33 +200,22 @@ RegisterCpuInterruptHandler (
}
/**
Initializes all CPU exceptions entries with optional extra initializations.
Setup separate stacks for certain exception handlers.
By default, this method should include all functionalities implemented by
InitializeCpuExceptionHandlers(), plus extra initialization works, if any.
This could be done by calling InitializeCpuExceptionHandlers() directly
in this method besides the extra works.
InitData is optional and processor arch dependent.
InitData is optional and its use and content are processor arch dependent.
The typical usage of it is to convey resources which have to be reserved
elsewhere and are necessary for the extra initializations of exception.
@param[in] InitData Pointer to data optional for information about how
to assign stacks for certain exception handlers.
@param[in] VectorInfo Pointer to reserved vector list.
@param[in] InitData Pointer to data optional for extra initializations
of exception.
@retval EFI_SUCCESS The exceptions have been successfully
initialized.
@retval EFI_INVALID_PARAMETER VectorInfo or InitData contains invalid
content.
@retval EFI_SUCCESS The stacks are assigned successfully.
@retval EFI_UNSUPPORTED This function is not supported.
**/
EFI_STATUS
EFIAPI
InitializeCpuExceptionHandlersEx (
IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL,
InitializeSeparateExceptionStacks (
IN CPU_EXCEPTION_INIT_DATA *InitData OPTIONAL
)
{
return InitializeCpuExceptionHandlers (VectorInfo);
return EFI_UNSUPPORTED;
}

View File

@ -96,33 +96,22 @@ RegisterCpuInterruptHandler (
}
/**
Initializes all CPU exceptions entries with optional extra initializations.
Setup separate stacks for certain exception handlers.
By default, this method should include all functionalities implemented by
InitializeCpuExceptionHandlers(), plus extra initialization works, if any.
This could be done by calling InitializeCpuExceptionHandlers() directly
in this method besides the extra works.
InitData is optional and processor arch dependent.
InitData is optional and its use and content are processor arch dependent.
The typical usage of it is to convey resources which have to be reserved
elsewhere and are necessary for the extra initializations of exception.
@param[in] InitData Pointer to data optional for information about how
to assign stacks for certain exception handlers.
@param[in] VectorInfo Pointer to reserved vector list.
@param[in] InitData Pointer to data optional for extra initializations
of exception.
@retval EFI_SUCCESS The exceptions have been successfully
initialized.
@retval EFI_INVALID_PARAMETER VectorInfo or InitData contains invalid
content.
@retval EFI_SUCCESS The stacks are assigned successfully.
@retval EFI_UNSUPPORTED This function is not supported.
**/
EFI_STATUS
EFIAPI
InitializeCpuExceptionHandlersEx (
IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL,
InitializeSeparateExceptionStacks (
IN CPU_EXCEPTION_INIT_DATA *InitData OPTIONAL
)
{
return InitializeCpuExceptionHandlers (VectorInfo);
return EFI_UNSUPPORTED;
}