diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
commit | f215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch) | |
tree | 6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe | |
parent | Initial commit. (diff) | |
download | virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip |
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe')
4 files changed, 390 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c new file mode 100644 index 00000000..040d23e8 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c @@ -0,0 +1,277 @@ +/** @file +ACPI CPU Data initialization module + +This module initializes the ACPI_CPU_DATA structure and registers the address +of this structure in the PcdCpuS3DataAddress PCD. This is a generic/simple +version of this module. It does not provide a machine check handler or CPU +register initialization tables for ACPI S3 resume. It also only supports the +number of CPUs reported by the MP Services Protocol, so this module does not +support hot plug CPUs. This module can be copied into a CPU specific package +and customized if these additional features are required. + +Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved.<BR> +Copyright (c) 2015, Red Hat, Inc. + +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiDxe.h> + +#include <AcpiCpuData.h> + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/DebugLib.h> +#include <Library/MtrrLib.h> +#include <Library/MemoryAllocationLib.h> + +#include <Protocol/MpService.h> +#include <Guid/EventGroup.h> + +// +// Data structure used to allocate ACPI_CPU_DATA and its supporting structures +// +typedef struct { + ACPI_CPU_DATA AcpiCpuData; + MTRR_SETTINGS MtrrTable; + IA32_DESCRIPTOR GdtrProfile; + IA32_DESCRIPTOR IdtrProfile; +} ACPI_CPU_DATA_EX; + +/** + Allocate EfiACPIMemoryNVS memory. + + @param[in] Size Size of memory to allocate. + + @return Allocated address for output. + +**/ +VOID * +AllocateAcpiNvsMemory ( + IN UINTN Size + ) +{ + EFI_PHYSICAL_ADDRESS Address; + EFI_STATUS Status; + VOID *Buffer; + + Status = gBS->AllocatePages ( + AllocateAnyPages, + EfiACPIMemoryNVS, + EFI_SIZE_TO_PAGES (Size), + &Address + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + Buffer = (VOID *)(UINTN)Address; + ZeroMem (Buffer, Size); + + return Buffer; +} + +/** + Allocate memory and clean it with zero. + + @param[in] Size Size of memory to allocate. + + @return Allocated address for output. + +**/ +VOID * +AllocateZeroPages ( + IN UINTN Size + ) +{ + VOID *Buffer; + + Buffer = AllocatePages (EFI_SIZE_TO_PAGES (Size)); + if (Buffer != NULL) { + ZeroMem (Buffer, Size); + } + + return Buffer; +} +/** + Callback function executed when the EndOfDxe event group is signaled. + + We delay allocating StartupVector and saving the MTRR settings until BDS signals EndOfDxe. + + @param[in] Event Event whose notification function is being invoked. + @param[out] Context Pointer to the MTRR_SETTINGS buffer to fill in. +**/ +VOID +EFIAPI +CpuS3DataOnEndOfDxe ( + IN EFI_EVENT Event, + OUT VOID *Context + ) +{ + EFI_STATUS Status; + ACPI_CPU_DATA_EX *AcpiCpuDataEx; + + AcpiCpuDataEx = (ACPI_CPU_DATA_EX *) Context; + // + // Allocate a 4KB reserved page below 1MB + // + AcpiCpuDataEx->AcpiCpuData.StartupVector = BASE_1MB - 1; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiReservedMemoryType, + 1, + &AcpiCpuDataEx->AcpiCpuData.StartupVector + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((EFI_D_VERBOSE, "%a\n", __FUNCTION__)); + MtrrGetAllMtrrs (&AcpiCpuDataEx->MtrrTable); + + // + // Close event, so it will not be invoked again. + // + gBS->CloseEvent (Event); +} + +/** + The entry function of the CpuS3Data driver. + + Allocate and initialize all fields of the ACPI_CPU_DATA structure except the + MTRR settings. Register an event notification on gEfiEndOfDxeEventGroupGuid + to capture the ACPI_CPU_DATA MTRR settings. The PcdCpuS3DataAddress is set + to the address that ACPI_CPU_DATA is allocated at. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval EFI_UNSUPPORTED Do not support ACPI S3. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +CpuS3DataInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + ACPI_CPU_DATA_EX *AcpiCpuDataEx; + ACPI_CPU_DATA *AcpiCpuData; + EFI_MP_SERVICES_PROTOCOL *MpServices; + UINTN NumberOfCpus; + UINTN NumberOfEnabledProcessors; + VOID *Stack; + UINTN GdtSize; + UINTN IdtSize; + VOID *Gdt; + VOID *Idt; + EFI_EVENT Event; + ACPI_CPU_DATA *OldAcpiCpuData; + + if (!PcdGetBool (PcdAcpiS3Enable)) { + return EFI_UNSUPPORTED; + } + + // + // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure + // + OldAcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress); + + AcpiCpuDataEx = AllocateZeroPages (sizeof (ACPI_CPU_DATA_EX)); + ASSERT (AcpiCpuDataEx != NULL); + AcpiCpuData = &AcpiCpuDataEx->AcpiCpuData; + + // + // Get MP Services Protocol + // + Status = gBS->LocateProtocol ( + &gEfiMpServiceProtocolGuid, + NULL, + (VOID **)&MpServices + ); + ASSERT_EFI_ERROR (Status); + + // + // Get the number of CPUs + // + Status = MpServices->GetNumberOfProcessors ( + MpServices, + &NumberOfCpus, + &NumberOfEnabledProcessors + ); + ASSERT_EFI_ERROR (Status); + AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus; + + // + // Initialize ACPI_CPU_DATA fields + // + AcpiCpuData->StackSize = PcdGet32 (PcdCpuApStackSize); + AcpiCpuData->ApMachineCheckHandlerBase = 0; + AcpiCpuData->ApMachineCheckHandlerSize = 0; + AcpiCpuData->GdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)&AcpiCpuDataEx->GdtrProfile; + AcpiCpuData->IdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)&AcpiCpuDataEx->IdtrProfile; + AcpiCpuData->MtrrTable = (EFI_PHYSICAL_ADDRESS)(UINTN)&AcpiCpuDataEx->MtrrTable; + + // + // Allocate stack space for all CPUs. + // Use ACPI NVS memory type because this data will be directly used by APs + // in S3 resume phase in long mode. Also during S3 resume, the stack buffer + // will only be used as scratch space. i.e. we won't read anything from it + // before we write to it, in PiSmmCpuDxeSmm. + // + Stack = AllocateAcpiNvsMemory (NumberOfCpus * AcpiCpuData->StackSize); + ASSERT (Stack != NULL); + AcpiCpuData->StackAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Stack; + + // + // Get the boot processor's GDT and IDT + // + AsmReadGdtr (&AcpiCpuDataEx->GdtrProfile); + AsmReadIdtr (&AcpiCpuDataEx->IdtrProfile); + + // + // Allocate GDT and IDT and copy current GDT and IDT contents + // + GdtSize = AcpiCpuDataEx->GdtrProfile.Limit + 1; + IdtSize = AcpiCpuDataEx->IdtrProfile.Limit + 1; + Gdt = AllocateZeroPages (GdtSize + IdtSize); + ASSERT (Gdt != NULL); + Idt = (VOID *)((UINTN)Gdt + GdtSize); + CopyMem (Gdt, (VOID *)AcpiCpuDataEx->GdtrProfile.Base, GdtSize); + CopyMem (Idt, (VOID *)AcpiCpuDataEx->IdtrProfile.Base, IdtSize); + AcpiCpuDataEx->GdtrProfile.Base = (UINTN)Gdt; + AcpiCpuDataEx->IdtrProfile.Base = (UINTN)Idt; + + if (OldAcpiCpuData != NULL) { + AcpiCpuData->RegisterTable = OldAcpiCpuData->RegisterTable; + AcpiCpuData->PreSmmInitRegisterTable = OldAcpiCpuData->PreSmmInitRegisterTable; + AcpiCpuData->ApLocation = OldAcpiCpuData->ApLocation; + CopyMem (&AcpiCpuData->CpuStatus, &OldAcpiCpuData->CpuStatus, sizeof (CPU_STATUS_INFORMATION)); + } + + // + // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure + // + Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData); + ASSERT_EFI_ERROR (Status); + + // + // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event. + // The notification function allocates StartupVector and saves MTRRs for ACPI_CPU_DATA + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + CpuS3DataOnEndOfDxe, + AcpiCpuData, + &gEfiEndOfDxeEventGroupGuid, + &Event + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf new file mode 100644 index 00000000..b0645a7c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf @@ -0,0 +1,65 @@ +## @file +# ACPI CPU Data initialization module +# +# This module initializes the ACPI_CPU_DATA structure and registers the address +# of this structure in the PcdCpuS3DataAddress PCD. This is a generic/simple +# version of this module. It does not provide a machine check handler or CPU +# register initialization tables for ACPI S3 resume. It also only supports the +# number of CPUs reported by the MP Services Protocol, so this module does not +# support hot plug CPUs. This module can be copied into a CPU specific package +# and customized if these additional features are required. +# +# Copyright (c) 2013-2016, Intel Corporation. All rights reserved.<BR> +# Copyright (c) 2015, Red Hat, Inc. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = CpuS3DataDxe + MODULE_UNI_FILE = CpuS3DataDxe.uni + FILE_GUID = 4D2E57EE-0E3F-44DD-93C4-D3B57E96945D + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = CpuS3DataInitialize + +# The following information is for reference only and not required by the build +# tools. +# +# VALID_ARCHITECTURES = IA32 X64 + +[Sources] + CpuS3Data.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + BaseLib + MtrrLib + MemoryAllocationLib + +[Guids] + gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event + +[Protocols] + gEfiMpServiceProtocolGuid ## CONSUMES + +[Pcd] + gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdCpuS3DataAddress ## PRODUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable ## CONSUMES + +[Depex] + gEfiMpServiceProtocolGuid + +[UserExtensions.TianoCore."ExtraFiles"] + CpuS3DataDxeExtra.uni diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.uni b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.uni new file mode 100644 index 00000000..d16c03fc --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.uni @@ -0,0 +1,34 @@ +// /** @file
+// ACPI CPU Data initialization module
+//
+// This module initializes the ACPI_CPU_DATA structure and registers the address
+// of this structure in the PcdCpuS3DataAddress PCD. This is a generic/simple
+// version of this module. It does not provide a machine check handler or CPU
+// register initialization tables for ACPI S3 resume. It also only supports the
+// number of CPUs reported by the MP Services Protocol, so this module does not
+// support hot plug CPUs. This module can be copied into a CPU specific package
+// and customized if these additional features are required.
+//
+// Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+//
+// Copyright (c) 2015, Red Hat, Inc.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT
+#language en-US
+"ACPI CPU Data initialization module"
+
+#string STR_MODULE_DESCRIPTION
+#language en-US
+"This module initializes the ACPI_CPU_DATA structure and registers the address "
+"of this structure in the PcdCpuS3DataAddress PCD. This is a generic/simple "
+"version of this module. It does not provide a machine check handler or CPU "
+"register initialization tables for ACPI S3 resume. It also only supports the "
+"number of CPUs reported by the MP Services Protocol, so this module does not "
+"support hot plug CPUs. This module can be copied into a CPU specific package "
+"and customized if these additional features are required."
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxeExtra.uni b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxeExtra.uni new file mode 100644 index 00000000..42653f20 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxeExtra.uni @@ -0,0 +1,14 @@ +// /** @file
+// CpuS3DataDxe Localized Strings and Content
+//
+// Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+//
+// Copyright (c) 2015, Red Hat, Inc.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME #language en-US "CpuS3DataDxe module"
+
+
|