Laszlo, Thanks for the feedback and the testing!
I have made the updates you suggested in this series except for removing the lines that initialize the RegisterTable fields. I left those there to make it easier for CPU/Platform package that needs to use this module as a starting point for a custom version. This series has been committed, so it is now available for use with your OVMF SMM v5 series. Mike > -----Original Message----- > From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Laszlo > Ersek > Sent: Wednesday, November 25, 2015 3:04 AM > To: Kinney, Michael D <michael.d.kin...@intel.com>; edk2-de...@ml01.01.org > Cc: Yao, Jiewen <jiewen....@intel.com>; Fan, Jeff <jeff....@intel.com> > Subject: Re: [edk2] [PATCH v2 2/2] UefiCpuPkg/CpuS3DataDxe: Add module to > initialize ACPI_CPU_DATA for S3 > > On 11/25/15 00:47, Michael Kinney wrote: > > 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. > > > > This patch series is in response to the OvmfPkg patch series from > > Laszlo Ersek that enables SMM on OVMF. The v4 version of the patch > > series from Laszlo includes an OVMF specific CPU module to initialize > > the ACPI_CPU_DATA structure. > > > > This proposed patch series replaces the patches listed below. > > > > [PATCH v4 27/41] OvmfPkg: > > add skeleton QuarkPort/CpuS3DataDxe > > > > [PATCH v4 28/41] OvmfPkg: > > QuarkPort/CpuS3DataDxe: fill in ACPI_CPU_DATA.StartupVector > > > > [PATCH v4 29/41] OvmfPkg: > > QuarkPort/CpuS3DataDxe: handle IDT, GDT and MCE in ACPI_CPU_DATA > > > > [PATCH v4 30/41] OvmfPkg: > > QuarkPort/CpuS3DataDxe: handle StackAddress and StackSize > > > > [PATCH v4 31/41] OvmfPkg: > > import CpuConfigLib header from Quark_EDKII_v1.1.0/IA32FamilyCpuBasePkg > > > > [PATCH v4 32/41] OvmfPkg: > > QuarkPort/CpuS3DataDxe: fill in ACPI_CPU_DATA.NumberOfCpus > > > > [PATCH v4 33/41] OvmfPkg: > > QuarkPort/CpuS3DataDxe: fill in ACPI_CPU_DATA.MtrrTable > > > > [PATCH v4 34/41] OvmfPkg: > > QuarkPort/CpuS3DataDxe: handle register tables in ACPI_CPU_DATA > > > > [PATCH v4 35/41] OvmfPkg: > > port CpuS3DataDxe to X64 > > > > [PATCH v4 36/41] OvmfPkg: > > build QuarkPort/CpuS3DataDxe for -D SMM_REQUIRE > > > > Cc: Laszlo Ersek <ler...@redhat.com> > > Cc: "Yao, Jiewen" <jiewen....@intel.com> > > Cc: "Fan, Jeff" <jeff....@intel.com> > > Contributed-under: TianoCore Contribution Agreement 1.0 > > Signed-off-by: Michael Kinney <michael.d.kin...@intel.com> > > --- > > UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c | 271 > > +++++++++++++++++++++++++++++++ > > UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf | 64 ++++++++ > > UefiCpuPkg/UefiCpuPkg.dsc | 1 + > > 3 files changed, 336 insertions(+) > > create mode 100644 UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c > > create mode 100644 UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf > > (1) The commit message looks great, thank you very much for the references. > > A small request: please mark, under "port CpuS3DataDxe to X64" (i.e., > [PATCH v4 35/41]), that that patch was originally authored by Paolo Bonzini. > > There's no need to submit a v3 of this series just because of this; it > can be fixed up before committing the patch. > > > > > diff --git a/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c > > b/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c > > new file mode 100644 > > index 0000000..7cf923d > > --- /dev/null > > +++ b/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c > > @@ -0,0 +1,271 @@ > > +/** @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 - 2015, Intel Corporation. All rights reserved.<BR> > > +Copyright (c) 2015, Red Hat, Inc. > > + > > +This program and the accompanying materials > > +are licensed and made available under the terms and conditions of the BSD > > License > > +which accompanies this distribution. The full text of the license may be > > found at > > +http://opensource.org/licenses/bsd-license.php > > + > > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR > > IMPLIED. > > + > > +**/ > > + > > +#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 <Protocol/MpService.h> > > +#include <Guid/EventGroup.h> > > + > > +// > > +// Data structure used to allocate ACPI_CPU_DATA and its supporting > > structures > > +// > > +typedef struct { > > + ACPI_CPU_DATA AcpuCpuData; > > (2) Please fix the typo in the name of this field: it should be > Acp[i]CpuData. Apologies for not noticing it in v1. > > No need to submit a v3 just because of this; can be fixed up on commit. > > > + MTRR_SETTINGS MtrrTable; > > + IA32_DESCRIPTOR GdtrProfile; > > + IA32_DESCRIPTOR IdtrProfile; > > +} ACPI_CPU_DATA_EX; > > + > > +/** > > + Allocate EfiACPIMemoryNVS below 4G memory address. > > + > > + This function allocates EfiACPIMemoryNVS below 4G memory address. > > + > > + @param[in] Size Size of memory to allocate. > > + > > + @return Allocated address for output. > > + > > +**/ > > +VOID * > > +AllocateAcpiNvsMemoryBelow4G ( > > + IN UINTN Size > > + ) > > +{ > > + EFI_PHYSICAL_ADDRESS Address; > > + EFI_STATUS Status; > > + VOID *Buffer; > > + > > + Address = BASE_4GB - 1; > > + Status = gBS->AllocatePages ( > > + AllocateMaxAddress, > > + EfiACPIMemoryNVS, > > + EFI_SIZE_TO_PAGES (Size), > > + &Address > > + ); > > + if (EFI_ERROR (Status)) { > > + return NULL; > > + } > > + > > + Buffer = (VOID *)(UINTN)Address; > > + ZeroMem (Buffer, Size); > > + > > + return Buffer; > > +} > > + > > +/** > > + Callback function executed when the EndOfDxe event group is signaled. > > + > > + We delay 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 > > +SaveMtrrsOnEndOfDxe ( > > + IN EFI_EVENT Event, > > + OUT VOID *Context > > + ) > > +{ > > + DEBUG ((EFI_D_VERBOSE, "%a\n", __FUNCTION__)); > > + MtrrGetAllMtrrs (Context); > > + > > + // > > + // 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. > > (3) I think the last sentence above should go like: > > [] PcdCpuS3DataAddress is set to the address that ACPI_CPU_DATA is > allocated [at]. > > Can be fixed up at commit time. > > > + > > + @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 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 TableSize; > > + CPU_REGISTER_TABLE *RegisterTable; > > + UINTN Index; > > + EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; > > + UINTN GdtSize; > > + UINTN IdtSize; > > + VOID *Gdt; > > + VOID *Idt; > > + EFI_EVENT Event; > > + > > + // > > + // Allocate ACPI NVS memory below 4G memory for use on ACPI S3 resume. > > + // > > + AcpiCpuDataEx = AllocateAcpiNvsMemoryBelow4G (sizeof (ACPI_CPU_DATA_EX)); > > + ASSERT (AcpiCpuDataEx != NULL); > > + AcpiCpuData = &AcpiCpuDataEx->AcpuCpuData; > > + > > + // > > + // Get MP Services Protocol > > + // > > + Status = gBS->LocateProtocol ( > > + &gEfiMpServiceProtocolGuid, > > + NULL, > > + (VOID **)&MpServices > > + ); > > + ASSERT_EFI_ERROR (Status); > > + > > + // > > + // If there are 1 or more APs, then allocate a 4KB reserved page below > > 1MB > > + // > > (4) I think this comment should be dropped now. The code is correct; the > comment is stale. Can be fixed up when committing the patch. > > > + AcpiCpuData->StartupVector = BASE_1MB - 1; > > + Status = gBS->AllocatePages ( > > + AllocateMaxAddress, > > + EfiReservedMemoryType, > > + 1, > > + &AcpiCpuData->StartupVector > > + ); > > (5) The indentation of the function arguments and the closing paren > doesn't seem right. Can be fixed up on commit. > > > + 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 > > + // > > + Stack = AllocateAcpiNvsMemoryBelow4G (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); > > Turns out you have removed the casts for v2 -- great, thanks! > > > + > > + // > > + // Allocate GDT and IDT in ACPI NVS and copy current GDT and IDT contents > > + // > > + GdtSize = AcpiCpuDataEx->GdtrProfile.Limit + 1; > > + IdtSize = AcpiCpuDataEx->IdtrProfile.Limit + 1; > > + Gdt = AllocateAcpiNvsMemoryBelow4G (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; > > + > > + // > > + // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable > > for all CPUs > > + // > > + TableSize = 2 * NumberOfCpus * sizeof (CPU_REGISTER_TABLE); > > + RegisterTable = (CPU_REGISTER_TABLE *)AllocateAcpiNvsMemoryBelow4G > > (TableSize); > > + ASSERT (RegisterTable != NULL); > > + for (Index = 0; Index < NumberOfCpus; Index++) { > > + Status = MpServices->GetProcessorInfo ( > > + MpServices, > > + Index, > > + &ProcessorInfoBuffer > > + ); > > + ASSERT_EFI_ERROR (Status); > > + > > + RegisterTable[Index].InitialApicId = > > (UINT32)ProcessorInfoBuffer.ProcessorId; > > + RegisterTable[Index].TableLength = 0; > > + RegisterTable[Index].AllocatedSize = 0; > > + RegisterTable[Index].RegisterTableEntry = NULL; > > + > > + RegisterTable[NumberOfCpus + Index].InitialApicId = > > (UINT32)ProcessorInfoBuffer.ProcessorId; > > + RegisterTable[NumberOfCpus + Index].TableLength = 0; > > + RegisterTable[NumberOfCpus + Index].AllocatedSize = 0; > > + RegisterTable[NumberOfCpus + Index].RegisterTableEntry = NULL; > > + } > > (6) Because AllocateAcpiNvsMemoryBelow4G() zero-fills the allocated > buffer, all field assignments except InitialApicId could be dropped, for > further simplification. > > Not necessary to do, and if you opt to drop the zero / NULL assignments, > that can be done on commit. > > ... On the other hand, if a different package needs to customize this > module, they will probably appreciate the field assignments (the left > hand sides anyway) already being spelled out -- so I guess this could > actually prove helpful down the road. > > > With the above minor tweaks (of which (6) is definitely optional): > > Reviewed-by: Laszlo Ersek <ler...@redhat.com> > > In addition, I rebased my series on top of this one. I tested S3 with > 32-bit and 64-bit Fedora guests, and also with a 64-bit Windows 8.1 > guest (all using 4 VCPUs and running on KVM). Everything worked fine. > > Series > Tested-by: Laszlo Ersek <ler...@redhat.com> > > I'm ready to post my version 5 series soon after this one gets committed. > > Thank you! > Laszlo > > > > + AcpiCpuData->RegisterTable = > > (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTable; > > + AcpiCpuData->PreSmmInitRegisterTable = > > (EFI_PHYSICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus); > > + > > + // > > + // 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 saves MTRRs for ACPI_CPU_DATA > > + // > > + Status = gBS->CreateEventEx ( > > + EVT_NOTIFY_SIGNAL, > > + TPL_CALLBACK, > > + SaveMtrrsOnEndOfDxe, > > + &AcpiCpuDataEx->MtrrTable, > > + &gEfiEndOfDxeEventGroupGuid, > > + &Event > > + ); > > + ASSERT_EFI_ERROR (Status); > > + > > + return EFI_SUCCESS; > > +} > > diff --git a/UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf > > b/UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf > > new file mode 100644 > > index 0000000..2ef16a7 > > --- /dev/null > > +++ b/UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf > > @@ -0,0 +1,64 @@ > > +## @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-2015, Intel Corporation. All rights reserved.<BR> > > +# Copyright (c) 2015, Red Hat, Inc. > > +# > > +# This program and the accompanying materials > > +# are licensed and made available under the terms and conditions of the > > BSD License > > +# which accompanies this distribution. The full text of the license may > > be found at > > +# http://opensource.org/licenses/bsd-license.php > > +# > > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR > > IMPLIED. > > +# > > +## > > + > > +[Defines] > > + INF_VERSION = 0x00010005 > > + BASE_NAME = CpuS3DataDxe > > + 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 > > + UefiCpuPkg/UefiCpuPkg.dec > > + > > +[LibraryClasses] > > + UefiDriverEntryPoint > > + UefiBootServicesTableLib > > + BaseMemoryLib > > + DebugLib > > + BaseLib > > + MtrrLib > > + > > +[Guids] > > + gEfiEndOfDxeEventGroupGuid ## CONSUMES > > + > > +[Protocols] > > + gEfiMpServiceProtocolGuid ## CONSUMES > > + > > +[Pcd] > > + gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES > > + gUefiCpuPkgTokenSpaceGuid.PcdCpuS3DataAddress ## PRODUCES > > + > > +[Depex] > > + gEfiMpServiceProtocolGuid > > diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc > > index 756645f..4061050 100644 > > --- a/UefiCpuPkg/UefiCpuPkg.dsc > > +++ b/UefiCpuPkg/UefiCpuPkg.dsc > > @@ -101,6 +101,7 @@ > > UefiCpuPkg/CpuDxe/CpuDxe.inf > > UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf > > UefiCpuPkg/CpuMpPei/CpuMpPei.inf > > + UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf > > UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf > > UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf > > UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf > > > > _______________________________________________ > edk2-devel mailing list > edk2-devel@lists.01.org > https://lists.01.org/mailman/listinfo/edk2-devel _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel