audk/OvmfPkg/SmmControl2Dxe/SmiFeatures.c

330 lines
9.1 KiB
C
Raw Normal View History

OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
/**@file
Negotiate SMI features with QEMU, and configure UefiCpuPkg/PiSmmCpuDxeSmm
accordingly.
Copyright (C) 2016-2017, Red Hat, Inc.
SPDX-License-Identifier: BSD-2-Clause-Patent
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
**/
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
OvmfPkg/SmmControl2Dxe: negotiate ICH9_LPC_SMI_F_CPU_HOTPLUG The ICH9_LPC_SMI_F_BROADCAST and ICH9_LPC_SMI_F_CPU_HOTPLUG feature flags cause QEMU to behave as follows: BROADCAST CPU_HOTPLUG use case / behavior --------- ----------- ------------------------------------------------ clear clear OVMF built without SMM_REQUIRE; or very old OVMF (from before commit a316d7ac91d3 / 2017-02-07). QEMU permits CPU hotplug operations, and does not cause the OS to inject an SMI upon hotplug. Firmware is not expected to be aware of hotplug events. clear set Invalid feature set; QEMU rejects the feature negotiation. set clear OVMF after a316d7ac91d3 / 2017-02-07, built with SMM_REQUIRE, but no support for CPU hotplug. QEMU gracefully refuses hotplug operations. set set OVMF after a316d7ac91d3 / 2017-02-07, built with SMM_REQUIRE, and supporting CPU hotplug. QEMU permits CPU hotplug operations, and causes the OS to inject an SMI upon hotplug. Firmware is expected to deal with hotplug events. Negotiate ICH9_LPC_SMI_F_CPU_HOTPLUG -- but only if SEV is disabled, as OvmfPkg/CpuHotplugSmm can't deal with SEV yet. Cc: Ard Biesheuvel <ard.biesheuvel@arm.com> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: Igor Mammedov <imammedo@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Liran Alon <liran.alon@oracle.com> Cc: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: Laszlo Ersek <lersek@redhat.com> Message-Id: <20200714184305.9814-1-lersek@redhat.com> Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
2020-07-14 20:43:05 +02:00
#include <Library/MemEncryptSevLib.h>
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Library/QemuFwCfgLib.h>
#include <Library/QemuFwCfgS3Lib.h>
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
#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
OvmfPkg/SmmControl2Dxe: negotiate ICH9_LPC_SMI_F_CPU_HOTPLUG The ICH9_LPC_SMI_F_BROADCAST and ICH9_LPC_SMI_F_CPU_HOTPLUG feature flags cause QEMU to behave as follows: BROADCAST CPU_HOTPLUG use case / behavior --------- ----------- ------------------------------------------------ clear clear OVMF built without SMM_REQUIRE; or very old OVMF (from before commit a316d7ac91d3 / 2017-02-07). QEMU permits CPU hotplug operations, and does not cause the OS to inject an SMI upon hotplug. Firmware is not expected to be aware of hotplug events. clear set Invalid feature set; QEMU rejects the feature negotiation. set clear OVMF after a316d7ac91d3 / 2017-02-07, built with SMM_REQUIRE, but no support for CPU hotplug. QEMU gracefully refuses hotplug operations. set set OVMF after a316d7ac91d3 / 2017-02-07, built with SMM_REQUIRE, and supporting CPU hotplug. QEMU permits CPU hotplug operations, and causes the OS to inject an SMI upon hotplug. Firmware is expected to deal with hotplug events. Negotiate ICH9_LPC_SMI_F_CPU_HOTPLUG -- but only if SEV is disabled, as OvmfPkg/CpuHotplugSmm can't deal with SEV yet. Cc: Ard Biesheuvel <ard.biesheuvel@arm.com> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: Igor Mammedov <imammedo@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Liran Alon <liran.alon@oracle.com> Cc: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: Laszlo Ersek <lersek@redhat.com> Message-Id: <20200714184305.9814-1-lersek@redhat.com> Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
2020-07-14 20:43:05 +02:00
//
// The following bit value stands for "enable CPU hotplug, and inject an SMI
// with control value ICH9_APM_CNT_CPU_HOTPLUG upon hotplug", in the
// "etc/smi/supported-features" and "etc/smi/requested-features" fw_cfg files.
//
#define ICH9_LPC_SMI_F_CPU_HOTPLUG BIT1
//
// The following bit value stands for "enable CPU hot-unplug, and inject an SMI
// with control value ICH9_APM_CNT_CPU_HOTPLUG upon hot-unplug", in the
// "etc/smi/supported-features" and "etc/smi/requested-features" fw_cfg files.
//
#define ICH9_LPC_SMI_F_CPU_HOT_UNPLUG BIT2
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
//
// Provides a scratch buffer (allocated in EfiReservedMemoryType type memory)
// for the S3 boot script fragment to write to and read from.
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
//
#pragma pack (1)
typedef union {
UINT64 Features;
UINT8 FeaturesOk;
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
} 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
// AppendFwCfgBootScript().
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
//
STATIC FIRMWARE_CONFIG_ITEM mRequestedFeaturesItem;
STATIC FIRMWARE_CONFIG_ITEM mFeaturesOkItem;
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
//
// Carries the negotiated SMI features from NegotiateSmiFeatures() to
// AppendFwCfgBootScript().
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
//
STATIC UINT64 mSmiFeatures;
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
/**
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;
UINT64 RequestedFeaturesMask;
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
//
// 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__
));
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
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__
));
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
goto FatalError;
}
//
// Get the features supported by the host.
//
QemuFwCfgSelectItem (SupportedFeaturesItem);
QemuFwCfgReadBytes (sizeof mSmiFeatures, &mSmiFeatures);
//
// We want broadcast SMI, SMI on CPU hotplug, SMI on CPU hot-unplug
// and nothing else.
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
//
OvmfPkg/SmmControl2Dxe: negotiate ICH9_LPC_SMI_F_CPU_HOTPLUG The ICH9_LPC_SMI_F_BROADCAST and ICH9_LPC_SMI_F_CPU_HOTPLUG feature flags cause QEMU to behave as follows: BROADCAST CPU_HOTPLUG use case / behavior --------- ----------- ------------------------------------------------ clear clear OVMF built without SMM_REQUIRE; or very old OVMF (from before commit a316d7ac91d3 / 2017-02-07). QEMU permits CPU hotplug operations, and does not cause the OS to inject an SMI upon hotplug. Firmware is not expected to be aware of hotplug events. clear set Invalid feature set; QEMU rejects the feature negotiation. set clear OVMF after a316d7ac91d3 / 2017-02-07, built with SMM_REQUIRE, but no support for CPU hotplug. QEMU gracefully refuses hotplug operations. set set OVMF after a316d7ac91d3 / 2017-02-07, built with SMM_REQUIRE, and supporting CPU hotplug. QEMU permits CPU hotplug operations, and causes the OS to inject an SMI upon hotplug. Firmware is expected to deal with hotplug events. Negotiate ICH9_LPC_SMI_F_CPU_HOTPLUG -- but only if SEV is disabled, as OvmfPkg/CpuHotplugSmm can't deal with SEV yet. Cc: Ard Biesheuvel <ard.biesheuvel@arm.com> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: Igor Mammedov <imammedo@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Liran Alon <liran.alon@oracle.com> Cc: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: Laszlo Ersek <lersek@redhat.com> Message-Id: <20200714184305.9814-1-lersek@redhat.com> Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
2020-07-14 20:43:05 +02:00
RequestedFeaturesMask = ICH9_LPC_SMI_F_BROADCAST;
if (!MemEncryptSevIsEnabled ()) {
//
// For now, we only support hotplug with SEV disabled.
//
RequestedFeaturesMask |= ICH9_LPC_SMI_F_CPU_HOTPLUG;
RequestedFeaturesMask |= ICH9_LPC_SMI_F_CPU_HOT_UNPLUG;
OvmfPkg/SmmControl2Dxe: negotiate ICH9_LPC_SMI_F_CPU_HOTPLUG The ICH9_LPC_SMI_F_BROADCAST and ICH9_LPC_SMI_F_CPU_HOTPLUG feature flags cause QEMU to behave as follows: BROADCAST CPU_HOTPLUG use case / behavior --------- ----------- ------------------------------------------------ clear clear OVMF built without SMM_REQUIRE; or very old OVMF (from before commit a316d7ac91d3 / 2017-02-07). QEMU permits CPU hotplug operations, and does not cause the OS to inject an SMI upon hotplug. Firmware is not expected to be aware of hotplug events. clear set Invalid feature set; QEMU rejects the feature negotiation. set clear OVMF after a316d7ac91d3 / 2017-02-07, built with SMM_REQUIRE, but no support for CPU hotplug. QEMU gracefully refuses hotplug operations. set set OVMF after a316d7ac91d3 / 2017-02-07, built with SMM_REQUIRE, and supporting CPU hotplug. QEMU permits CPU hotplug operations, and causes the OS to inject an SMI upon hotplug. Firmware is expected to deal with hotplug events. Negotiate ICH9_LPC_SMI_F_CPU_HOTPLUG -- but only if SEV is disabled, as OvmfPkg/CpuHotplugSmm can't deal with SEV yet. Cc: Ard Biesheuvel <ard.biesheuvel@arm.com> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: Igor Mammedov <imammedo@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Liran Alon <liran.alon@oracle.com> Cc: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: Laszlo Ersek <lersek@redhat.com> Message-Id: <20200714184305.9814-1-lersek@redhat.com> Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
2020-07-14 20:43:05 +02:00
}
OvmfPkg/SmmControl2Dxe: negotiate ICH9_LPC_SMI_F_CPU_HOTPLUG The ICH9_LPC_SMI_F_BROADCAST and ICH9_LPC_SMI_F_CPU_HOTPLUG feature flags cause QEMU to behave as follows: BROADCAST CPU_HOTPLUG use case / behavior --------- ----------- ------------------------------------------------ clear clear OVMF built without SMM_REQUIRE; or very old OVMF (from before commit a316d7ac91d3 / 2017-02-07). QEMU permits CPU hotplug operations, and does not cause the OS to inject an SMI upon hotplug. Firmware is not expected to be aware of hotplug events. clear set Invalid feature set; QEMU rejects the feature negotiation. set clear OVMF after a316d7ac91d3 / 2017-02-07, built with SMM_REQUIRE, but no support for CPU hotplug. QEMU gracefully refuses hotplug operations. set set OVMF after a316d7ac91d3 / 2017-02-07, built with SMM_REQUIRE, and supporting CPU hotplug. QEMU permits CPU hotplug operations, and causes the OS to inject an SMI upon hotplug. Firmware is expected to deal with hotplug events. Negotiate ICH9_LPC_SMI_F_CPU_HOTPLUG -- but only if SEV is disabled, as OvmfPkg/CpuHotplugSmm can't deal with SEV yet. Cc: Ard Biesheuvel <ard.biesheuvel@arm.com> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: Igor Mammedov <imammedo@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Liran Alon <liran.alon@oracle.com> Cc: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: Laszlo Ersek <lersek@redhat.com> Message-Id: <20200714184305.9814-1-lersek@redhat.com> Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
2020-07-14 20:43:05 +02:00
mSmiFeatures &= RequestedFeaturesMask;
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
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
));
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
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__
));
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
goto FatalError;
}
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
DEBUG ((DEBUG_INFO, "%a: using SMI broadcast\n", __FUNCTION__));
}
OvmfPkg/SmmControl2Dxe: negotiate ICH9_LPC_SMI_F_CPU_HOTPLUG The ICH9_LPC_SMI_F_BROADCAST and ICH9_LPC_SMI_F_CPU_HOTPLUG feature flags cause QEMU to behave as follows: BROADCAST CPU_HOTPLUG use case / behavior --------- ----------- ------------------------------------------------ clear clear OVMF built without SMM_REQUIRE; or very old OVMF (from before commit a316d7ac91d3 / 2017-02-07). QEMU permits CPU hotplug operations, and does not cause the OS to inject an SMI upon hotplug. Firmware is not expected to be aware of hotplug events. clear set Invalid feature set; QEMU rejects the feature negotiation. set clear OVMF after a316d7ac91d3 / 2017-02-07, built with SMM_REQUIRE, but no support for CPU hotplug. QEMU gracefully refuses hotplug operations. set set OVMF after a316d7ac91d3 / 2017-02-07, built with SMM_REQUIRE, and supporting CPU hotplug. QEMU permits CPU hotplug operations, and causes the OS to inject an SMI upon hotplug. Firmware is expected to deal with hotplug events. Negotiate ICH9_LPC_SMI_F_CPU_HOTPLUG -- but only if SEV is disabled, as OvmfPkg/CpuHotplugSmm can't deal with SEV yet. Cc: Ard Biesheuvel <ard.biesheuvel@arm.com> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: Igor Mammedov <imammedo@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Liran Alon <liran.alon@oracle.com> Cc: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: Laszlo Ersek <lersek@redhat.com> Message-Id: <20200714184305.9814-1-lersek@redhat.com> Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
2020-07-14 20:43:05 +02:00
if ((mSmiFeatures & ICH9_LPC_SMI_F_CPU_HOTPLUG) == 0) {
DEBUG ((DEBUG_INFO, "%a: CPU hotplug not negotiated\n", __FUNCTION__));
} else {
DEBUG ((
DEBUG_INFO,
"%a: CPU hotplug with SMI negotiated\n",
__FUNCTION__
));
OvmfPkg/SmmControl2Dxe: negotiate ICH9_LPC_SMI_F_CPU_HOTPLUG The ICH9_LPC_SMI_F_BROADCAST and ICH9_LPC_SMI_F_CPU_HOTPLUG feature flags cause QEMU to behave as follows: BROADCAST CPU_HOTPLUG use case / behavior --------- ----------- ------------------------------------------------ clear clear OVMF built without SMM_REQUIRE; or very old OVMF (from before commit a316d7ac91d3 / 2017-02-07). QEMU permits CPU hotplug operations, and does not cause the OS to inject an SMI upon hotplug. Firmware is not expected to be aware of hotplug events. clear set Invalid feature set; QEMU rejects the feature negotiation. set clear OVMF after a316d7ac91d3 / 2017-02-07, built with SMM_REQUIRE, but no support for CPU hotplug. QEMU gracefully refuses hotplug operations. set set OVMF after a316d7ac91d3 / 2017-02-07, built with SMM_REQUIRE, and supporting CPU hotplug. QEMU permits CPU hotplug operations, and causes the OS to inject an SMI upon hotplug. Firmware is expected to deal with hotplug events. Negotiate ICH9_LPC_SMI_F_CPU_HOTPLUG -- but only if SEV is disabled, as OvmfPkg/CpuHotplugSmm can't deal with SEV yet. Cc: Ard Biesheuvel <ard.biesheuvel@arm.com> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: Igor Mammedov <imammedo@redhat.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Liran Alon <liran.alon@oracle.com> Cc: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: Laszlo Ersek <lersek@redhat.com> Message-Id: <20200714184305.9814-1-lersek@redhat.com> Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
2020-07-14 20:43:05 +02:00
}
if ((mSmiFeatures & ICH9_LPC_SMI_F_CPU_HOT_UNPLUG) == 0) {
DEBUG ((DEBUG_INFO, "%a: CPU hot-unplug not negotiated\n", __FUNCTION__));
} else {
DEBUG ((
DEBUG_INFO,
"%a: CPU hot-unplug with SMI negotiated\n",
__FUNCTION__
));
}
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
//
// Negotiation successful (although we may not have gotten the optimal
// feature set).
//
return TRUE;
FatalError:
ASSERT (FALSE);
CpuDeadLoop ();
//
// Keep the compiler happy.
//
return FALSE;
}
/**
FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION provided to QemuFwCfgS3Lib.
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
**/
STATIC
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
VOID
EFIAPI
AppendFwCfgBootScript (
IN OUT VOID *Context OPTIONAL,
IN OUT VOID *ExternalScratchBuffer
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
)
{
SCRATCH_BUFFER *ScratchBuffer;
RETURN_STATUS Status;
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
ScratchBuffer = ExternalScratchBuffer;
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
//
// Write the negotiated feature bitmap into "etc/smi/requested-features".
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
//
ScratchBuffer->Features = mSmiFeatures;
Status = QemuFwCfgS3ScriptWriteBytes (
mRequestedFeaturesItem,
sizeof ScratchBuffer->Features
);
if (RETURN_ERROR (Status)) {
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
goto FatalError;
}
//
// Read back "etc/smi/features-ok". This invokes the feature validation &
// lockdown. (The validation succeeded at first boot.)
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
//
Status = QemuFwCfgS3ScriptReadBytes (
mFeaturesOkItem,
sizeof ScratchBuffer->FeaturesOk
);
if (RETURN_ERROR (Status)) {
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
goto FatalError;
}
//
// If "etc/smi/features-ok" read as 1, we're good. Otherwise, hang the S3
// resume process.
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
//
Status = QemuFwCfgS3ScriptCheckValue (
&ScratchBuffer->FeaturesOk,
sizeof ScratchBuffer->FeaturesOk,
MAX_UINT8,
1
);
if (RETURN_ERROR (Status)) {
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
goto FatalError;
}
DEBUG ((
DEBUG_VERBOSE,
"%a: SMI feature negotiation boot script saved\n",
__FUNCTION__
));
OvmfPkg/SmmControl2Dxe: select broadcast SMI if available When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an SMI only on the VCPU that is writing the port. 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. 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> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2016-11-30 20:06:34 +01:00
return;
FatalError:
ASSERT (FALSE);
CpuDeadLoop ();
}
/**
Append a boot script fragment that will re-select the previously negotiated
SMI features during S3 resume.
**/
VOID
SaveSmiFeatures (
VOID
)
{
RETURN_STATUS Status;
//
// We are already running at TPL_CALLBACK, on the stack of
// OnS3SaveStateInstalled(). But that's okay, we can easily queue more
// notification functions while executing a notification function.
//
Status = QemuFwCfgS3CallWhenBootScriptReady (
AppendFwCfgBootScript,
NULL,
sizeof (SCRATCH_BUFFER)
);
if (RETURN_ERROR (Status)) {
ASSERT (FALSE);
CpuDeadLoop ();
}
}