|
@@ -1,7 +1,7 @@
|
|
|
/** @file
|
|
|
CPU PEI Module installs CPU Multiple Processor PPI.
|
|
|
|
|
|
- Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
|
|
|
+ Copyright (c) 2015 - 2022, Intel Corporation. All rights reserved.<BR>
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
|
|
**/
|
|
@@ -411,23 +411,13 @@ PeiWhoAmI (
|
|
|
return MpInitLibWhoAmI (ProcessorNumber);
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- 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.
|
|
@@ -444,27 +434,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
|
|
@@ -472,148 +452,60 @@ InitializeMpExceptionStackSwitchHandlers (
|
|
|
VOID
|
|
|
)
|
|
|
{
|
|
|
- EFI_STATUS Status;
|
|
|
- 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 NumberOfProcessors;
|
|
|
+ UINTN Index;
|
|
|
+ UINTN Bsp;
|
|
|
+ EXCEPTION_STACK_SWITCH_CONTEXT SwitchStackData;
|
|
|
+ UINTN BufferSize;
|
|
|
+ UINTN NumberOfProcessors;
|
|
|
|
|
|
if (!PcdGetBool (PcdCpuStackGuard)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ SwitchStackData.BufferSize = &BufferSize;
|
|
|
MpInitLibGetNumberOfProcessors (&NumberOfProcessors, NULL);
|
|
|
MpInitLibWhoAmI (&Bsp);
|
|
|
|
|
|
- ExceptionNumber = FixedPcdGetSize (PcdCpuStackSwitchExceptionList);
|
|
|
- NewStackSize = FixedPcdGet32 (PcdCpuKnownGoodStackSize) * ExceptionNumber;
|
|
|
-
|
|
|
- StackTop = AllocatePages (EFI_SIZE_TO_PAGES (NewStackSize * NumberOfProcessors));
|
|
|
- ASSERT (StackTop != NULL);
|
|
|
- if (StackTop == NULL) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- StackTop += NewStackSize * NumberOfProcessors;
|
|
|
-
|
|
|
- //
|
|
|
- // 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;
|
|
|
for (Index = 0; Index < NumberOfProcessors; ++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;
|
|
|
-
|
|
|
- Status = PeiServicesAllocatePool (
|
|
|
- NewGdtSize,
|
|
|
- (VOID **)&GdtBuffer
|
|
|
- );
|
|
|
- ASSERT (GdtBuffer != NULL);
|
|
|
- if (EFI_ERROR (Status)) {
|
|
|
- ASSERT_EFI_ERROR (Status);
|
|
|
- return;
|
|
|
+ if (BufferSize == 0) {
|
|
|
+ continue;
|
|
|
}
|
|
|
|
|
|
- //
|
|
|
- // 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 = AllocatePages (EFI_SIZE_TO_PAGES (BufferSize));
|
|
|
+ ASSERT (SwitchStackData.Buffer != NULL);
|
|
|
+ ZeroMem (SwitchStackData.Buffer, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (BufferSize)));
|
|
|
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;
|
|
|
}
|
|
|
}
|
|
|
|