On Wed, 26 Feb 2020 at 23:12, Laszlo Ersek <ler...@redhat.com> wrote: > > With "PcdCpuSmmEnableBspElection" set to FALSE, PiSmmCpuDxeSmm always > considers the processor with index 0 to be the SMM Monarch (a.k.a. the SMM > BSP). The SMM Monarch handles the SMI for real, while the other CPUs wait > in their SMM loops. > > In a subsequent patch, we want to set "PcdCpuHotPlugSupport" to TRUE. For > that, PiCpuSmmEntry() [UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c] forces > us with an ASSERT() to set "PcdCpuSmmEnableBspElection" to TRUE as well. > To satisfy that expectation, we can simply remove our current > "PcdCpuSmmEnableBspElection|FALSE" setting, and inherit the default TRUE > value from "UefiCpuPkg.dec". > > This causes "mSmmMpSyncData->BspIndex" in PiSmmCpuDxeSmm to lose its > static zero value (standing for CPU#0); instead it becomes (-1) in > general, and the SMM Monarch is elected anew on every SMI. > > The default SMM Monarch Election is basically a race -- whichever CPU can > flip "mSmmMpSyncData->BspIndex" from (-1) to its own index, becomes king, > for handling that SMI. Refer to SmiRendezvous() > [UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c]. > > I consider this non-determinism less than ideal on QEMU/KVM; it would be > nice to stick with a "mostly permanent" SMM Monarch even with the Election > enabled. We can do that by implementing the PlatformSmmBspElection() API > in the SmmCpuPlatformHookLibQemu instance: > > The IA32 APIC Base MSR can be read on each CPU concurrently, and it will > report the BSP bit as set only on the current Boot Service Processor. QEMU > marks CPU#0 as the BSP, by default. > > Elect the current BSP, as reported by QEMU, for the SMM Monarch role. > > (Note that the QEMU commit history is not entirely consistent on whether > QEMU/KVM may mark a CPU with nonzero index as the BSP: > > - At tag v4.2.0, "target/i386/cpu.c" has a comment saying "We hard-wire > the BSP to the first CPU". This comment goes back to commit 6cb2996cef5e > ("x86: Extend validity of bsp_to_cpu", 2010-03-04). > > - Compare commit 9cb11fd7539b ("target-i386: clear bsp bit when > designating bsp", 2015-04-02) though, especially considering KVM. > > Either way, this OvmfPkg patch is *not* dependent on CPU index 0; it just > takes the race on every SMI out of the game.) > > One benefit of using a "mostly permanent" SMM Monarch / BSP is that we can > continue testing the SMM CPU synchronization by deterministically entering > the firmware on the BSP, vs. on an AP, from Linux guests: > > $ time taskset -c 0 efibootmgr > $ time taskset -c 1 efibootmgr > > (See > <https://github.com/tianocore/tianocore.github.io/wiki/Testing-SMM-with-QEMU,-KVM-and-libvirt#uefi-variable-access-test>.) > > Cc: Ard Biesheuvel <ard.biesheu...@linaro.org> > Cc: Igor Mammedov <imamm...@redhat.com> > Cc: Jiewen Yao <jiewen....@intel.com> > Cc: Jordan Justen <jordan.l.jus...@intel.com> > Cc: Michael Kinney <michael.d.kin...@intel.com> > Cc: Philippe Mathieu-Daudé <phi...@redhat.com> > Suggested-by: Igor Mammedov <imamm...@redhat.com> > Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1512#c5 > Signed-off-by: Laszlo Ersek <ler...@redhat.com> > Acked-by: Ard Biesheuvel <ard.biesheu...@linaro.org>
Reviewed-by: Ard Biesheuvel <ard.biesheu...@linaro.org> (I checked the code below versus the intent below, which looks to me to be in agreement.) > --- > > Notes: > v2: > > - Pick up Ard's Acked-by, which is conditional on approval from Intel > reviewers on Cc. (I'd like to save Ard the churn of re-acking > unmodified patches.) > > OvmfPkg/OvmfPkgIa32.dsc | 1 - > OvmfPkg/OvmfPkgIa32X64.dsc | 1 - > OvmfPkg/OvmfPkgX64.dsc | 1 - > OvmfPkg/Library/SmmCpuPlatformHookLibQemu/SmmCpuPlatformHookLibQemu.inf | 3 > +++ > OvmfPkg/Library/SmmCpuPlatformHookLibQemu/SmmCpuPlatformHookLibQemu.c | 9 > ++++++++- > 5 files changed, 11 insertions(+), 4 deletions(-) > > diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc > index 813995fefad8..60d8af185b9c 100644 > --- a/OvmfPkg/OvmfPkgIa32.dsc > +++ b/OvmfPkg/OvmfPkgIa32.dsc > @@ -414,45 +414,44 @@ [LibraryClasses.common.SMM_CORE] > !endif > PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf > > > ################################################################################ > # > # Pcd Section - list of all EDK II PCD Entries defined by this Platform. > # > > ################################################################################ > [PcdsFeatureFlag] > gEfiMdeModulePkgTokenSpaceGuid.PcdHiiOsRuntimeSupport|FALSE > gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE > gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE > gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress|FALSE > gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE > gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE > gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE > gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|TRUE > !ifdef $(CSM_ENABLE) > gUefiOvmfPkgTokenSpaceGuid.PcdCsmEnable|TRUE > !endif > !if $(SMM_REQUIRE) == TRUE > gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire|TRUE > - gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection|FALSE > gEfiMdeModulePkgTokenSpaceGuid.PcdEnableVariableRuntimeCache|FALSE > !endif > > [PcdsFixedAtBuild] > gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1 > gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE > gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10 > !if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048) > gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000 > gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800 > !if $(NETWORK_TLS_ENABLE) == FALSE > # match PcdFlashNvStorageVariableSize purely for convenience > gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0xe000 > !endif > !endif > !if $(FD_SIZE_IN_KB) == 4096 > gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x8400 > gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x8400 > !if $(NETWORK_TLS_ENABLE) == FALSE > # match PcdFlashNvStorageVariableSize purely for convenience > gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x40000 > !endif > diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc > index a256c7084a7e..be6bc7bd88a7 100644 > --- a/OvmfPkg/OvmfPkgIa32X64.dsc > +++ b/OvmfPkg/OvmfPkgIa32X64.dsc > @@ -419,45 +419,44 @@ [LibraryClasses.common.SMM_CORE] > !endif > PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf > > > ################################################################################ > # > # Pcd Section - list of all EDK II PCD Entries defined by this Platform. > # > > ################################################################################ > [PcdsFeatureFlag] > gEfiMdeModulePkgTokenSpaceGuid.PcdHiiOsRuntimeSupport|FALSE > gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE > gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE > gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress|FALSE > gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|TRUE > gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE > gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE > gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|TRUE > !ifdef $(CSM_ENABLE) > gUefiOvmfPkgTokenSpaceGuid.PcdCsmEnable|TRUE > !endif > !if $(SMM_REQUIRE) == TRUE > gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire|TRUE > - gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection|FALSE > gEfiMdeModulePkgTokenSpaceGuid.PcdEnableVariableRuntimeCache|FALSE > !endif > > [PcdsFixedAtBuild] > gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1 > gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE > gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10 > !if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048) > gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000 > gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800 > !if $(NETWORK_TLS_ENABLE) == FALSE > # match PcdFlashNvStorageVariableSize purely for convenience > gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0xe000 > !endif > !endif > !if $(FD_SIZE_IN_KB) == 4096 > gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x8400 > gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x8400 > !if $(NETWORK_TLS_ENABLE) == FALSE > # match PcdFlashNvStorageVariableSize purely for convenience > gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x40000 > !endif > diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc > index 78079b9f8e13..e258c474b60d 100644 > --- a/OvmfPkg/OvmfPkgX64.dsc > +++ b/OvmfPkg/OvmfPkgX64.dsc > @@ -419,45 +419,44 @@ [LibraryClasses.common.SMM_CORE] > !endif > PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf > > > ################################################################################ > # > # Pcd Section - list of all EDK II PCD Entries defined by this Platform. > # > > ################################################################################ > [PcdsFeatureFlag] > gEfiMdeModulePkgTokenSpaceGuid.PcdHiiOsRuntimeSupport|FALSE > gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE > gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE > gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress|FALSE > gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE > gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE > gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE > gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|TRUE > !ifdef $(CSM_ENABLE) > gUefiOvmfPkgTokenSpaceGuid.PcdCsmEnable|TRUE > !endif > !if $(SMM_REQUIRE) == TRUE > gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire|TRUE > - gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection|FALSE > gEfiMdeModulePkgTokenSpaceGuid.PcdEnableVariableRuntimeCache|FALSE > !endif > > [PcdsFixedAtBuild] > gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1 > gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE > gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10 > !if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048) > gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000 > gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800 > !if $(NETWORK_TLS_ENABLE) == FALSE > # match PcdFlashNvStorageVariableSize purely for convenience > gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0xe000 > !endif > !endif > !if $(FD_SIZE_IN_KB) == 4096 > gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x8400 > gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x8400 > !if $(NETWORK_TLS_ENABLE) == FALSE > # match PcdFlashNvStorageVariableSize purely for convenience > gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x40000 > !endif > diff --git > a/OvmfPkg/Library/SmmCpuPlatformHookLibQemu/SmmCpuPlatformHookLibQemu.inf > b/OvmfPkg/Library/SmmCpuPlatformHookLibQemu/SmmCpuPlatformHookLibQemu.inf > index 82edeca3d12d..413c56fce6e1 100644 > --- a/OvmfPkg/Library/SmmCpuPlatformHookLibQemu/SmmCpuPlatformHookLibQemu.inf > +++ b/OvmfPkg/Library/SmmCpuPlatformHookLibQemu/SmmCpuPlatformHookLibQemu.inf > @@ -8,22 +8,25 @@ > > [Defines] > INF_VERSION = 1.29 > BASE_NAME = SmmCpuPlatformHookLibQemu > FILE_GUID = 154D6D26-54B8-45BC-BA3A-CBAA20C02A6A > MODULE_TYPE = DXE_DRIVER > VERSION_STRING = 1.0 > LIBRARY_CLASS = SmmCpuPlatformHookLib > > # > # The following information is for reference only and not required by the > build > # tools. > # > # VALID_ARCHITECTURES = IA32 X64 > # > > [Sources] > SmmCpuPlatformHookLibQemu.c > > [Packages] > MdePkg/MdePkg.dec > UefiCpuPkg/UefiCpuPkg.dec > + > +[LibraryClasses] > + BaseLib > diff --git > a/OvmfPkg/Library/SmmCpuPlatformHookLibQemu/SmmCpuPlatformHookLibQemu.c > b/OvmfPkg/Library/SmmCpuPlatformHookLibQemu/SmmCpuPlatformHookLibQemu.c > index 257e1d399cc6..c88a95c6deff 100644 > --- a/OvmfPkg/Library/SmmCpuPlatformHookLibQemu/SmmCpuPlatformHookLibQemu.c > +++ b/OvmfPkg/Library/SmmCpuPlatformHookLibQemu/SmmCpuPlatformHookLibQemu.c > @@ -1,31 +1,34 @@ > /** @file > SMM CPU Platform Hook library instance for QEMU. > > Copyright (c) 2020, Red Hat, Inc. > Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR> > SPDX-License-Identifier: BSD-2-Clause-Patent > > **/ > +#include <Library/BaseLib.h> // AsmReadMsr64() > #include <PiSmm.h> > +#include <Register/Intel/ArchitecturalMsr.h> // MSR_IA32_APIC_BASE_REGISTER > + > #include <Library/SmmCpuPlatformHookLib.h> > > /** > Checks if platform produces a valid SMI. > > This function checks if platform produces a valid SMI. This function is > called at SMM entry to detect if this is a spurious SMI. This function > must be implemented in an MP safe way because it is called by multiple CPU > threads. > > @retval TRUE There is a valid SMI > @retval FALSE There is no valid SMI > > **/ > BOOLEAN > EFIAPI > PlatformValidSmi ( > VOID > ) > { > return TRUE; > } > @@ -56,45 +59,49 @@ ClearTopLevelSmiStatus ( > > @param IsBsp Output parameter. TRUE: the CPU this function > executes on is elected to be the SMM BSP. FALSE: > the CPU this function executes on is to be SMM > AP. > > @retval EFI_SUCCESS The function executes successfully. > @retval EFI_NOT_READY The function does not determine whether this CPU > should be BSP or AP. This may occur if hardware > init sequence to enable the determination is yet > to > be done, or the function chooses not to do BSP > election and will let SMM CPU driver to use its > default BSP election process. > @retval EFI_DEVICE_ERROR The function cannot determine whether this CPU > should be BSP or AP due to hardware error. > > **/ > EFI_STATUS > EFIAPI > PlatformSmmBspElection ( > OUT BOOLEAN *IsBsp > ) > { > - return EFI_NOT_READY; > + MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr; > + > + ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE); > + *IsBsp = (BOOLEAN)(ApicBaseMsr.Bits.BSP == 1); > + return EFI_SUCCESS; > } > > /** > Get platform page table attribute. > > This function gets page table attribute of platform. > > @param Address Input parameter. Obtain the page table entries > attribute on this address. > @param PageSize Output parameter. The size of the page. > @param NumOfPages Output parameter. Number of page. > @param PageAttribute Output parameter. Paging Attributes (WB, UC, etc). > > @retval EFI_SUCCESS The platform page table attribute from the address > is determined. > @retval EFI_UNSUPPORTED The platform does not support getting page table > attribute for the address. > > **/ > EFI_STATUS > EFIAPI > GetPlatformPageTableAttribute ( > -- > 2.19.1.3.g30247aa5d201 > > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#55191): https://edk2.groups.io/g/devel/message/55191 Mute This Topic: https://groups.io/mt/71575177/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-