UefiCpuPkg: Simplify InitializeSeparateExceptionStacks
Hide the Exception implementation details in CpuExcetionHandlerLib and caller only need to provide buffer Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Ray Ni <ray.ni@intel.com> Cc: Rahul Kumar <rahul1.kumar@intel.com> Cc: Leif Lindholm <quic_llindhol@quicinc.com> Cc: Dandan Bi <dandan.bi@intel.com> Cc: Liming Gao <gaoliming@byosoft.com.cn> Cc: Jian J Wang <jian.j.wang@intel.com> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org> Reviewed-by: Sami Mujawar <sami.mujawar@arm.com> Signed-off-by: Zhiguang Liu <zhiguang.liu@intel.com>
This commit is contained in:
committed by
mergify[bot]
parent
1da2012d93
commit
0f7bccf584
@@ -596,23 +596,13 @@ CollectBistDataFromHob (
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Get GDT register value.
|
||||
|
||||
This function is mainly for AP purpose because AP may have different GDT
|
||||
table than BSP.
|
||||
|
||||
@param[in,out] Buffer The pointer to private data buffer.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
GetGdtr (
|
||||
IN OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
AsmReadGdtr ((IA32_DESCRIPTOR *)Buffer);
|
||||
}
|
||||
//
|
||||
// Structure for InitializeSeparateExceptionStacks
|
||||
//
|
||||
typedef struct {
|
||||
VOID *Buffer;
|
||||
UINTN *BufferSize;
|
||||
} EXCEPTION_STACK_SWITCH_CONTEXT;
|
||||
|
||||
/**
|
||||
Initializes CPU exceptions handlers for the sake of stack switch requirement.
|
||||
@@ -629,27 +619,17 @@ InitializeExceptionStackSwitchHandlers (
|
||||
IN OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
CPU_EXCEPTION_INIT_DATA *EssData;
|
||||
IA32_DESCRIPTOR Idtr;
|
||||
EFI_STATUS Status;
|
||||
EXCEPTION_STACK_SWITCH_CONTEXT *SwitchStackData;
|
||||
|
||||
EssData = Buffer;
|
||||
//
|
||||
// We don't plan to replace IDT table with a new one, but we should not assume
|
||||
// the AP's IDT is the same as BSP's IDT either.
|
||||
//
|
||||
AsmReadIdtr (&Idtr);
|
||||
EssData->Ia32.IdtTable = (VOID *)Idtr.Base;
|
||||
EssData->Ia32.IdtTableSize = Idtr.Limit + 1;
|
||||
Status = InitializeSeparateExceptionStacks (EssData);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
SwitchStackData = (EXCEPTION_STACK_SWITCH_CONTEXT *)Buffer;
|
||||
InitializeSeparateExceptionStacks (SwitchStackData->Buffer, SwitchStackData->BufferSize);
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes MP exceptions handlers for the sake of stack switch requirement.
|
||||
|
||||
This function will allocate required resources required to setup stack switch
|
||||
and pass them through CPU_EXCEPTION_INIT_DATA to each logic processor.
|
||||
and pass them through SwitchStackData to each logic processor.
|
||||
|
||||
**/
|
||||
VOID
|
||||
@@ -657,129 +637,53 @@ InitializeMpExceptionStackSwitchHandlers (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
UINTN Bsp;
|
||||
UINTN ExceptionNumber;
|
||||
UINTN OldGdtSize;
|
||||
UINTN NewGdtSize;
|
||||
UINTN NewStackSize;
|
||||
IA32_DESCRIPTOR Gdtr;
|
||||
CPU_EXCEPTION_INIT_DATA EssData;
|
||||
UINT8 *GdtBuffer;
|
||||
UINT8 *StackTop;
|
||||
UINTN Index;
|
||||
UINTN Bsp;
|
||||
EXCEPTION_STACK_SWITCH_CONTEXT SwitchStackData;
|
||||
UINTN BufferSize;
|
||||
|
||||
ExceptionNumber = FixedPcdGetSize (PcdCpuStackSwitchExceptionList);
|
||||
NewStackSize = FixedPcdGet32 (PcdCpuKnownGoodStackSize) * ExceptionNumber;
|
||||
|
||||
StackTop = AllocateRuntimeZeroPool (NewStackSize * mNumberOfProcessors);
|
||||
ASSERT (StackTop != NULL);
|
||||
StackTop += NewStackSize * mNumberOfProcessors;
|
||||
|
||||
//
|
||||
// The default exception handlers must have been initialized. Let's just skip
|
||||
// it in this method.
|
||||
//
|
||||
EssData.Ia32.Revision = CPU_EXCEPTION_INIT_DATA_REV;
|
||||
EssData.Ia32.InitDefaultHandlers = FALSE;
|
||||
|
||||
EssData.Ia32.StackSwitchExceptions = FixedPcdGetPtr (PcdCpuStackSwitchExceptionList);
|
||||
EssData.Ia32.StackSwitchExceptionNumber = ExceptionNumber;
|
||||
EssData.Ia32.KnownGoodStackSize = FixedPcdGet32 (PcdCpuKnownGoodStackSize);
|
||||
|
||||
//
|
||||
// Initialize Gdtr to suppress incorrect compiler/analyzer warnings.
|
||||
//
|
||||
Gdtr.Base = 0;
|
||||
Gdtr.Limit = 0;
|
||||
SwitchStackData.BufferSize = &BufferSize;
|
||||
MpInitLibWhoAmI (&Bsp);
|
||||
|
||||
for (Index = 0; Index < mNumberOfProcessors; ++Index) {
|
||||
//
|
||||
// To support stack switch, we need to re-construct GDT but not IDT.
|
||||
//
|
||||
SwitchStackData.Buffer = NULL;
|
||||
BufferSize = 0;
|
||||
|
||||
if (Index == Bsp) {
|
||||
GetGdtr (&Gdtr);
|
||||
InitializeExceptionStackSwitchHandlers (&SwitchStackData);
|
||||
} else {
|
||||
//
|
||||
// AP might have different size of GDT from BSP.
|
||||
// AP might need different buffer size from BSP.
|
||||
//
|
||||
MpInitLibStartupThisAP (GetGdtr, Index, NULL, 0, (VOID *)&Gdtr, NULL);
|
||||
MpInitLibStartupThisAP (InitializeExceptionStackSwitchHandlers, Index, NULL, 0, (VOID *)&SwitchStackData, NULL);
|
||||
}
|
||||
|
||||
//
|
||||
// X64 needs only one TSS of current task working for all exceptions
|
||||
// because of its IST feature. IA32 needs one TSS for each exception
|
||||
// in addition to current task. Since AP is not supposed to allocate
|
||||
// memory, we have to do it in BSP. To simplify the code, we allocate
|
||||
// memory for IA32 case to cover both IA32 and X64 exception stack
|
||||
// switch.
|
||||
//
|
||||
// Layout of memory to allocate for each processor:
|
||||
// --------------------------------
|
||||
// | Alignment | (just in case)
|
||||
// --------------------------------
|
||||
// | |
|
||||
// | Original GDT |
|
||||
// | |
|
||||
// --------------------------------
|
||||
// | Current task descriptor |
|
||||
// --------------------------------
|
||||
// | |
|
||||
// | Exception task descriptors | X ExceptionNumber
|
||||
// | |
|
||||
// --------------------------------
|
||||
// | Current task-state segment |
|
||||
// --------------------------------
|
||||
// | |
|
||||
// | Exception task-state segment | X ExceptionNumber
|
||||
// | |
|
||||
// --------------------------------
|
||||
//
|
||||
OldGdtSize = Gdtr.Limit + 1;
|
||||
EssData.Ia32.ExceptionTssDescSize = sizeof (IA32_TSS_DESCRIPTOR) *
|
||||
(ExceptionNumber + 1);
|
||||
EssData.Ia32.ExceptionTssSize = sizeof (IA32_TASK_STATE_SEGMENT) *
|
||||
(ExceptionNumber + 1);
|
||||
NewGdtSize = sizeof (IA32_TSS_DESCRIPTOR) +
|
||||
OldGdtSize +
|
||||
EssData.Ia32.ExceptionTssDescSize +
|
||||
EssData.Ia32.ExceptionTssSize;
|
||||
if (BufferSize == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GdtBuffer = AllocateRuntimeZeroPool (NewGdtSize);
|
||||
ASSERT (GdtBuffer != NULL);
|
||||
|
||||
//
|
||||
// Make sure GDT table alignment
|
||||
//
|
||||
EssData.Ia32.GdtTable = ALIGN_POINTER (GdtBuffer, sizeof (IA32_TSS_DESCRIPTOR));
|
||||
NewGdtSize -= ((UINT8 *)EssData.Ia32.GdtTable - GdtBuffer);
|
||||
EssData.Ia32.GdtTableSize = NewGdtSize;
|
||||
|
||||
EssData.Ia32.ExceptionTssDesc = ((UINT8 *)EssData.Ia32.GdtTable + OldGdtSize);
|
||||
EssData.Ia32.ExceptionTss = ((UINT8 *)EssData.Ia32.GdtTable + OldGdtSize +
|
||||
EssData.Ia32.ExceptionTssDescSize);
|
||||
|
||||
EssData.Ia32.KnownGoodStackTop = (UINTN)StackTop;
|
||||
SwitchStackData.Buffer = AllocateRuntimeZeroPool (BufferSize);
|
||||
ASSERT (SwitchStackData.Buffer != NULL);
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"Exception stack top[cpu%lu]: 0x%lX\n",
|
||||
"Buffer[cpu%lu] for InitializeExceptionStackSwitchHandlers: 0x%lX with size 0x%x\n",
|
||||
(UINT64)(UINTN)Index,
|
||||
(UINT64)(UINTN)StackTop
|
||||
(UINT64)(UINTN)SwitchStackData.Buffer,
|
||||
(UINT32)BufferSize
|
||||
));
|
||||
|
||||
if (Index == Bsp) {
|
||||
InitializeExceptionStackSwitchHandlers (&EssData);
|
||||
InitializeExceptionStackSwitchHandlers (&SwitchStackData);
|
||||
} else {
|
||||
MpInitLibStartupThisAP (
|
||||
InitializeExceptionStackSwitchHandlers,
|
||||
Index,
|
||||
NULL,
|
||||
0,
|
||||
(VOID *)&EssData,
|
||||
(VOID *)&SwitchStackData,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
StackTop -= NewStackSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user