From: Laszlo Ersek <lersek@redhat.com>
To: Jordan Justen <jordan.l.justen@intel.com>
Cc: edk2-devel-01 <edk2-devel@ml01.01.org>
Subject: Re: [PATCH v3 2/2] OvmfPkg/SmmControl2Dxe: select broadcast SMI if available
Date: Tue, 7 Feb 2017 12:32:13 +0100 [thread overview]
Message-ID: <934805ad-1e5a-ce9f-263a-fb72b4d0628e@redhat.com> (raw)
In-Reply-To: <148646137918.13729.17315316362028292158@jljusten-ivb>
On 02/07/17 10:56, Jordan Justen wrote:
> On 2017-01-31 03:02:21, Laszlo Ersek wrote:
>> When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an
>> SMI only on the VCPU that is writing the port.
>
> I'm still annoyed that qemu didn't follow chipset hardware in handling
> the b2 port. I know this is long passed any possibility of doing
> anything about it, but it is also my last chance to complain. :)
It was difficult to come up with a QEMU design that everyone was willing
to accept (it was a tough community effort, really -- sort of walking a
fine line), and then getting the QEMU patches right (as defined by QEMU
maintainers) was again super difficult to me, despite the patches' small
size.
So yes, I can (quite selfishly :)) agree that "just doing the broadcast"
would have been better.
I'm much relieved that the feature seems to be converging finally, on
both sides.
>
>> This has exposed corner
>> cases and strange behavior with edk2 code, which generally expects a
>> software SMI to affect all CPUs at once. We've experienced instability
>> despite the fact that OVMF sets PcdCpuSmmApSyncTimeout and
>> PcdCpuSmmSyncMode differently from the UefiCpuPkg defaults, such that they
>> match QEMU's unicast SMIs better. (Refer to edk2 commits 9b1e378811ff and
>> bb0f18b0bce6.)
>>
>> Using the new fw_cfg-based SMI feature negotiation in QEMU (see commits
>> 50de920b372b "hw/isa/lpc_ich9: add SMI feature negotiation via fw_cfg" and
>> 5ce45c7a2b15 "hw/isa/lpc_ich9: add broadcast SMI feature"), we can ask
>> QEMU to broadcast SMIs. Extensive testing from earlier proves that
>> broadcast SMIs are only reliable if we use the UefiCpuPkg defaults for the
>> above PCDs. With those settings however, the broadcast is very reliable --
>> the most reliable configuration encountered thus far.
>
> Given my experience with SMI's we could see more unexpected corner
> cases. It seems that SMM is all corner cases. :)
Processor mode changes, multiprocessing, and security impact. What could
go wrong! :)
>
> Series Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
\o/ Hooray! Thank you!
Pushed as 7c609a144b66..a316d7ac91d3.
Cheers!
Laszlo
>
>>
>> Therefore negotiate broadcast SMIs with QEMU, and if the negotiation is
>> successful, dynamically revert the PCDs to the UefiCpuPkg defaults.
>>
>> Setting the PCDs in this module is safe:
>>
>> - only PiSmmCpuDxeSmm consumes them,
>>
>> - PiSmmCpuDxeSmm is a DXE_SMM_DRIVER, launched by the SMM_CORE
>> (MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf),
>>
>> - the SMM_CORE is launched by the SMM IPL runtime DXE driver
>> (MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf),
>>
>> - the SMM IPL has a DEPEX on EFI_SMM_CONTROL2_PROTOCOL,
>>
>> - OvmfPkg/SmmControl2Dxe produces that protocol.
>>
>> The end result is that PiSmmCpuDxeSmm cannot be dispatched before
>> SmmControl2Dxe installs EFI_SMM_CONTROL2_PROTOCOL and returns from its
>> entry point. Hence we can set the PCD's consumed by PiSmmCpuDxeSmm in
>> SmmControl2Dxe.
>>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=230
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Signed-off-by: Laszlo Ersek <lersek@redhat.com>
>> ---
>>
>> Notes:
>> v3:
>> - replace the ICH9_APM_STS-based feature negotiation with the new
>> writeable fw_cfg kind
>>
>> OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf | 8 +
>> OvmfPkg/SmmControl2Dxe/SmiFeatures.h | 49 +++
>> OvmfPkg/SmmControl2Dxe/SmiFeatures.c | 324 ++++++++++++++++++++
>> OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.c | 21 ++
>> 4 files changed, 402 insertions(+)
>>
>> diff --git a/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf b/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf
>> index 0e9f98c2871c..31c80bd4448c 100644
>> --- a/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf
>> +++ b/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf
>> @@ -35,32 +35,40 @@ [Defines]
>> #
>> # The following information is for reference only and not required by the build tools.
>> #
>> # VALID_ARCHITECTURES = IA32 X64
>> #
>>
>> [Sources]
>> + SmiFeatures.h
>> + SmiFeatures.c
>> SmmControl2Dxe.c
>>
>> [Packages]
>> MdePkg/MdePkg.dec
>> OvmfPkg/OvmfPkg.dec
>> + UefiCpuPkg/UefiCpuPkg.dec
>>
>> [LibraryClasses]
>> BaseLib
>> DebugLib
>> IoLib
>> + MemoryAllocationLib
>> PcdLib
>> PciLib
>> QemuFwCfgLib
>> UefiBootServicesTableLib
>> UefiDriverEntryPoint
>>
>> [Protocols]
>> gEfiS3SaveStateProtocolGuid ## SOMETIMES_CONSUMES
>> gEfiSmmControl2ProtocolGuid ## PRODUCES
>>
>> +[Pcd]
>> + gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmApSyncTimeout ## SOMETIMES_PRODUCES
>> + gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmSyncMode ## SOMETIMES_PRODUCES
>> +
>> [FeaturePcd]
>> gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
>>
>> [Depex]
>> TRUE
>> diff --git a/OvmfPkg/SmmControl2Dxe/SmiFeatures.h b/OvmfPkg/SmmControl2Dxe/SmiFeatures.h
>> new file mode 100644
>> index 000000000000..9d5f1dbcb57e
>> --- /dev/null
>> +++ b/OvmfPkg/SmmControl2Dxe/SmiFeatures.h
>> @@ -0,0 +1,49 @@
>> +/**@file
>> + Negotiate SMI features with QEMU, and configure UefiCpuPkg/PiSmmCpuDxeSmm
>> + accordingly.
>> +
>> + Copyright (C) 2016-2017, 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.
>> +**/
>> +
>> +#ifndef __SMI_FEATURES_H__
>> +#define __SMI_FEATURES_H__
>> +
>> +#include <Protocol/S3SaveState.h>
>> +
>> +/**
>> + Negotiate SMI features with QEMU.
>> +
>> + @retval FALSE If SMI feature negotiation is not supported by QEMU. This is
>> + not an error, it just means that SaveSmiFeatures() should not
>> + be called.
>> +
>> + @retval TRUE SMI feature negotiation is supported, and it has completed
>> + successfully as well. (Failure to negotiate is a fatal error
>> + and the function never returns in that case.)
>> +**/
>> +BOOLEAN
>> +NegotiateSmiFeatures (
>> + VOID
>> + );
>> +
>> +/**
>> + Append a boot script fragment that will re-select the previously negotiated
>> + SMI features during S3 resume.
>> +
>> + @param[in] S3SaveState The EFI_S3_SAVE_STATE_PROTOCOL instance to append to
>> + the S3 boot script with.
>> +**/
>> +VOID
>> +SaveSmiFeatures (
>> + IN EFI_S3_SAVE_STATE_PROTOCOL *S3SaveState
>> + );
>> +
>> +#endif
>> diff --git a/OvmfPkg/SmmControl2Dxe/SmiFeatures.c b/OvmfPkg/SmmControl2Dxe/SmiFeatures.c
>> new file mode 100644
>> index 000000000000..e070969065c0
>> --- /dev/null
>> +++ b/OvmfPkg/SmmControl2Dxe/SmiFeatures.c
>> @@ -0,0 +1,324 @@
>> +/**@file
>> + Negotiate SMI features with QEMU, and configure UefiCpuPkg/PiSmmCpuDxeSmm
>> + accordingly.
>> +
>> + Copyright (C) 2016-2017, 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 <Library/BaseLib.h>
>> +#include <Library/DebugLib.h>
>> +#include <Library/MemoryAllocationLib.h>
>> +#include <Library/PcdLib.h>
>> +#include <Library/QemuFwCfgLib.h>
>> +
>> +#include "SmiFeatures.h"
>> +
>> +//
>> +// The following bit value stands for "broadcast SMI" in the
>> +// "etc/smi/supported-features" and "etc/smi/requested-features" fw_cfg files.
>> +//
>> +#define ICH9_LPC_SMI_F_BROADCAST BIT0
>> +
>> +//
>> +// Provides a scratch buffer (allocated in EfiReservedMemoryType type memory)
>> +// for the S3 boot script fragment to write to and read from. The buffer
>> +// captures a combined fw_cfg item selection + write command using the DMA
>> +// access method. Note that we don't trust the runtime OS to preserve the
>> +// contents of the buffer, the boot script will first rewrite it.
>> +//
>> +#pragma pack (1)
>> +typedef struct {
>> + FW_CFG_DMA_ACCESS Access;
>> + UINT64 Features;
>> +} SCRATCH_BUFFER;
>> +#pragma pack ()
>> +
>> +//
>> +// These carry the selector keys of the "etc/smi/requested-features" and
>> +// "etc/smi/features-ok" fw_cfg files from NegotiateSmiFeatures() to
>> +// SaveSmiFeatures().
>> +//
>> +STATIC FIRMWARE_CONFIG_ITEM mRequestedFeaturesItem;
>> +STATIC FIRMWARE_CONFIG_ITEM mFeaturesOkItem;
>> +
>> +//
>> +// Carries the negotiated SMI features from NegotiateSmiFeatures() to
>> +// SaveSmiFeatures().
>> +//
>> +STATIC UINT64 mSmiFeatures;
>> +
>> +/**
>> + Negotiate SMI features with QEMU.
>> +
>> + @retval FALSE If SMI feature negotiation is not supported by QEMU. This is
>> + not an error, it just means that SaveSmiFeatures() should not
>> + be called.
>> +
>> + @retval TRUE SMI feature negotiation is supported, and it has completed
>> + successfully as well. (Failure to negotiate is a fatal error
>> + and the function never returns in that case.)
>> +**/
>> +BOOLEAN
>> +NegotiateSmiFeatures (
>> + VOID
>> + )
>> +{
>> + FIRMWARE_CONFIG_ITEM SupportedFeaturesItem;
>> + UINTN SupportedFeaturesSize;
>> + UINTN RequestedFeaturesSize;
>> + UINTN FeaturesOkSize;
>> +
>> + //
>> + // Look up the fw_cfg files used for feature negotiation. The selector keys
>> + // of "etc/smi/requested-features" and "etc/smi/features-ok" are saved
>> + // statically. If the files are missing, then QEMU doesn't support SMI
>> + // feature negotiation.
>> + //
>> + if (RETURN_ERROR (QemuFwCfgFindFile ("etc/smi/supported-features",
>> + &SupportedFeaturesItem, &SupportedFeaturesSize)) ||
>> + RETURN_ERROR (QemuFwCfgFindFile ("etc/smi/requested-features",
>> + &mRequestedFeaturesItem, &RequestedFeaturesSize)) ||
>> + RETURN_ERROR (QemuFwCfgFindFile ("etc/smi/features-ok",
>> + &mFeaturesOkItem, &FeaturesOkSize))) {
>> + DEBUG ((DEBUG_INFO, "%a: SMI feature negotiation unavailable\n",
>> + __FUNCTION__));
>> + return FALSE;
>> + }
>> +
>> + //
>> + // If the files are present but their sizes disagree with us, that's a fatal
>> + // error (we can't trust the behavior of SMIs either way).
>> + //
>> + if (SupportedFeaturesSize != sizeof mSmiFeatures ||
>> + RequestedFeaturesSize != sizeof mSmiFeatures ||
>> + FeaturesOkSize != sizeof (UINT8)) {
>> + DEBUG ((DEBUG_ERROR, "%a: size mismatch in feature negotiation\n",
>> + __FUNCTION__));
>> + goto FatalError;
>> + }
>> +
>> + //
>> + // Get the features supported by the host.
>> + //
>> + QemuFwCfgSelectItem (SupportedFeaturesItem);
>> + QemuFwCfgReadBytes (sizeof mSmiFeatures, &mSmiFeatures);
>> +
>> + //
>> + // We want broadcast SMI and nothing else.
>> + //
>> + mSmiFeatures &= ICH9_LPC_SMI_F_BROADCAST;
>> + QemuFwCfgSelectItem (mRequestedFeaturesItem);
>> + QemuFwCfgWriteBytes (sizeof mSmiFeatures, &mSmiFeatures);
>> +
>> + //
>> + // Invoke feature validation in QEMU. If the selection is accepted, the
>> + // features will be locked down. If the selection is rejected, feature
>> + // negotiation remains open; however we don't know what to do in that case,
>> + // so that's a fatal error.
>> + //
>> + QemuFwCfgSelectItem (mFeaturesOkItem);
>> + if (QemuFwCfgRead8 () != 1) {
>> + DEBUG ((DEBUG_ERROR, "%a: negotiation failed for feature bitmap 0x%Lx\n",
>> + __FUNCTION__, mSmiFeatures));
>> + goto FatalError;
>> + }
>> +
>> + if ((mSmiFeatures & ICH9_LPC_SMI_F_BROADCAST) == 0) {
>> + //
>> + // If we can't get broadcast SMIs from QEMU, that's acceptable too,
>> + // although not optimal.
>> + //
>> + DEBUG ((DEBUG_INFO, "%a: SMI broadcast unavailable\n", __FUNCTION__));
>> + } else {
>> + //
>> + // Configure the traditional AP sync / SMI delivery mode for
>> + // PiSmmCpuDxeSmm. Effectively, restore the UefiCpuPkg defaults, from which
>> + // the original QEMU behavior (i.e., unicast SMI) used to differ.
>> + //
>> + if (RETURN_ERROR (PcdSet64S (PcdCpuSmmApSyncTimeout, 1000000)) ||
>> + RETURN_ERROR (PcdSet8S (PcdCpuSmmSyncMode, 0x00))) {
>> + DEBUG ((DEBUG_ERROR, "%a: PiSmmCpuDxeSmm PCD configuration failed\n",
>> + __FUNCTION__));
>> + goto FatalError;
>> + }
>> + DEBUG ((DEBUG_INFO, "%a: using SMI broadcast\n", __FUNCTION__));
>> + }
>> +
>> + //
>> + // Negotiation successful (although we may not have gotten the optimal
>> + // feature set).
>> + //
>> + return TRUE;
>> +
>> +FatalError:
>> + ASSERT (FALSE);
>> + CpuDeadLoop ();
>> + //
>> + // Keep the compiler happy.
>> + //
>> + return FALSE;
>> +}
>> +
>> +/**
>> + Append a boot script fragment that will re-select the previously negotiated
>> + SMI features during S3 resume.
>> +
>> + @param[in] S3SaveState The EFI_S3_SAVE_STATE_PROTOCOL instance to append to
>> + the S3 boot script with.
>> +**/
>> +VOID
>> +SaveSmiFeatures (
>> + IN EFI_S3_SAVE_STATE_PROTOCOL *S3SaveState
>> + )
>> +{
>> + SCRATCH_BUFFER *ScratchBuffer;
>> + EFI_STATUS Status;
>> + UINT64 AccessAddress;
>> + UINT32 ControlPollData;
>> + UINT32 ControlPollMask;
>> + UINT16 FeaturesOkItemAsUint16;
>> + UINT8 FeaturesOkData;
>> + UINT8 FeaturesOkMask;
>> +
>> + ScratchBuffer = AllocateReservedPool (sizeof *ScratchBuffer);
>> + if (ScratchBuffer == NULL) {
>> + DEBUG ((DEBUG_ERROR, "%a: scratch buffer allocation failed\n",
>> + __FUNCTION__));
>> + goto FatalError;
>> + }
>> +
>> + //
>> + // Populate the scratch buffer with a select + write fw_cfg DMA command that
>> + // will write the negotiated feature bitmap into
>> + // "etc/smi/requested-features".
>> + //
>> + ScratchBuffer->Access.Control = SwapBytes32 (
>> + (UINT32)mRequestedFeaturesItem << 16 |
>> + FW_CFG_DMA_CTL_SELECT |
>> + FW_CFG_DMA_CTL_WRITE
>> + );
>> + ScratchBuffer->Access.Length = SwapBytes32 (
>> + (UINT32)sizeof ScratchBuffer->Features);
>> + ScratchBuffer->Access.Address = SwapBytes64 (
>> + (UINTN)&ScratchBuffer->Features);
>> + ScratchBuffer->Features = mSmiFeatures;
>> +
>> + //
>> + // Copy the scratch buffer into the boot script. When replayed, this
>> + // EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE will restore the current contents of the
>> + // scratch buffer, in-place.
>> + //
>> + Status = S3SaveState->Write (
>> + S3SaveState, // This
>> + EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE, // OpCode
>> + EfiBootScriptWidthUint8, // Width
>> + (UINT64)(UINTN)ScratchBuffer, // Address
>> + sizeof *ScratchBuffer, // Count
>> + (VOID*)ScratchBuffer // Buffer
>> + );
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "%a:%d: EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE: %r\n",
>> + __FUNCTION__, __LINE__, Status));
>> + goto FatalError;
>> + }
>> +
>> + //
>> + // Append an opcode that will write the address of the scratch buffer to the
>> + // fw_cfg DMA address register, which consists of two 32-bit IO ports. The
>> + // second (highest address, least significant) write will start the transfer.
>> + //
>> + AccessAddress = SwapBytes64 ((UINTN)&ScratchBuffer->Access);
>> + Status = S3SaveState->Write (
>> + S3SaveState, // This
>> + EFI_BOOT_SCRIPT_IO_WRITE_OPCODE, // OpCode
>> + EfiBootScriptWidthUint32, // Width
>> + (UINT64)0x514, // Address
>> + (UINTN)2, // Count
>> + &AccessAddress // Buffer
>> + );
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "%a:%d: EFI_BOOT_SCRIPT_IO_WRITE_OPCODE: %r\n",
>> + __FUNCTION__, __LINE__, Status));
>> + goto FatalError;
>> + }
>> +
>> + //
>> + // The EFI_BOOT_SCRIPT_MEM_POLL_OPCODE will wait until the Control word reads
>> + // as zero (transfer complete). As timeout we use MAX_UINT64 * 100ns, which
>> + // is approximately 58494 years.
>> + //
>> + ControlPollData = 0;
>> + ControlPollMask = MAX_UINT32;
>> + Status = S3SaveState->Write (
>> + S3SaveState, // This
>> + EFI_BOOT_SCRIPT_MEM_POLL_OPCODE, // OpCode
>> + EfiBootScriptWidthUint32, // Width
>> + (UINT64)(UINTN)&ScratchBuffer->Access.Control, // Address
>> + &ControlPollData, // Data
>> + &ControlPollMask, // DataMask
>> + MAX_UINT64 // Delay
>> + );
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "%a:%d: EFI_BOOT_SCRIPT_MEM_POLL_OPCODE: %r\n",
>> + __FUNCTION__, __LINE__, Status));
>> + goto FatalError;
>> + }
>> +
>> + //
>> + // Select the "etc/smi/features-ok" fw_cfg file, which invokes the feature
>> + // validation & lockdown. (The validation succeeded at first boot.)
>> + //
>> + FeaturesOkItemAsUint16 = (UINT16)mFeaturesOkItem;
>> + Status = S3SaveState->Write (
>> + S3SaveState, // This
>> + EFI_BOOT_SCRIPT_IO_WRITE_OPCODE, // OpCode
>> + EfiBootScriptWidthUint16, // Width
>> + (UINT64)0x510, // Address
>> + (UINTN)1, // Count
>> + &FeaturesOkItemAsUint16 // Buffer
>> + );
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "%a:%d: EFI_BOOT_SCRIPT_IO_WRITE_OPCODE: %r\n",
>> + __FUNCTION__, __LINE__, Status));
>> + goto FatalError;
>> + }
>> +
>> + //
>> + // Read the contents (one byte) of "etc/smi/features-ok". If the value is
>> + // one, we're good. Otherwise, continue reading the data port: QEMU returns 0
>> + // past the end of the fw_cfg item, so this will hang the resume process,
>> + // which matches our intent.
>> + //
>> + FeaturesOkData = 1;
>> + FeaturesOkMask = MAX_UINT8;
>> + Status = S3SaveState->Write (
>> + S3SaveState, // This
>> + EFI_BOOT_SCRIPT_IO_POLL_OPCODE, // OpCode
>> + EfiBootScriptWidthUint8, // Width
>> + (UINT64)(UINTN)0x511, // Address
>> + &FeaturesOkData, // Data
>> + &FeaturesOkMask, // DataMask
>> + MAX_UINT64 // Delay
>> + );
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "%a:%d: EFI_BOOT_SCRIPT_IO_POLL_OPCODE: %r\n",
>> + __FUNCTION__, __LINE__, Status));
>> + goto FatalError;
>> + }
>> +
>> + DEBUG ((DEBUG_VERBOSE, "%a: ScratchBuffer@%p\n", __FUNCTION__,
>> + (VOID *)ScratchBuffer));
>> + return;
>> +
>> +FatalError:
>> + ASSERT (FALSE);
>> + CpuDeadLoop ();
>> +}
>> diff --git a/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.c b/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.c
>> index 6c03e17a3a8d..f31646d73461 100644
>> --- a/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.c
>> +++ b/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.c
>> @@ -32,14 +32,16 @@
>> #include <Library/PcdLib.h>
>> #include <Library/PciLib.h>
>> #include <Library/QemuFwCfgLib.h>
>> #include <Library/UefiBootServicesTableLib.h>
>> #include <Protocol/S3SaveState.h>
>> #include <Protocol/SmmControl2.h>
>>
>> +#include "SmiFeatures.h"
>> +
>> //
>> // Forward declaration.
>> //
>> STATIC
>> VOID
>> EFIAPI
>> OnS3SaveStateInstalled (
>> @@ -52,14 +54,21 @@ OnS3SaveStateInstalled (
>> // only used to carry information from the entry point function to the
>> // S3SaveState protocol installation callback, strictly before the runtime
>> // phase.
>> //
>> STATIC UINTN mSmiEnable;
>>
>> //
>> +// Captures whether SMI feature negotiation is supported. The variable is only
>> +// used to carry this information from the entry point function to the
>> +// S3SaveState protocol installation callback.
>> +//
>> +STATIC BOOLEAN mSmiFeatureNegotiation;
>> +
>> +//
>> // Event signaled when an S3SaveState protocol interface is installed.
>> //
>> STATIC EFI_EVENT mS3SaveStateInstalled;
>>
>> /**
>> Invokes SMI activation from either the preboot or runtime environment.
>>
>> @@ -225,14 +234,19 @@ SmmControl2DxeEntryPoint (
>> IoWrite32 (mSmiEnable, SmiEnableVal & ~(UINT32)ICH9_SMI_EN_GBL_SMI_EN);
>> if (IoRead32 (mSmiEnable) != SmiEnableVal) {
>> DEBUG ((EFI_D_ERROR, "%a: failed to lock down GBL_SMI_EN\n",
>> __FUNCTION__));
>> goto FatalError;
>> }
>>
>> + //
>> + // QEMU can inject SMIs in different ways, negotiate our preferences.
>> + //
>> + mSmiFeatureNegotiation = NegotiateSmiFeatures ();
>> +
>> if (QemuFwCfgS3Enabled ()) {
>> VOID *Registration;
>>
>> //
>> // On S3 resume the above register settings have to be repeated. Register a
>> // protocol notify callback that, when boot script saving becomes
>> // available, saves operations equivalent to the above to the boot script.
>> @@ -359,11 +373,18 @@ OnS3SaveStateInstalled (
>> DEBUG ((EFI_D_ERROR,
>> "%a: EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE: %r\n", __FUNCTION__,
>> Status));
>> ASSERT (FALSE);
>> CpuDeadLoop ();
>> }
>>
>> + //
>> + // Append a boot script fragment that re-selects the negotiated SMI features.
>> + //
>> + if (mSmiFeatureNegotiation) {
>> + SaveSmiFeatures (S3SaveState);
>> + }
>> +
>> DEBUG ((EFI_D_VERBOSE, "%a: boot script fragment saved\n", __FUNCTION__));
>> gBS->CloseEvent (Event);
>> mS3SaveStateInstalled = NULL;
>> }
>> --
>> 2.9.3
>>
prev parent reply other threads:[~2017-02-07 11:32 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-01-31 11:02 [PATCH v3 0/2] OvmfPkg: broadcast SMIs and dynamically revert to traditional AP sync mode Laszlo Ersek
2017-01-31 11:02 ` [PATCH v3 1/2] OvmfPkg: dynamic defaults for PcdCpuSmmApSyncTimeout, PcdCpuSmmSyncMode Laszlo Ersek
2017-01-31 11:02 ` [PATCH v3 2/2] OvmfPkg/SmmControl2Dxe: select broadcast SMI if available Laszlo Ersek
[not found] ` <148646137918.13729.17315316362028292158@jljusten-ivb>
2017-02-07 11:32 ` Laszlo Ersek [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=934805ad-1e5a-ce9f-263a-fb72b4d0628e@redhat.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox