summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--UefiCpuPkg/CpuDxe/CpuMp.c28
1 files changed, 25 insertions, 3 deletions
diff --git a/UefiCpuPkg/CpuDxe/CpuMp.c b/UefiCpuPkg/CpuDxe/CpuMp.c
index b90312e863..b5478ff7c4 100644
--- a/UefiCpuPkg/CpuDxe/CpuMp.c
+++ b/UefiCpuPkg/CpuDxe/CpuMp.c
@@ -661,7 +661,12 @@ InitializeMpExceptionStackSwitchHandlers (
UINT8 *Buffer;
SwitchStackData = AllocateZeroPool (mNumberOfProcessors * sizeof (EXCEPTION_STACK_SWITCH_CONTEXT));
- ASSERT (SwitchStackData != NULL);
+ if (SwitchStackData == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a Failed to allocate buffer for SwitchStackData\n", __func__));
+ ASSERT (SwitchStackData != NULL);
+ return;
+ }
+
for (Index = 0; Index < mNumberOfProcessors; ++Index) {
//
// Because the procedure may runs multiple times, use the status EFI_NOT_STARTED
@@ -689,8 +694,24 @@ InitializeMpExceptionStackSwitchHandlers (
}
if (BufferSize != 0) {
- Buffer = AllocateRuntimeZeroPool (BufferSize);
- ASSERT (Buffer != NULL);
+ // we are allocating the buffer that will hold the new GDT and IDT for the APs. These must be allocated below
+ // 4GB as they are used by protected mode code on the APs when they are started up after this point. If they are
+ // above 4GB, the APs will triple fault because the 32 bit code segment is invalid
+ Buffer = (UINT8 *)(UINTN)(BASE_4GB - 1);
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiRuntimeServicesData,
+ EFI_SIZE_TO_PAGES (BufferSize),
+ (EFI_PHYSICAL_ADDRESS *)&Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to allocate buffer for InitializeExceptionStackSwitchHandlers Status %r\n", Status));
+ ASSERT_EFI_ERROR (Status);
+ goto Exit;
+ }
+
+ ZeroMem (Buffer, BufferSize);
+
BufferSize = 0;
for (Index = 0; Index < mNumberOfProcessors; ++Index) {
if (SwitchStackData[Index].Status == EFI_BUFFER_TOO_SMALL) {
@@ -717,6 +738,7 @@ InitializeMpExceptionStackSwitchHandlers (
}
}
+Exit:
FreePool (SwitchStackData);
}