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); }