2009-05-27 23:10:18 +02:00
|
|
|
/**@file
|
|
|
|
Platform PEI driver
|
|
|
|
|
2016-04-07 12:19:23 +02:00
|
|
|
Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
|
2011-08-05 17:43:05 +02:00
|
|
|
Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>
|
|
|
|
|
2019-04-04 01:06:33 +02:00
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
2009-05-27 23:10:18 +02:00
|
|
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
//
|
|
|
|
// The package level header files this module uses
|
|
|
|
//
|
|
|
|
#include <PiPei.h>
|
|
|
|
|
|
|
|
//
|
|
|
|
// The Library classes this module consumes
|
|
|
|
//
|
2021-12-13 09:16:56 +01:00
|
|
|
#include <Library/BaseMemoryLib.h>
|
2015-12-01 00:36:31 +01:00
|
|
|
#include <Library/BaseLib.h>
|
2009-05-27 23:10:18 +02:00
|
|
|
#include <Library/DebugLib.h>
|
|
|
|
#include <Library/HobLib.h>
|
|
|
|
#include <Library/IoLib.h>
|
2009-09-07 22:18:17 +02:00
|
|
|
#include <Library/MemoryAllocationLib.h>
|
|
|
|
#include <Library/PcdLib.h>
|
2009-05-27 23:10:18 +02:00
|
|
|
#include <Library/PciLib.h>
|
|
|
|
#include <Library/PeimEntryPoint.h>
|
2011-03-22 02:55:08 +01:00
|
|
|
#include <Library/PeiServicesLib.h>
|
2014-03-04 09:01:58 +01:00
|
|
|
#include <Library/QemuFwCfgLib.h>
|
2017-02-22 03:47:18 +01:00
|
|
|
#include <Library/QemuFwCfgS3Lib.h>
|
2020-04-24 09:53:49 +02:00
|
|
|
#include <Library/QemuFwCfgSimpleParserLib.h>
|
2009-05-27 23:10:18 +02:00
|
|
|
#include <Library/ResourcePublicationLib.h>
|
2011-03-22 02:55:08 +01:00
|
|
|
#include <Ppi/MasterBootMode.h>
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
#include <IndustryStandard/I440FxPiix4.h>
|
2021-09-08 11:01:13 +02:00
|
|
|
#include <IndustryStandard/Microvm.h>
|
OvmfPkg: enable PIIX4 IO space in the PEI phase
I. There are at least three locations in OvmfPkg that manipulate the PMBA
and related PIIX4 registers.
1. MiscInitialization() [OvmfPkg/PlatformPei/Platform.c]
module type: PEIM -- Pre-EFI Initialization Module
(a) currently sets the PMBA only: 00.01.3 / 0x40 bits [15:6]
2. AcpiTimerLibConstructor() [OvmfPkg/Library/AcpiTimerLib/AcpiTimerLib.c]
module type: BASE -- probably callable anywhere after PEI
(a) sets the PMBA if needed: 00.01.3 / 0x40 bits [15:6]
(b) sets PCICMD/IOSE if needed: 00.01.3 / 0x04 bit 0
(c) sets PMREGMISC/PMIOSE: 00.01.3 / 0x80 bit 0
3. AcpiInitialization() [OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c]
module type: DXE_DRIVER -- Driver eXecution Environment
(a) sets SCI_EN, which depends on correct PMBA setting from earlier
(
The relative order of #1 and #3 is dictated minimally by their module
types. Said relative order can be verified with the boot log:
27 Loading PEIM at 0x00000822320 EntryPoint=0x00000822580
PlatformPei.efi
28 Platform PEIM Loaded
1259 PlatformBdsInit
1270 PlatformBdsPolicyBehavior
Line 28 is printed by InitializePlatform()
[OvmfPkg/PlatformPei/Platform.c] which is the entry point of that
module. The other two lines are printed by the corresponding functions
in "OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c".
)
Currently #2 (AcpiTimerLibConstructor()) is called in a random spot
(whenever it gets loaded from the firmware image) and masks the
insufficient setup in #1. We shouldn't depend on that, PEI should finish
with IO space being fully accessibe. In addition, PEI should program the
same PMBA value as AcpiTimerLib.
II. The PEI change notwithstanding, AcpiTimerLib should stay defensive and
ensure proper PM configuration for itself (either by confirming or by
doing).
III. Considering a possible cleanup/unification of #2 and #3: timer
functions relying on AcpiTimerLibConstructor(),
- MicroSecondDelay()
- NanoSecondDelay()
- GetPerformanceCounter()
- GetPerformanceCounterProperties()
- GetTimeInNanoSecond()
may be called before #3 is reached (in Boot Device Selection phase), so we
should not move the initialization from #2 to #3. (Again, AcpiTimerLib
should contain its own setup.)
We should also not move #3 to an earlier phase -- SCI_EN is premature
unless we're about to boot real soon ("enable generation of SCI upon
assertion of PWRBTN_STS, LID_STS, THRM_STS, or GPI_STS bits").
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13722 6f19259b-4bc3-4df7-8a09-765794883524
2012-09-12 09:19:16 +02:00
|
|
|
#include <IndustryStandard/Pci22.h>
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
#include <IndustryStandard/Q35MchIch9.h>
|
|
|
|
#include <IndustryStandard/QemuCpuHotplug.h>
|
2022-03-06 03:20:36 +01:00
|
|
|
#include <Library/MemEncryptSevLib.h>
|
2014-11-14 01:37:26 +01:00
|
|
|
#include <OvmfPlatforms.h>
|
2009-05-27 23:10:18 +02:00
|
|
|
|
|
|
|
#include "Platform.h"
|
|
|
|
|
2022-03-06 03:20:36 +01:00
|
|
|
EFI_HOB_PLATFORM_INFO mPlatformInfoHob = { 0 };
|
|
|
|
|
2021-12-05 23:54:09 +01:00
|
|
|
EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = {
|
2011-03-22 02:55:08 +01:00
|
|
|
{
|
|
|
|
EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
|
|
|
|
&gEfiPeiMasterBootModePpiGuid,
|
|
|
|
NULL
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-12-08 02:36:15 +01:00
|
|
|
VOID
|
2014-02-01 22:22:43 +01:00
|
|
|
MemMapInitialization (
|
2022-03-06 03:20:36 +01:00
|
|
|
IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
|
2013-12-08 02:36:15 +01:00
|
|
|
)
|
|
|
|
{
|
2021-12-05 23:54:09 +01:00
|
|
|
UINT64 PciIoBase;
|
|
|
|
UINT64 PciIoSize;
|
|
|
|
RETURN_STATUS PcdStatus;
|
|
|
|
UINT32 TopOfLowRam;
|
|
|
|
UINT64 PciExBarBase;
|
|
|
|
UINT32 PciBase;
|
|
|
|
UINT32 PciSize;
|
2016-05-09 22:39:44 +02:00
|
|
|
|
|
|
|
PciIoBase = 0xC000;
|
|
|
|
PciIoSize = 0x4000;
|
|
|
|
|
2013-12-08 02:36:15 +01:00
|
|
|
//
|
|
|
|
// Video memory + Legacy BIOS region
|
|
|
|
//
|
2022-02-12 09:53:26 +01:00
|
|
|
PlatformAddIoMemoryRangeHob (0x0A0000, BASE_1MB);
|
2013-12-08 02:36:15 +01:00
|
|
|
|
2022-03-06 03:20:36 +01:00
|
|
|
if (PlatformInfoHob->HostBridgeDevId == 0xffff /* microvm */) {
|
2022-02-12 09:53:26 +01:00
|
|
|
PlatformAddIoMemoryBaseSizeHob (MICROVM_GED_MMIO_BASE, SIZE_4KB);
|
|
|
|
PlatformAddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB); /* ioapic #1 */
|
|
|
|
PlatformAddIoMemoryBaseSizeHob (0xFEC10000, SIZE_4KB); /* ioapic #2 */
|
2021-09-08 11:01:12 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-03-07 14:54:30 +01:00
|
|
|
TopOfLowRam = PlatformGetSystemMemorySizeBelow4gb (PlatformInfoHob);
|
2021-05-26 22:14:24 +02:00
|
|
|
PciExBarBase = 0;
|
2022-03-06 03:20:36 +01:00
|
|
|
if (PlatformInfoHob->HostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
|
2021-05-26 22:14:24 +02:00
|
|
|
//
|
|
|
|
// The MMCONFIG area is expected to fall between the top of low RAM and
|
|
|
|
// the base of the 32-bit PCI host aperture.
|
|
|
|
//
|
|
|
|
PciExBarBase = FixedPcdGet64 (PcdPciExpressBaseAddress);
|
|
|
|
ASSERT (TopOfLowRam <= PciExBarBase);
|
|
|
|
ASSERT (PciExBarBase <= MAX_UINT32 - SIZE_256MB);
|
|
|
|
PciBase = (UINT32)(PciExBarBase + SIZE_256MB);
|
|
|
|
} else {
|
2022-03-06 03:20:36 +01:00
|
|
|
ASSERT (TopOfLowRam <= PlatformInfoHob->Uc32Base);
|
|
|
|
PciBase = PlatformInfoHob->Uc32Base;
|
2021-05-26 22:14:24 +02:00
|
|
|
}
|
2015-09-02 20:45:44 +02:00
|
|
|
|
2021-05-26 22:14:24 +02:00
|
|
|
//
|
|
|
|
// address purpose size
|
|
|
|
// ------------ -------- -------------------------
|
|
|
|
// max(top, 2g) PCI MMIO 0xFC000000 - max(top, 2g)
|
|
|
|
// 0xFC000000 gap 44 MB
|
|
|
|
// 0xFEC00000 IO-APIC 4 KB
|
|
|
|
// 0xFEC01000 gap 1020 KB
|
|
|
|
// 0xFED00000 HPET 1 KB
|
|
|
|
// 0xFED00400 gap 111 KB
|
|
|
|
// 0xFED1C000 gap (PIIX4) / RCRB (ICH9) 16 KB
|
|
|
|
// 0xFED20000 gap 896 KB
|
|
|
|
// 0xFEE00000 LAPIC 1 MB
|
|
|
|
//
|
|
|
|
PciSize = 0xFC000000 - PciBase;
|
2022-02-12 09:53:26 +01:00
|
|
|
PlatformAddIoMemoryBaseSizeHob (PciBase, PciSize);
|
2021-05-26 22:14:24 +02:00
|
|
|
PcdStatus = PcdSet64S (PcdPciMmio32Base, PciBase);
|
|
|
|
ASSERT_RETURN_ERROR (PcdStatus);
|
|
|
|
PcdStatus = PcdSet64S (PcdPciMmio32Size, PciSize);
|
|
|
|
ASSERT_RETURN_ERROR (PcdStatus);
|
2009-05-27 23:10:18 +02:00
|
|
|
|
2022-03-06 03:20:36 +01:00
|
|
|
PlatformInfoHob->PcdPciMmio32Base = PciBase;
|
|
|
|
PlatformInfoHob->PcdPciMmio32Size = PciSize;
|
|
|
|
|
2022-02-12 09:53:26 +01:00
|
|
|
PlatformAddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB);
|
|
|
|
PlatformAddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB);
|
2022-03-06 03:20:36 +01:00
|
|
|
if (PlatformInfoHob->HostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
|
2022-02-12 09:53:26 +01:00
|
|
|
PlatformAddIoMemoryBaseSizeHob (ICH9_ROOT_COMPLEX_BASE, SIZE_16KB);
|
2014-02-01 22:22:43 +01:00
|
|
|
//
|
2021-05-26 22:14:24 +02:00
|
|
|
// Note: there should be an
|
2016-05-09 22:54:36 +02:00
|
|
|
//
|
2022-02-12 09:53:26 +01:00
|
|
|
// PlatformAddIoMemoryBaseSizeHob (PciExBarBase, SIZE_256MB);
|
2016-05-09 22:54:36 +02:00
|
|
|
//
|
2021-05-26 22:14:24 +02:00
|
|
|
// call below, just like the one above for RCBA. However, Linux insists
|
|
|
|
// that the MMCONFIG area be marked in the E820 or UEFI memory map as
|
|
|
|
// "reserved memory" -- Linux does not content itself with a simple gap
|
|
|
|
// in the memory map wherever the MCFG ACPI table points to.
|
|
|
|
//
|
|
|
|
// This appears to be a safety measure. The PCI Firmware Specification
|
|
|
|
// (rev 3.1) says in 4.1.2. "MCFG Table Description": "The resources can
|
|
|
|
// *optionally* be returned in [...] EFIGetMemoryMap as reserved memory
|
|
|
|
// [...]". (Emphasis added here.)
|
|
|
|
//
|
|
|
|
// Normally we add memory resource descriptor HOBs in
|
|
|
|
// QemuInitializeRam(), and pre-allocate from those with memory
|
|
|
|
// allocation HOBs in InitializeRamRegions(). However, the MMCONFIG area
|
|
|
|
// is most definitely not RAM; so, as an exception, cover it with
|
|
|
|
// uncacheable reserved memory right here.
|
|
|
|
//
|
2022-02-12 09:53:26 +01:00
|
|
|
PlatformAddReservedMemoryBaseSizeHob (PciExBarBase, SIZE_256MB, FALSE);
|
2021-12-05 23:54:09 +01:00
|
|
|
BuildMemoryAllocationHob (
|
|
|
|
PciExBarBase,
|
|
|
|
SIZE_256MB,
|
|
|
|
EfiReservedMemoryType
|
|
|
|
);
|
2021-05-26 22:14:24 +02:00
|
|
|
}
|
2021-12-05 23:54:09 +01:00
|
|
|
|
2022-02-12 09:53:26 +01:00
|
|
|
PlatformAddIoMemoryBaseSizeHob (PcdGet32 (PcdCpuLocalApicBaseAddress), SIZE_1MB);
|
2021-05-26 22:14:24 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// On Q35, the IO Port space is available for PCI resource allocations from
|
|
|
|
// 0x6000 up.
|
|
|
|
//
|
2022-03-06 03:20:36 +01:00
|
|
|
if (PlatformInfoHob->HostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
|
2021-05-26 22:14:24 +02:00
|
|
|
PciIoBase = 0x6000;
|
|
|
|
PciIoSize = 0xA000;
|
|
|
|
ASSERT ((ICH9_PMBASE_VALUE & 0xF000) < PciIoBase);
|
2014-02-01 22:22:43 +01:00
|
|
|
}
|
2016-05-09 22:39:44 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// Add PCI IO Port space available for PCI resource allocations.
|
|
|
|
//
|
|
|
|
BuildResourceDescriptorHob (
|
|
|
|
EFI_RESOURCE_IO,
|
|
|
|
EFI_RESOURCE_ATTRIBUTE_PRESENT |
|
|
|
|
EFI_RESOURCE_ATTRIBUTE_INITIALIZED,
|
|
|
|
PciIoBase,
|
|
|
|
PciIoSize
|
|
|
|
);
|
2016-10-21 11:59:36 +02:00
|
|
|
PcdStatus = PcdSet64S (PcdPciIoBase, PciIoBase);
|
|
|
|
ASSERT_RETURN_ERROR (PcdStatus);
|
|
|
|
PcdStatus = PcdSet64S (PcdPciIoSize, PciIoSize);
|
|
|
|
ASSERT_RETURN_ERROR (PcdStatus);
|
2022-03-06 03:20:36 +01:00
|
|
|
|
|
|
|
PlatformInfoHob->PcdPciIoBase = PciIoBase;
|
|
|
|
PlatformInfoHob->PcdPciIoSize = PciIoSize;
|
2009-05-27 23:10:18 +02:00
|
|
|
}
|
|
|
|
|
2015-09-15 10:35:14 +02:00
|
|
|
#define UPDATE_BOOLEAN_PCD_FROM_FW_CFG(TokenName) \
|
|
|
|
do { \
|
2016-10-21 11:59:36 +02:00
|
|
|
BOOLEAN Setting; \
|
|
|
|
RETURN_STATUS PcdStatus; \
|
2015-09-15 10:35:14 +02:00
|
|
|
\
|
2020-04-24 09:53:49 +02:00
|
|
|
if (!RETURN_ERROR (QemuFwCfgParseBool ( \
|
2015-09-15 10:35:14 +02:00
|
|
|
"opt/ovmf/" #TokenName, &Setting))) { \
|
2016-10-21 11:59:36 +02:00
|
|
|
PcdStatus = PcdSetBoolS (TokenName, Setting); \
|
|
|
|
ASSERT_RETURN_ERROR (PcdStatus); \
|
2015-09-15 10:35:14 +02:00
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NoexecDxeInitialization (
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdSetNxForStack);
|
|
|
|
}
|
2009-05-27 23:10:18 +02:00
|
|
|
|
2016-03-03 20:46:22 +01:00
|
|
|
VOID
|
|
|
|
PciExBarInitialization (
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
union {
|
2021-12-05 23:54:09 +01:00
|
|
|
UINT64 Uint64;
|
|
|
|
UINT32 Uint32[2];
|
2016-03-03 20:46:22 +01:00
|
|
|
} PciExBarBase;
|
|
|
|
|
|
|
|
//
|
|
|
|
// We only support the 256MB size for the MMCONFIG area:
|
|
|
|
// 256 buses * 32 devices * 8 functions * 4096 bytes config space.
|
|
|
|
//
|
|
|
|
// The masks used below enforce the Q35 requirements that the MMCONFIG area
|
|
|
|
// be (a) correctly aligned -- here at 256 MB --, (b) located under 64 GB.
|
|
|
|
//
|
|
|
|
// Note that (b) also ensures that the minimum address width we have
|
|
|
|
// determined in AddressWidthInitialization(), i.e., 36 bits, will suffice
|
|
|
|
// for DXE's page tables to cover the MMCONFIG area.
|
|
|
|
//
|
|
|
|
PciExBarBase.Uint64 = FixedPcdGet64 (PcdPciExpressBaseAddress);
|
|
|
|
ASSERT ((PciExBarBase.Uint32[1] & MCH_PCIEXBAR_HIGHMASK) == 0);
|
|
|
|
ASSERT ((PciExBarBase.Uint32[0] & MCH_PCIEXBAR_LOWMASK) == 0);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Clear the PCIEXBAREN bit first, before programming the high register.
|
|
|
|
//
|
|
|
|
PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW), 0);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Program the high register. Then program the low register, setting the
|
|
|
|
// MMCONFIG area size and enabling decoding at once.
|
|
|
|
//
|
|
|
|
PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_HIGH), PciExBarBase.Uint32[1]);
|
|
|
|
PciWrite32 (
|
|
|
|
DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW),
|
|
|
|
PciExBarBase.Uint32[0] | MCH_PCIEXBAR_BUS_FF | MCH_PCIEXBAR_EN
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-12-13 09:16:56 +01:00
|
|
|
static const UINT8 EmptyFdt[] = {
|
|
|
|
0xd0, 0x0d, 0xfe, 0xed, 0x00, 0x00, 0x00, 0x48,
|
|
|
|
0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x48,
|
|
|
|
0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x11,
|
|
|
|
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09,
|
|
|
|
};
|
|
|
|
|
2021-12-13 09:16:55 +01:00
|
|
|
VOID
|
|
|
|
MicrovmInitialization (
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
FIRMWARE_CONFIG_ITEM FdtItem;
|
|
|
|
UINTN FdtSize;
|
|
|
|
UINTN FdtPages;
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINT64 *FdtHobData;
|
|
|
|
VOID *NewBase;
|
|
|
|
|
|
|
|
Status = QemuFwCfgFindFile ("etc/fdt", &FdtItem, &FdtSize);
|
|
|
|
if (EFI_ERROR (Status)) {
|
2021-12-13 09:16:56 +01:00
|
|
|
DEBUG ((DEBUG_INFO, "%a: no etc/fdt found in fw_cfg, using dummy\n", __FUNCTION__));
|
|
|
|
FdtItem = 0;
|
|
|
|
FdtSize = sizeof (EmptyFdt);
|
2021-12-13 09:16:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
FdtPages = EFI_SIZE_TO_PAGES (FdtSize);
|
|
|
|
NewBase = AllocatePages (FdtPages);
|
|
|
|
if (NewBase == NULL) {
|
|
|
|
DEBUG ((DEBUG_INFO, "%a: AllocatePages failed\n", __FUNCTION__));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-12-13 09:16:56 +01:00
|
|
|
if (FdtItem) {
|
|
|
|
QemuFwCfgSelectItem (FdtItem);
|
|
|
|
QemuFwCfgReadBytes (FdtSize, NewBase);
|
|
|
|
} else {
|
|
|
|
CopyMem (NewBase, EmptyFdt, FdtSize);
|
|
|
|
}
|
2021-12-13 09:16:55 +01:00
|
|
|
|
|
|
|
FdtHobData = BuildGuidHob (&gFdtHobGuid, sizeof (*FdtHobData));
|
|
|
|
if (FdtHobData == NULL) {
|
|
|
|
DEBUG ((DEBUG_INFO, "%a: BuildGuidHob failed\n", __FUNCTION__));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG ((
|
|
|
|
DEBUG_INFO,
|
|
|
|
"%a: fdt at 0x%x (size %d)\n",
|
|
|
|
__FUNCTION__,
|
|
|
|
NewBase,
|
|
|
|
FdtSize
|
|
|
|
));
|
|
|
|
*FdtHobData = (UINTN)NewBase;
|
|
|
|
}
|
|
|
|
|
2022-03-06 13:04:53 +01:00
|
|
|
VOID
|
|
|
|
MiscInitializationForMicrovm (
|
|
|
|
IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob
|
|
|
|
)
|
|
|
|
{
|
|
|
|
RETURN_STATUS PcdStatus;
|
|
|
|
|
|
|
|
ASSERT (PlatformInfoHob->HostBridgeDevId == 0xffff);
|
|
|
|
|
|
|
|
DEBUG ((DEBUG_INFO, "%a: microvm\n", __FUNCTION__));
|
|
|
|
//
|
|
|
|
// Disable A20 Mask
|
|
|
|
//
|
|
|
|
IoOr8 (0x92, BIT1);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Build the CPU HOB with guest RAM size dependent address width and 16-bits
|
|
|
|
// of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
|
|
|
|
// S3 resume as well, so we build it unconditionally.)
|
|
|
|
//
|
|
|
|
BuildCpuHob (PlatformInfoHob->PhysMemAddressWidth, 16);
|
|
|
|
|
|
|
|
MicrovmInitialization ();
|
|
|
|
PcdStatus = PcdSet16S (
|
|
|
|
PcdOvmfHostBridgePciDevId,
|
|
|
|
MICROVM_PSEUDO_DEVICE_ID
|
|
|
|
);
|
|
|
|
ASSERT_RETURN_ERROR (PcdStatus);
|
|
|
|
}
|
|
|
|
|
2009-05-27 23:10:18 +02:00
|
|
|
VOID
|
|
|
|
MiscInitialization (
|
2022-03-06 03:20:36 +01:00
|
|
|
IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob
|
2009-05-27 23:10:18 +02:00
|
|
|
)
|
|
|
|
{
|
2021-12-05 23:54:09 +01:00
|
|
|
UINTN PmCmd;
|
|
|
|
UINTN Pmba;
|
|
|
|
UINT32 PmbaAndVal;
|
|
|
|
UINT32 PmbaOrVal;
|
|
|
|
UINTN AcpiCtlReg;
|
|
|
|
UINT8 AcpiEnBit;
|
|
|
|
RETURN_STATUS PcdStatus;
|
2014-11-14 01:37:26 +01:00
|
|
|
|
2009-05-27 23:10:18 +02:00
|
|
|
//
|
|
|
|
// Disable A20 Mask
|
|
|
|
//
|
2010-10-13 09:07:29 +02:00
|
|
|
IoOr8 (0x92, BIT1);
|
2009-05-27 23:10:18 +02:00
|
|
|
|
|
|
|
//
|
2015-06-26 18:09:43 +02:00
|
|
|
// Build the CPU HOB with guest RAM size dependent address width and 16-bits
|
|
|
|
// of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
|
|
|
|
// S3 resume as well, so we build it unconditionally.)
|
2009-05-27 23:10:18 +02:00
|
|
|
//
|
2022-03-06 03:20:36 +01:00
|
|
|
BuildCpuHob (PlatformInfoHob->PhysMemAddressWidth, 16);
|
2011-01-13 06:46:24 +01:00
|
|
|
|
2014-11-14 01:37:26 +01:00
|
|
|
//
|
2015-06-09 17:28:09 +02:00
|
|
|
// Determine platform type and save Host Bridge DID to PCD
|
2014-11-14 01:37:26 +01:00
|
|
|
//
|
2022-03-06 03:20:36 +01:00
|
|
|
switch (PlatformInfoHob->HostBridgeDevId) {
|
2014-11-14 01:37:26 +01:00
|
|
|
case INTEL_82441_DEVICE_ID:
|
OvmfPkg: Q35: Use correct ACPI PM control register:bit
On PIIX4, function 3, the PMREGMISC register at offset 0x80, with
default value 0x00 has its bit 0 (PMIOSE) indicate whether the PM
IO space given in the PMBA register (offset 0x40) is enabled.
PMBA must be configured *before* setting this bit.
On Q35/ICH9+, function 0x1f, the equivalent role is fulfilled by
bit 7 (ACPI_EN) in the ACPI Control Register (ACPI_CNTL) at offset
0x44, also with a default value of 0x00.
Currently, OVMF hangs when Q35 reboots, because while PMBA is reset
by QEMU, the register at offset 0x80 (matching PMREGMISC on PIIX4)
is not reset, since it has a completely different meaning on LPC.
As such, the power management initialization logic in OVMF finds
the "PMIOSE" bit enabled after a reboot and decides to skip setting
PMBA. This causes the ACPI timer tick routine to read a constant
value from the wrong register, which in turn causes the ACPI delay
loop to hang indefinitely.
This patch modifies the Base[Rom]AcpiTimerLib constructors and the
PlatformPei ACPI PM init routines to use ACPI_CNTL:ACPI_EN instead
of PMREGMISC:PMIOSE when running on Q35.
Reported-by: Reza Jelveh <reza.jelveh@tuhh.de>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17076 6f19259b-4bc3-4df7-8a09-765794883524
2015-03-26 20:06:07 +01:00
|
|
|
PmCmd = POWER_MGMT_REGISTER_PIIX4 (PCI_COMMAND_OFFSET);
|
2015-05-13 11:31:49 +02:00
|
|
|
Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
|
OvmfPkg: determine PMBA value dependent on host bridge device ID
In this patch, the AcpiTimerLib instances, ResetSystemLib, and PlatformPei
are modified together in order to keep VMs functional across a bisection:
they all must agree on the PMBA value used.
ResetSystemLib must not use dynamic PCDs. With SOURCE_DEBUG_ENABLE, it
gets linked into the debug agent, therefore the same restrictions apply to
it as to BaseRomAcpiTimerLib. Luckily, AcpiPmControl() is only used for
powering off the virtual machine, thus the extra cost of a PCI config
space read, compared to a PcdGet16(), should be negligible.
This is the patch that moves the PMBA to IO port 0x0600 on Q35 in
practice.
The ResetSystemLib change is easiest to verify with the "reset -s" command
in the UEFI shell (which goes through gRT->ResetSystem() and, in OVMF,
PcAtChipsetPkg/KbcResetDxe).
Cc: Gabriel Somlo <somlo@cmu.edu>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1333238
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Tested-by: Gabriel Somlo <somlo@cmu.edu>
2016-05-09 21:04:47 +02:00
|
|
|
PmbaAndVal = ~(UINT32)PIIX4_PMBA_MASK;
|
|
|
|
PmbaOrVal = PIIX4_PMBA_VALUE;
|
2015-05-13 11:31:49 +02:00
|
|
|
AcpiCtlReg = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMREGMISC);
|
|
|
|
AcpiEnBit = PIIX4_PMREGMISC_PMIOSE;
|
2014-11-14 01:37:26 +01:00
|
|
|
break;
|
|
|
|
case INTEL_Q35_MCH_DEVICE_ID:
|
OvmfPkg: Q35: Use correct ACPI PM control register:bit
On PIIX4, function 3, the PMREGMISC register at offset 0x80, with
default value 0x00 has its bit 0 (PMIOSE) indicate whether the PM
IO space given in the PMBA register (offset 0x40) is enabled.
PMBA must be configured *before* setting this bit.
On Q35/ICH9+, function 0x1f, the equivalent role is fulfilled by
bit 7 (ACPI_EN) in the ACPI Control Register (ACPI_CNTL) at offset
0x44, also with a default value of 0x00.
Currently, OVMF hangs when Q35 reboots, because while PMBA is reset
by QEMU, the register at offset 0x80 (matching PMREGMISC on PIIX4)
is not reset, since it has a completely different meaning on LPC.
As such, the power management initialization logic in OVMF finds
the "PMIOSE" bit enabled after a reboot and decides to skip setting
PMBA. This causes the ACPI timer tick routine to read a constant
value from the wrong register, which in turn causes the ACPI delay
loop to hang indefinitely.
This patch modifies the Base[Rom]AcpiTimerLib constructors and the
PlatformPei ACPI PM init routines to use ACPI_CNTL:ACPI_EN instead
of PMREGMISC:PMIOSE when running on Q35.
Reported-by: Reza Jelveh <reza.jelveh@tuhh.de>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17076 6f19259b-4bc3-4df7-8a09-765794883524
2015-03-26 20:06:07 +01:00
|
|
|
PmCmd = POWER_MGMT_REGISTER_Q35 (PCI_COMMAND_OFFSET);
|
2015-05-13 11:31:44 +02:00
|
|
|
Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
|
OvmfPkg: determine PMBA value dependent on host bridge device ID
In this patch, the AcpiTimerLib instances, ResetSystemLib, and PlatformPei
are modified together in order to keep VMs functional across a bisection:
they all must agree on the PMBA value used.
ResetSystemLib must not use dynamic PCDs. With SOURCE_DEBUG_ENABLE, it
gets linked into the debug agent, therefore the same restrictions apply to
it as to BaseRomAcpiTimerLib. Luckily, AcpiPmControl() is only used for
powering off the virtual machine, thus the extra cost of a PCI config
space read, compared to a PcdGet16(), should be negligible.
This is the patch that moves the PMBA to IO port 0x0600 on Q35 in
practice.
The ResetSystemLib change is easiest to verify with the "reset -s" command
in the UEFI shell (which goes through gRT->ResetSystem() and, in OVMF,
PcAtChipsetPkg/KbcResetDxe).
Cc: Gabriel Somlo <somlo@cmu.edu>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1333238
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Tested-by: Gabriel Somlo <somlo@cmu.edu>
2016-05-09 21:04:47 +02:00
|
|
|
PmbaAndVal = ~(UINT32)ICH9_PMBASE_MASK;
|
|
|
|
PmbaOrVal = ICH9_PMBASE_VALUE;
|
2015-05-13 11:31:44 +02:00
|
|
|
AcpiCtlReg = POWER_MGMT_REGISTER_Q35 (ICH9_ACPI_CNTL);
|
|
|
|
AcpiEnBit = ICH9_ACPI_CNTL_ACPI_EN;
|
2014-11-14 01:37:26 +01:00
|
|
|
break;
|
2021-12-10 15:41:54 +01:00
|
|
|
case CLOUDHV_DEVICE_ID:
|
2022-03-06 13:09:00 +01:00
|
|
|
break;
|
2014-11-14 01:37:26 +01:00
|
|
|
default:
|
2021-12-05 23:54:09 +01:00
|
|
|
DEBUG ((
|
|
|
|
DEBUG_ERROR,
|
|
|
|
"%a: Unknown Host Bridge Device ID: 0x%04x\n",
|
|
|
|
__FUNCTION__,
|
2022-03-06 03:20:36 +01:00
|
|
|
PlatformInfoHob->HostBridgeDevId
|
2021-12-05 23:54:09 +01:00
|
|
|
));
|
2014-11-14 01:37:26 +01:00
|
|
|
ASSERT (FALSE);
|
|
|
|
return;
|
|
|
|
}
|
2021-12-05 23:54:09 +01:00
|
|
|
|
2022-03-06 03:20:36 +01:00
|
|
|
PcdStatus = PcdSet16S (PcdOvmfHostBridgePciDevId, PlatformInfoHob->HostBridgeDevId);
|
2016-10-21 11:59:36 +02:00
|
|
|
ASSERT_RETURN_ERROR (PcdStatus);
|
2014-11-14 01:37:26 +01:00
|
|
|
|
2022-03-06 13:09:00 +01:00
|
|
|
if (PlatformInfoHob->HostBridgeDevId == CLOUDHV_DEVICE_ID) {
|
|
|
|
DEBUG ((DEBUG_INFO, "%a: Cloud Hypervisor is done.\n", __FUNCTION__));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-09-12 09:19:28 +02:00
|
|
|
//
|
2021-05-26 22:14:24 +02:00
|
|
|
// If the appropriate IOspace enable bit is set, assume the ACPI PMBA has
|
|
|
|
// been configured and skip the setup here. This matches the logic in
|
|
|
|
// AcpiTimerLibConstructor ().
|
2012-09-12 09:19:28 +02:00
|
|
|
//
|
OvmfPkg: Q35: Use correct ACPI PM control register:bit
On PIIX4, function 3, the PMREGMISC register at offset 0x80, with
default value 0x00 has its bit 0 (PMIOSE) indicate whether the PM
IO space given in the PMBA register (offset 0x40) is enabled.
PMBA must be configured *before* setting this bit.
On Q35/ICH9+, function 0x1f, the equivalent role is fulfilled by
bit 7 (ACPI_EN) in the ACPI Control Register (ACPI_CNTL) at offset
0x44, also with a default value of 0x00.
Currently, OVMF hangs when Q35 reboots, because while PMBA is reset
by QEMU, the register at offset 0x80 (matching PMREGMISC on PIIX4)
is not reset, since it has a completely different meaning on LPC.
As such, the power management initialization logic in OVMF finds
the "PMIOSE" bit enabled after a reboot and decides to skip setting
PMBA. This causes the ACPI timer tick routine to read a constant
value from the wrong register, which in turn causes the ACPI delay
loop to hang indefinitely.
This patch modifies the Base[Rom]AcpiTimerLib constructors and the
PlatformPei ACPI PM init routines to use ACPI_CNTL:ACPI_EN instead
of PMREGMISC:PMIOSE when running on Q35.
Reported-by: Reza Jelveh <reza.jelveh@tuhh.de>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17076 6f19259b-4bc3-4df7-8a09-765794883524
2015-03-26 20:06:07 +01:00
|
|
|
if ((PciRead8 (AcpiCtlReg) & AcpiEnBit) == 0) {
|
2011-08-05 17:43:05 +02:00
|
|
|
//
|
OvmfPkg: Q35: Use correct ACPI PM control register:bit
On PIIX4, function 3, the PMREGMISC register at offset 0x80, with
default value 0x00 has its bit 0 (PMIOSE) indicate whether the PM
IO space given in the PMBA register (offset 0x40) is enabled.
PMBA must be configured *before* setting this bit.
On Q35/ICH9+, function 0x1f, the equivalent role is fulfilled by
bit 7 (ACPI_EN) in the ACPI Control Register (ACPI_CNTL) at offset
0x44, also with a default value of 0x00.
Currently, OVMF hangs when Q35 reboots, because while PMBA is reset
by QEMU, the register at offset 0x80 (matching PMREGMISC on PIIX4)
is not reset, since it has a completely different meaning on LPC.
As such, the power management initialization logic in OVMF finds
the "PMIOSE" bit enabled after a reboot and decides to skip setting
PMBA. This causes the ACPI timer tick routine to read a constant
value from the wrong register, which in turn causes the ACPI delay
loop to hang indefinitely.
This patch modifies the Base[Rom]AcpiTimerLib constructors and the
PlatformPei ACPI PM init routines to use ACPI_CNTL:ACPI_EN instead
of PMREGMISC:PMIOSE when running on Q35.
Reported-by: Reza Jelveh <reza.jelveh@tuhh.de>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17076 6f19259b-4bc3-4df7-8a09-765794883524
2015-03-26 20:06:07 +01:00
|
|
|
// The PEI phase should be exited with fully accessibe ACPI PM IO space:
|
OvmfPkg: enable PIIX4 IO space in the PEI phase
I. There are at least three locations in OvmfPkg that manipulate the PMBA
and related PIIX4 registers.
1. MiscInitialization() [OvmfPkg/PlatformPei/Platform.c]
module type: PEIM -- Pre-EFI Initialization Module
(a) currently sets the PMBA only: 00.01.3 / 0x40 bits [15:6]
2. AcpiTimerLibConstructor() [OvmfPkg/Library/AcpiTimerLib/AcpiTimerLib.c]
module type: BASE -- probably callable anywhere after PEI
(a) sets the PMBA if needed: 00.01.3 / 0x40 bits [15:6]
(b) sets PCICMD/IOSE if needed: 00.01.3 / 0x04 bit 0
(c) sets PMREGMISC/PMIOSE: 00.01.3 / 0x80 bit 0
3. AcpiInitialization() [OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c]
module type: DXE_DRIVER -- Driver eXecution Environment
(a) sets SCI_EN, which depends on correct PMBA setting from earlier
(
The relative order of #1 and #3 is dictated minimally by their module
types. Said relative order can be verified with the boot log:
27 Loading PEIM at 0x00000822320 EntryPoint=0x00000822580
PlatformPei.efi
28 Platform PEIM Loaded
1259 PlatformBdsInit
1270 PlatformBdsPolicyBehavior
Line 28 is printed by InitializePlatform()
[OvmfPkg/PlatformPei/Platform.c] which is the entry point of that
module. The other two lines are printed by the corresponding functions
in "OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c".
)
Currently #2 (AcpiTimerLibConstructor()) is called in a random spot
(whenever it gets loaded from the firmware image) and masks the
insufficient setup in #1. We shouldn't depend on that, PEI should finish
with IO space being fully accessibe. In addition, PEI should program the
same PMBA value as AcpiTimerLib.
II. The PEI change notwithstanding, AcpiTimerLib should stay defensive and
ensure proper PM configuration for itself (either by confirming or by
doing).
III. Considering a possible cleanup/unification of #2 and #3: timer
functions relying on AcpiTimerLibConstructor(),
- MicroSecondDelay()
- NanoSecondDelay()
- GetPerformanceCounter()
- GetPerformanceCounterProperties()
- GetTimeInNanoSecond()
may be called before #3 is reached (in Boot Device Selection phase), so we
should not move the initialization from #2 to #3. (Again, AcpiTimerLib
should contain its own setup.)
We should also not move #3 to an earlier phase -- SCI_EN is premature
unless we're about to boot real soon ("enable generation of SCI upon
assertion of PWRBTN_STS, LID_STS, THRM_STS, or GPI_STS bits").
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13722 6f19259b-4bc3-4df7-8a09-765794883524
2012-09-12 09:19:16 +02:00
|
|
|
// 1. set PMBA
|
2011-08-05 17:43:05 +02:00
|
|
|
//
|
OvmfPkg: determine PMBA value dependent on host bridge device ID
In this patch, the AcpiTimerLib instances, ResetSystemLib, and PlatformPei
are modified together in order to keep VMs functional across a bisection:
they all must agree on the PMBA value used.
ResetSystemLib must not use dynamic PCDs. With SOURCE_DEBUG_ENABLE, it
gets linked into the debug agent, therefore the same restrictions apply to
it as to BaseRomAcpiTimerLib. Luckily, AcpiPmControl() is only used for
powering off the virtual machine, thus the extra cost of a PCI config
space read, compared to a PcdGet16(), should be negligible.
This is the patch that moves the PMBA to IO port 0x0600 on Q35 in
practice.
The ResetSystemLib change is easiest to verify with the "reset -s" command
in the UEFI shell (which goes through gRT->ResetSystem() and, in OVMF,
PcAtChipsetPkg/KbcResetDxe).
Cc: Gabriel Somlo <somlo@cmu.edu>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1333238
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Tested-by: Gabriel Somlo <somlo@cmu.edu>
2016-05-09 21:04:47 +02:00
|
|
|
PciAndThenOr32 (Pmba, PmbaAndVal, PmbaOrVal);
|
OvmfPkg: enable PIIX4 IO space in the PEI phase
I. There are at least three locations in OvmfPkg that manipulate the PMBA
and related PIIX4 registers.
1. MiscInitialization() [OvmfPkg/PlatformPei/Platform.c]
module type: PEIM -- Pre-EFI Initialization Module
(a) currently sets the PMBA only: 00.01.3 / 0x40 bits [15:6]
2. AcpiTimerLibConstructor() [OvmfPkg/Library/AcpiTimerLib/AcpiTimerLib.c]
module type: BASE -- probably callable anywhere after PEI
(a) sets the PMBA if needed: 00.01.3 / 0x40 bits [15:6]
(b) sets PCICMD/IOSE if needed: 00.01.3 / 0x04 bit 0
(c) sets PMREGMISC/PMIOSE: 00.01.3 / 0x80 bit 0
3. AcpiInitialization() [OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c]
module type: DXE_DRIVER -- Driver eXecution Environment
(a) sets SCI_EN, which depends on correct PMBA setting from earlier
(
The relative order of #1 and #3 is dictated minimally by their module
types. Said relative order can be verified with the boot log:
27 Loading PEIM at 0x00000822320 EntryPoint=0x00000822580
PlatformPei.efi
28 Platform PEIM Loaded
1259 PlatformBdsInit
1270 PlatformBdsPolicyBehavior
Line 28 is printed by InitializePlatform()
[OvmfPkg/PlatformPei/Platform.c] which is the entry point of that
module. The other two lines are printed by the corresponding functions
in "OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c".
)
Currently #2 (AcpiTimerLibConstructor()) is called in a random spot
(whenever it gets loaded from the firmware image) and masks the
insufficient setup in #1. We shouldn't depend on that, PEI should finish
with IO space being fully accessibe. In addition, PEI should program the
same PMBA value as AcpiTimerLib.
II. The PEI change notwithstanding, AcpiTimerLib should stay defensive and
ensure proper PM configuration for itself (either by confirming or by
doing).
III. Considering a possible cleanup/unification of #2 and #3: timer
functions relying on AcpiTimerLibConstructor(),
- MicroSecondDelay()
- NanoSecondDelay()
- GetPerformanceCounter()
- GetPerformanceCounterProperties()
- GetTimeInNanoSecond()
may be called before #3 is reached (in Boot Device Selection phase), so we
should not move the initialization from #2 to #3. (Again, AcpiTimerLib
should contain its own setup.)
We should also not move #3 to an earlier phase -- SCI_EN is premature
unless we're about to boot real soon ("enable generation of SCI upon
assertion of PWRBTN_STS, LID_STS, THRM_STS, or GPI_STS bits").
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13722 6f19259b-4bc3-4df7-8a09-765794883524
2012-09-12 09:19:16 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// 2. set PCICMD/IOSE
|
|
|
|
//
|
2014-11-14 01:37:26 +01:00
|
|
|
PciOr8 (PmCmd, EFI_PCI_COMMAND_IO_SPACE);
|
OvmfPkg: enable PIIX4 IO space in the PEI phase
I. There are at least three locations in OvmfPkg that manipulate the PMBA
and related PIIX4 registers.
1. MiscInitialization() [OvmfPkg/PlatformPei/Platform.c]
module type: PEIM -- Pre-EFI Initialization Module
(a) currently sets the PMBA only: 00.01.3 / 0x40 bits [15:6]
2. AcpiTimerLibConstructor() [OvmfPkg/Library/AcpiTimerLib/AcpiTimerLib.c]
module type: BASE -- probably callable anywhere after PEI
(a) sets the PMBA if needed: 00.01.3 / 0x40 bits [15:6]
(b) sets PCICMD/IOSE if needed: 00.01.3 / 0x04 bit 0
(c) sets PMREGMISC/PMIOSE: 00.01.3 / 0x80 bit 0
3. AcpiInitialization() [OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c]
module type: DXE_DRIVER -- Driver eXecution Environment
(a) sets SCI_EN, which depends on correct PMBA setting from earlier
(
The relative order of #1 and #3 is dictated minimally by their module
types. Said relative order can be verified with the boot log:
27 Loading PEIM at 0x00000822320 EntryPoint=0x00000822580
PlatformPei.efi
28 Platform PEIM Loaded
1259 PlatformBdsInit
1270 PlatformBdsPolicyBehavior
Line 28 is printed by InitializePlatform()
[OvmfPkg/PlatformPei/Platform.c] which is the entry point of that
module. The other two lines are printed by the corresponding functions
in "OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c".
)
Currently #2 (AcpiTimerLibConstructor()) is called in a random spot
(whenever it gets loaded from the firmware image) and masks the
insufficient setup in #1. We shouldn't depend on that, PEI should finish
with IO space being fully accessibe. In addition, PEI should program the
same PMBA value as AcpiTimerLib.
II. The PEI change notwithstanding, AcpiTimerLib should stay defensive and
ensure proper PM configuration for itself (either by confirming or by
doing).
III. Considering a possible cleanup/unification of #2 and #3: timer
functions relying on AcpiTimerLibConstructor(),
- MicroSecondDelay()
- NanoSecondDelay()
- GetPerformanceCounter()
- GetPerformanceCounterProperties()
- GetTimeInNanoSecond()
may be called before #3 is reached (in Boot Device Selection phase), so we
should not move the initialization from #2 to #3. (Again, AcpiTimerLib
should contain its own setup.)
We should also not move #3 to an earlier phase -- SCI_EN is premature
unless we're about to boot real soon ("enable generation of SCI upon
assertion of PWRBTN_STS, LID_STS, THRM_STS, or GPI_STS bits").
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13722 6f19259b-4bc3-4df7-8a09-765794883524
2012-09-12 09:19:16 +02:00
|
|
|
|
|
|
|
//
|
OvmfPkg: Q35: Use correct ACPI PM control register:bit
On PIIX4, function 3, the PMREGMISC register at offset 0x80, with
default value 0x00 has its bit 0 (PMIOSE) indicate whether the PM
IO space given in the PMBA register (offset 0x40) is enabled.
PMBA must be configured *before* setting this bit.
On Q35/ICH9+, function 0x1f, the equivalent role is fulfilled by
bit 7 (ACPI_EN) in the ACPI Control Register (ACPI_CNTL) at offset
0x44, also with a default value of 0x00.
Currently, OVMF hangs when Q35 reboots, because while PMBA is reset
by QEMU, the register at offset 0x80 (matching PMREGMISC on PIIX4)
is not reset, since it has a completely different meaning on LPC.
As such, the power management initialization logic in OVMF finds
the "PMIOSE" bit enabled after a reboot and decides to skip setting
PMBA. This causes the ACPI timer tick routine to read a constant
value from the wrong register, which in turn causes the ACPI delay
loop to hang indefinitely.
This patch modifies the Base[Rom]AcpiTimerLib constructors and the
PlatformPei ACPI PM init routines to use ACPI_CNTL:ACPI_EN instead
of PMREGMISC:PMIOSE when running on Q35.
Reported-by: Reza Jelveh <reza.jelveh@tuhh.de>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17076 6f19259b-4bc3-4df7-8a09-765794883524
2015-03-26 20:06:07 +01:00
|
|
|
// 3. set ACPI PM IO enable bit (PMREGMISC:PMIOSE or ACPI_CNTL:ACPI_EN)
|
OvmfPkg: enable PIIX4 IO space in the PEI phase
I. There are at least three locations in OvmfPkg that manipulate the PMBA
and related PIIX4 registers.
1. MiscInitialization() [OvmfPkg/PlatformPei/Platform.c]
module type: PEIM -- Pre-EFI Initialization Module
(a) currently sets the PMBA only: 00.01.3 / 0x40 bits [15:6]
2. AcpiTimerLibConstructor() [OvmfPkg/Library/AcpiTimerLib/AcpiTimerLib.c]
module type: BASE -- probably callable anywhere after PEI
(a) sets the PMBA if needed: 00.01.3 / 0x40 bits [15:6]
(b) sets PCICMD/IOSE if needed: 00.01.3 / 0x04 bit 0
(c) sets PMREGMISC/PMIOSE: 00.01.3 / 0x80 bit 0
3. AcpiInitialization() [OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c]
module type: DXE_DRIVER -- Driver eXecution Environment
(a) sets SCI_EN, which depends on correct PMBA setting from earlier
(
The relative order of #1 and #3 is dictated minimally by their module
types. Said relative order can be verified with the boot log:
27 Loading PEIM at 0x00000822320 EntryPoint=0x00000822580
PlatformPei.efi
28 Platform PEIM Loaded
1259 PlatformBdsInit
1270 PlatformBdsPolicyBehavior
Line 28 is printed by InitializePlatform()
[OvmfPkg/PlatformPei/Platform.c] which is the entry point of that
module. The other two lines are printed by the corresponding functions
in "OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c".
)
Currently #2 (AcpiTimerLibConstructor()) is called in a random spot
(whenever it gets loaded from the firmware image) and masks the
insufficient setup in #1. We shouldn't depend on that, PEI should finish
with IO space being fully accessibe. In addition, PEI should program the
same PMBA value as AcpiTimerLib.
II. The PEI change notwithstanding, AcpiTimerLib should stay defensive and
ensure proper PM configuration for itself (either by confirming or by
doing).
III. Considering a possible cleanup/unification of #2 and #3: timer
functions relying on AcpiTimerLibConstructor(),
- MicroSecondDelay()
- NanoSecondDelay()
- GetPerformanceCounter()
- GetPerformanceCounterProperties()
- GetTimeInNanoSecond()
may be called before #3 is reached (in Boot Device Selection phase), so we
should not move the initialization from #2 to #3. (Again, AcpiTimerLib
should contain its own setup.)
We should also not move #3 to an earlier phase -- SCI_EN is premature
unless we're about to boot real soon ("enable generation of SCI upon
assertion of PWRBTN_STS, LID_STS, THRM_STS, or GPI_STS bits").
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13722 6f19259b-4bc3-4df7-8a09-765794883524
2012-09-12 09:19:16 +02:00
|
|
|
//
|
OvmfPkg: Q35: Use correct ACPI PM control register:bit
On PIIX4, function 3, the PMREGMISC register at offset 0x80, with
default value 0x00 has its bit 0 (PMIOSE) indicate whether the PM
IO space given in the PMBA register (offset 0x40) is enabled.
PMBA must be configured *before* setting this bit.
On Q35/ICH9+, function 0x1f, the equivalent role is fulfilled by
bit 7 (ACPI_EN) in the ACPI Control Register (ACPI_CNTL) at offset
0x44, also with a default value of 0x00.
Currently, OVMF hangs when Q35 reboots, because while PMBA is reset
by QEMU, the register at offset 0x80 (matching PMREGMISC on PIIX4)
is not reset, since it has a completely different meaning on LPC.
As such, the power management initialization logic in OVMF finds
the "PMIOSE" bit enabled after a reboot and decides to skip setting
PMBA. This causes the ACPI timer tick routine to read a constant
value from the wrong register, which in turn causes the ACPI delay
loop to hang indefinitely.
This patch modifies the Base[Rom]AcpiTimerLib constructors and the
PlatformPei ACPI PM init routines to use ACPI_CNTL:ACPI_EN instead
of PMREGMISC:PMIOSE when running on Q35.
Reported-by: Reza Jelveh <reza.jelveh@tuhh.de>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17076 6f19259b-4bc3-4df7-8a09-765794883524
2015-03-26 20:06:07 +01:00
|
|
|
PciOr8 (AcpiCtlReg, AcpiEnBit);
|
2011-08-05 17:43:05 +02:00
|
|
|
}
|
2015-06-09 17:28:15 +02:00
|
|
|
|
2022-03-06 03:20:36 +01:00
|
|
|
if (PlatformInfoHob->HostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
|
2015-06-09 17:28:15 +02:00
|
|
|
//
|
|
|
|
// Set Root Complex Register Block BAR
|
|
|
|
//
|
|
|
|
PciWrite32 (
|
|
|
|
POWER_MGMT_REGISTER_Q35 (ICH9_RCBA),
|
|
|
|
ICH9_ROOT_COMPLEX_BASE | ICH9_RCBA_EN
|
|
|
|
);
|
2016-03-03 20:46:22 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// Set PCI Express Register Range Base Address
|
|
|
|
//
|
|
|
|
PciExBarInitialization ();
|
2015-06-09 17:28:15 +02:00
|
|
|
}
|
2009-05-27 23:10:18 +02:00
|
|
|
}
|
|
|
|
|
2011-03-22 02:55:08 +01:00
|
|
|
VOID
|
|
|
|
BootModeInitialization (
|
2022-03-06 03:20:36 +01:00
|
|
|
IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
|
2011-03-22 02:55:08 +01:00
|
|
|
)
|
|
|
|
{
|
2021-12-05 23:54:09 +01:00
|
|
|
EFI_STATUS Status;
|
2014-03-04 09:01:32 +01:00
|
|
|
|
2022-02-12 07:06:46 +01:00
|
|
|
if (PlatformCmosRead8 (0xF) == 0xFE) {
|
2022-03-06 03:20:36 +01:00
|
|
|
PlatformInfoHob->BootMode = BOOT_ON_S3_RESUME;
|
2014-03-04 09:01:32 +01:00
|
|
|
}
|
2021-12-05 23:54:09 +01:00
|
|
|
|
2022-02-12 07:06:46 +01:00
|
|
|
PlatformCmosWrite8 (0xF, 0x00);
|
2011-03-22 05:54:18 +01:00
|
|
|
|
2022-03-06 03:20:36 +01:00
|
|
|
Status = PeiServicesSetBootMode (PlatformInfoHob->BootMode);
|
2011-03-22 05:54:18 +01:00
|
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
|
|
|
|
Status = PeiServicesInstallPpi (mPpiBootMode);
|
|
|
|
ASSERT_EFI_ERROR (Status);
|
2011-03-22 02:55:08 +01:00
|
|
|
}
|
|
|
|
|
2009-09-07 22:18:17 +02:00
|
|
|
VOID
|
|
|
|
ReserveEmuVariableNvStore (
|
|
|
|
)
|
|
|
|
{
|
2021-12-05 23:54:09 +01:00
|
|
|
EFI_PHYSICAL_ADDRESS VariableStore;
|
|
|
|
RETURN_STATUS PcdStatus;
|
2009-09-07 22:18:17 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// Allocate storage for NV variables early on so it will be
|
|
|
|
// at a consistent address. Since VM memory is preserved
|
|
|
|
// across reboots, this allows the NV variable storage to survive
|
|
|
|
// a VM reboot.
|
|
|
|
//
|
|
|
|
VariableStore =
|
|
|
|
(EFI_PHYSICAL_ADDRESS)(UINTN)
|
2021-12-05 23:54:09 +01:00
|
|
|
AllocateRuntimePages (
|
|
|
|
EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize))
|
|
|
|
);
|
|
|
|
DEBUG ((
|
|
|
|
DEBUG_INFO,
|
|
|
|
"Reserved variable store memory: 0x%lX; size: %dkb\n",
|
|
|
|
VariableStore,
|
|
|
|
(2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / 1024
|
|
|
|
));
|
2016-10-21 11:59:36 +02:00
|
|
|
PcdStatus = PcdSet64S (PcdEmuVariableNvStoreReserved, VariableStore);
|
|
|
|
ASSERT_RETURN_ERROR (PcdStatus);
|
2009-09-07 22:18:17 +02:00
|
|
|
}
|
|
|
|
|
2015-12-01 00:36:31 +01:00
|
|
|
VOID
|
|
|
|
S3Verification (
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
2021-12-05 23:54:09 +01:00
|
|
|
#if defined (MDE_CPU_X64)
|
2022-03-06 03:20:36 +01:00
|
|
|
if (mPlatformInfoHob.SmmSmramRequire && mPlatformInfoHob.S3Supported) {
|
2021-12-05 23:54:09 +01:00
|
|
|
DEBUG ((
|
|
|
|
DEBUG_ERROR,
|
|
|
|
"%a: S3Resume2Pei doesn't support X64 PEI + SMM yet.\n",
|
|
|
|
__FUNCTION__
|
|
|
|
));
|
|
|
|
DEBUG ((
|
|
|
|
DEBUG_ERROR,
|
2015-12-01 00:36:31 +01:00
|
|
|
"%a: Please disable S3 on the QEMU command line (see the README),\n",
|
2021-12-05 23:54:09 +01:00
|
|
|
__FUNCTION__
|
|
|
|
));
|
|
|
|
DEBUG ((
|
|
|
|
DEBUG_ERROR,
|
|
|
|
"%a: or build OVMF with \"OvmfPkgIa32X64.dsc\".\n",
|
|
|
|
__FUNCTION__
|
|
|
|
));
|
2015-12-01 00:36:31 +01:00
|
|
|
ASSERT (FALSE);
|
|
|
|
CpuDeadLoop ();
|
|
|
|
}
|
|
|
|
|
2021-12-05 23:54:09 +01:00
|
|
|
#endif
|
|
|
|
}
|
2015-12-01 00:36:31 +01:00
|
|
|
|
2019-09-20 13:36:56 +02:00
|
|
|
VOID
|
|
|
|
Q35BoardVerification (
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
2022-03-06 03:20:36 +01:00
|
|
|
if (mPlatformInfoHob.HostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
|
2019-09-20 13:36:56 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG ((
|
|
|
|
DEBUG_ERROR,
|
|
|
|
"%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "
|
|
|
|
"only DID=0x%04x (Q35) is supported\n",
|
|
|
|
__FUNCTION__,
|
2022-03-06 03:20:36 +01:00
|
|
|
mPlatformInfoHob.HostBridgeDevId,
|
2019-09-20 13:36:56 +02:00
|
|
|
INTEL_Q35_MCH_DEVICE_ID
|
|
|
|
));
|
|
|
|
ASSERT (FALSE);
|
|
|
|
CpuDeadLoop ();
|
|
|
|
}
|
|
|
|
|
2016-11-24 15:18:44 +01:00
|
|
|
/**
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
Fetch the boot CPU count and the possible CPU count from QEMU, and expose
|
2022-03-06 14:40:28 +01:00
|
|
|
them to UefiCpuPkg modules. Set the MaxCpuCount field in PlatformInfoHob.
|
2016-11-24 15:18:44 +01:00
|
|
|
**/
|
|
|
|
VOID
|
2022-03-06 14:40:28 +01:00
|
|
|
PlatformMaxCpuCountInitialization (
|
2022-03-06 03:20:36 +01:00
|
|
|
IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
|
2016-11-24 15:18:44 +01:00
|
|
|
)
|
|
|
|
{
|
2022-03-06 14:40:28 +01:00
|
|
|
UINT16 BootCpuCount;
|
|
|
|
UINT32 MaxCpuCount;
|
2016-11-24 15:18:44 +01:00
|
|
|
|
|
|
|
//
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
// Try to fetch the boot CPU count.
|
2016-11-24 15:18:44 +01:00
|
|
|
//
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount);
|
|
|
|
BootCpuCount = QemuFwCfgRead16 ();
|
|
|
|
if (BootCpuCount == 0) {
|
|
|
|
//
|
|
|
|
// QEMU doesn't report the boot CPU count. (BootCpuCount == 0) will let
|
|
|
|
// MpInitLib count APs up to (PcdCpuMaxLogicalProcessorNumber - 1), or
|
|
|
|
// until PcdCpuApInitTimeOutInMicroSeconds elapses (whichever is reached
|
|
|
|
// first).
|
|
|
|
//
|
|
|
|
DEBUG ((DEBUG_WARN, "%a: boot CPU count unavailable\n", __FUNCTION__));
|
2022-03-06 03:20:36 +01:00
|
|
|
MaxCpuCount = PlatformInfoHob->DefaultMaxCpuNumber;
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
} else {
|
|
|
|
//
|
|
|
|
// We will expose BootCpuCount to MpInitLib. MpInitLib will count APs up to
|
|
|
|
// (BootCpuCount - 1) precisely, regardless of timeout.
|
|
|
|
//
|
|
|
|
// Now try to fetch the possible CPU count.
|
|
|
|
//
|
2021-12-05 23:54:09 +01:00
|
|
|
UINTN CpuHpBase;
|
|
|
|
UINT32 CmdData2;
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
|
2022-03-06 03:20:36 +01:00
|
|
|
CpuHpBase = ((PlatformInfoHob->HostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) ?
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
ICH9_CPU_HOTPLUG_BASE : PIIX4_CPU_HOTPLUG_BASE);
|
|
|
|
|
|
|
|
//
|
|
|
|
// If only legacy mode is available in the CPU hotplug register block, or
|
|
|
|
// the register block is completely missing, then the writes below are
|
|
|
|
// no-ops.
|
|
|
|
//
|
|
|
|
// 1. Switch the hotplug register block to modern mode.
|
|
|
|
//
|
|
|
|
IoWrite32 (CpuHpBase + QEMU_CPUHP_W_CPU_SEL, 0);
|
|
|
|
//
|
|
|
|
// 2. Select a valid CPU for deterministic reading of
|
|
|
|
// QEMU_CPUHP_R_CMD_DATA2.
|
|
|
|
//
|
|
|
|
// CPU#0 is always valid; it is the always present and non-removable
|
|
|
|
// BSP.
|
|
|
|
//
|
|
|
|
IoWrite32 (CpuHpBase + QEMU_CPUHP_W_CPU_SEL, 0);
|
|
|
|
//
|
|
|
|
// 3. Send a command after which QEMU_CPUHP_R_CMD_DATA2 is specified to
|
|
|
|
// read as zero, and which does not invalidate the selector. (The
|
|
|
|
// selector may change, but it must not become invalid.)
|
|
|
|
//
|
|
|
|
// Send QEMU_CPUHP_CMD_GET_PENDING, as it will prove useful later.
|
|
|
|
//
|
|
|
|
IoWrite8 (CpuHpBase + QEMU_CPUHP_W_CMD, QEMU_CPUHP_CMD_GET_PENDING);
|
|
|
|
//
|
|
|
|
// 4. Read QEMU_CPUHP_R_CMD_DATA2.
|
|
|
|
//
|
|
|
|
// If the register block is entirely missing, then this is an unassigned
|
|
|
|
// IO read, returning all-bits-one.
|
|
|
|
//
|
|
|
|
// If only legacy mode is available, then bit#0 stands for CPU#0 in the
|
|
|
|
// "CPU present bitmap". CPU#0 is always present.
|
|
|
|
//
|
|
|
|
// Otherwise, QEMU_CPUHP_R_CMD_DATA2 is either still reserved (returning
|
|
|
|
// all-bits-zero), or it is specified to read as zero after the above
|
|
|
|
// steps. Both cases confirm modern mode.
|
|
|
|
//
|
|
|
|
CmdData2 = IoRead32 (CpuHpBase + QEMU_CPUHP_R_CMD_DATA2);
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "%a: CmdData2=0x%x\n", __FUNCTION__, CmdData2));
|
|
|
|
if (CmdData2 != 0) {
|
|
|
|
//
|
|
|
|
// QEMU doesn't support the modern CPU hotplug interface. Assume that the
|
|
|
|
// possible CPU count equals the boot CPU count (precluding hotplug).
|
|
|
|
//
|
2021-12-05 23:54:09 +01:00
|
|
|
DEBUG ((
|
|
|
|
DEBUG_WARN,
|
|
|
|
"%a: modern CPU hotplug interface unavailable\n",
|
|
|
|
__FUNCTION__
|
|
|
|
));
|
2022-03-06 03:20:36 +01:00
|
|
|
MaxCpuCount = BootCpuCount;
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
} else {
|
|
|
|
//
|
|
|
|
// Grab the possible CPU count from the modern CPU hotplug interface.
|
|
|
|
//
|
2021-12-05 23:54:09 +01:00
|
|
|
UINT32 Present, Possible, Selected;
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
|
2021-12-05 23:54:09 +01:00
|
|
|
Present = 0;
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
Possible = 0;
|
|
|
|
|
|
|
|
//
|
|
|
|
// We've sent QEMU_CPUHP_CMD_GET_PENDING last; this ensures
|
|
|
|
// QEMU_CPUHP_RW_CMD_DATA can now be read usefully. However,
|
|
|
|
// QEMU_CPUHP_CMD_GET_PENDING may have selected a CPU with actual pending
|
|
|
|
// hotplug events; therefore, select CPU#0 forcibly.
|
|
|
|
//
|
|
|
|
IoWrite32 (CpuHpBase + QEMU_CPUHP_W_CPU_SEL, Possible);
|
|
|
|
|
|
|
|
do {
|
2021-12-05 23:54:09 +01:00
|
|
|
UINT8 CpuStatus;
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// Read the status of the currently selected CPU. This will help with a
|
|
|
|
// sanity check against "BootCpuCount".
|
|
|
|
//
|
|
|
|
CpuStatus = IoRead8 (CpuHpBase + QEMU_CPUHP_R_CPU_STAT);
|
|
|
|
if ((CpuStatus & QEMU_CPUHP_STAT_ENABLED) != 0) {
|
|
|
|
++Present;
|
|
|
|
}
|
2021-12-05 23:54:09 +01:00
|
|
|
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
//
|
|
|
|
// Attempt to select the next CPU.
|
|
|
|
//
|
|
|
|
++Possible;
|
|
|
|
IoWrite32 (CpuHpBase + QEMU_CPUHP_W_CPU_SEL, Possible);
|
|
|
|
//
|
|
|
|
// If the selection is successful, then the following read will return
|
|
|
|
// the selector (which we know is positive at this point). Otherwise,
|
|
|
|
// the read will return 0.
|
|
|
|
//
|
|
|
|
Selected = IoRead32 (CpuHpBase + QEMU_CPUHP_RW_CMD_DATA);
|
|
|
|
ASSERT (Selected == Possible || Selected == 0);
|
|
|
|
} while (Selected > 0);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Sanity check: fw_cfg and the modern CPU hotplug interface should
|
|
|
|
// return the same boot CPU count.
|
|
|
|
//
|
|
|
|
if (BootCpuCount != Present) {
|
2021-12-05 23:54:09 +01:00
|
|
|
DEBUG ((
|
|
|
|
DEBUG_WARN,
|
|
|
|
"%a: QEMU v2.7 reset bug: BootCpuCount=%d "
|
|
|
|
"Present=%u\n",
|
|
|
|
__FUNCTION__,
|
|
|
|
BootCpuCount,
|
|
|
|
Present
|
|
|
|
));
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
//
|
|
|
|
// The handling of QemuFwCfgItemSmpCpuCount, across CPU hotplug plus
|
|
|
|
// platform reset (including S3), was corrected in QEMU commit
|
|
|
|
// e3cadac073a9 ("pc: fix FW_CFG_NB_CPUS to account for -device added
|
|
|
|
// CPUs", 2016-11-16), part of release v2.8.0.
|
|
|
|
//
|
|
|
|
BootCpuCount = (UINT16)Present;
|
|
|
|
}
|
|
|
|
|
2022-03-06 03:20:36 +01:00
|
|
|
MaxCpuCount = Possible;
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
}
|
2016-11-24 15:18:44 +01:00
|
|
|
}
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
|
2021-12-05 23:54:09 +01:00
|
|
|
DEBUG ((
|
|
|
|
DEBUG_INFO,
|
2022-03-06 03:20:36 +01:00
|
|
|
"%a: BootCpuCount=%d MaxCpuCount=%u\n",
|
2021-12-05 23:54:09 +01:00
|
|
|
__FUNCTION__,
|
|
|
|
BootCpuCount,
|
2022-03-06 03:20:36 +01:00
|
|
|
MaxCpuCount
|
2021-12-05 23:54:09 +01:00
|
|
|
));
|
2022-03-06 03:20:36 +01:00
|
|
|
ASSERT (BootCpuCount <= MaxCpuCount);
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
|
2022-03-06 03:20:36 +01:00
|
|
|
PlatformInfoHob->PcdCpuMaxLogicalProcessorNumber = MaxCpuCount;
|
|
|
|
PlatformInfoHob->PcdCpuBootLogicalProcessorNumber = BootCpuCount;
|
2016-11-24 15:18:44 +01:00
|
|
|
}
|
|
|
|
|
2022-03-06 14:40:28 +01:00
|
|
|
/**
|
|
|
|
Fetch the boot CPU count and the possible CPU count from QEMU, and expose
|
|
|
|
them to UefiCpuPkg modules. Set the MaxCpuCount field in PlatformInfoHob.
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
MaxCpuCountInitialization (
|
|
|
|
IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
|
|
|
|
)
|
|
|
|
{
|
|
|
|
RETURN_STATUS PcdStatus;
|
|
|
|
|
|
|
|
PlatformMaxCpuCountInitialization (PlatformInfoHob);
|
|
|
|
|
|
|
|
PcdStatus = PcdSet32S (PcdCpuBootLogicalProcessorNumber, PlatformInfoHob->PcdCpuBootLogicalProcessorNumber);
|
|
|
|
ASSERT_RETURN_ERROR (PcdStatus);
|
|
|
|
PcdStatus = PcdSet32S (PcdCpuMaxLogicalProcessorNumber, PlatformInfoHob->PcdCpuMaxLogicalProcessorNumber);
|
|
|
|
ASSERT_RETURN_ERROR (PcdStatus);
|
|
|
|
}
|
|
|
|
|
2009-05-27 23:10:18 +02:00
|
|
|
/**
|
|
|
|
Perform Platform PEI initialization.
|
|
|
|
|
|
|
|
@param FileHandle Handle of the file being invoked.
|
|
|
|
@param PeiServices Describes the list of possible PEI Services.
|
|
|
|
|
|
|
|
@return EFI_SUCCESS The PEIM initialized successfully.
|
|
|
|
|
|
|
|
**/
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
InitializePlatform (
|
|
|
|
IN EFI_PEI_FILE_HANDLE FileHandle,
|
|
|
|
IN CONST EFI_PEI_SERVICES **PeiServices
|
|
|
|
)
|
|
|
|
{
|
2021-12-05 23:54:09 +01:00
|
|
|
EFI_STATUS Status;
|
2016-04-07 12:19:23 +02:00
|
|
|
|
2017-09-04 20:31:21 +02:00
|
|
|
DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n"));
|
2009-05-27 23:10:18 +02:00
|
|
|
|
2022-03-06 14:31:41 +01:00
|
|
|
mPlatformInfoHob.SmmSmramRequire = FeaturePcdGet (PcdSmmSmramRequire);
|
|
|
|
mPlatformInfoHob.SevEsIsEnabled = MemEncryptSevEsIsEnabled ();
|
|
|
|
mPlatformInfoHob.PcdPciMmio64Size = PcdGet64 (PcdPciMmio64Size);
|
|
|
|
mPlatformInfoHob.DefaultMaxCpuNumber = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
|
2022-03-06 03:20:36 +01:00
|
|
|
|
2022-02-12 07:06:46 +01:00
|
|
|
PlatformDebugDumpCmos ();
|
2011-01-21 17:50:31 +01:00
|
|
|
|
2014-03-04 09:01:58 +01:00
|
|
|
if (QemuFwCfgS3Enabled ()) {
|
2020-04-29 23:53:27 +02:00
|
|
|
DEBUG ((DEBUG_INFO, "S3 support was detected on QEMU\n"));
|
2022-03-06 03:20:36 +01:00
|
|
|
mPlatformInfoHob.S3Supported = TRUE;
|
|
|
|
Status = PcdSetBoolS (PcdAcpiS3Enable, TRUE);
|
2016-04-07 12:19:23 +02:00
|
|
|
ASSERT_EFI_ERROR (Status);
|
2014-03-04 09:01:58 +01:00
|
|
|
}
|
|
|
|
|
2015-12-01 00:36:31 +01:00
|
|
|
S3Verification ();
|
2022-03-06 03:20:36 +01:00
|
|
|
BootModeInitialization (&mPlatformInfoHob);
|
|
|
|
AddressWidthInitialization (&mPlatformInfoHob);
|
2014-01-29 22:44:16 +01:00
|
|
|
|
2017-07-04 14:50:43 +02:00
|
|
|
//
|
|
|
|
// Query Host Bridge DID
|
|
|
|
//
|
2022-03-06 03:20:36 +01:00
|
|
|
mPlatformInfoHob.HostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);
|
2017-07-04 14:50:43 +02:00
|
|
|
|
2022-03-06 03:20:36 +01:00
|
|
|
MaxCpuCountInitialization (&mPlatformInfoHob);
|
OvmfPkg/PlatformPei: rewrite MaxCpuCountInitialization() for CPU hotplug
MaxCpuCountInitialization() currently handles the following options:
(1) QEMU does not report the boot CPU count (FW_CFG_NB_CPUS is 0)
In this case, PlatformPei makes MpInitLib enumerate APs up to the
default PcdCpuMaxLogicalProcessorNumber value (64) minus 1, or until
the default PcdCpuApInitTimeOutInMicroSeconds (50,000) elapses.
(Whichever is reached first.)
Time-limited AP enumeration had never been reliable on QEMU/KVM, which
is why commit 45a70db3c3a5 strated handling case (2) below, in OVMF.
(2) QEMU reports the boot CPU count (FW_CFG_NB_CPUS is nonzero)
In this case, PlatformPei sets
- PcdCpuMaxLogicalProcessorNumber to the reported boot CPU count
(FW_CFG_NB_CPUS, which exports "PCMachineState.boot_cpus"),
- and PcdCpuApInitTimeOutInMicroSeconds to practically "infinity"
(MAX_UINT32, ~71 minutes).
That causes MpInitLib to enumerate exactly the present (boot) APs.
With CPU hotplug in mind, this method is not good enough. Because,
using QEMU terminology, UefiCpuPkg expects
PcdCpuMaxLogicalProcessorNumber to provide the "possible CPUs" count
("MachineState.smp.max_cpus"), which includes present and not present
CPUs both (with not present CPUs being subject for hot-plugging).
FW_CFG_NB_CPUS does not include not present CPUs.
Rewrite MaxCpuCountInitialization() for handling the following cases:
(1) The behavior of case (1) does not change. (No UefiCpuPkg PCDs are set
to values different from the defaults.)
(2) QEMU reports the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), but not the possible CPUs count
("MachineState.smp.max_cpus").
In this case, the behavior remains unchanged.
The way MpInitLib is instructed to do the same differs however: we now
set the new PcdCpuBootLogicalProcessorNumber to the boot CPU count
(while continuing to set PcdCpuMaxLogicalProcessorNumber identically).
PcdCpuApInitTimeOutInMicroSeconds becomes irrelevant.
(3) QEMU reports both the boot CPU count ("PCMachineState.boot_cpus", via
FW_CFG_NB_CPUS), and the possible CPUs count
("MachineState.smp.max_cpus").
We tell UefiCpuPkg about the possible CPUs count through
PcdCpuMaxLogicalProcessorNumber. We also tell MpInitLib the boot CPU
count for precise and quick AP enumeration, via
PcdCpuBootLogicalProcessorNumber. PcdCpuApInitTimeOutInMicroSeconds is
irrelevant again.
This patch is a pre-requisite for enabling CPU hotplug with SMM_REQUIRE.
As a side effect, the patch also enables S3 to work with CPU hotplug at
once, *without* SMM_REQUIRE.
(Without the patch, S3 resume fails, if a CPU is hot-plugged at OS
runtime, prior to suspend: the FW_CFG_NB_CPUS increase seen during resume
causes PcdCpuMaxLogicalProcessorNumber to increase as well, which is not
permitted.
With the patch, PcdCpuMaxLogicalProcessorNumber stays the same, namely
"MachineState.smp.max_cpus". Therefore, the CPU structures allocated
during normal boot can accommodate the CPUs at S3 resume that have been
hotplugged prior to S3 suspend.)
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien.grall@arm.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20191022221554.14963-4-lersek@redhat.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-10-08 09:15:38 +02:00
|
|
|
|
2022-03-06 03:20:36 +01:00
|
|
|
if (mPlatformInfoHob.SmmSmramRequire) {
|
2019-09-20 13:36:56 +02:00
|
|
|
Q35BoardVerification ();
|
2017-07-04 12:44:05 +02:00
|
|
|
Q35TsegMbytesInitialization ();
|
2019-09-20 14:02:14 +02:00
|
|
|
Q35SmramAtDefaultSmbaseInitialization ();
|
2017-07-04 12:44:05 +02:00
|
|
|
}
|
|
|
|
|
2014-01-29 22:44:09 +01:00
|
|
|
PublishPeiMemory ();
|
|
|
|
|
2022-03-06 14:45:58 +01:00
|
|
|
PlatformQemuUc32BaseInitialization (&mPlatformInfoHob);
|
OvmfPkg/PlatformPei: set 32-bit UC area at PciBase / PciExBarBase (pc/q35)
(This is a replacement for commit 39b9a5ffe661 ("OvmfPkg/PlatformPei: fix
MTRR for low-RAM sizes that have many bits clear", 2019-05-16).)
Reintroduce the same logic as seen in commit 39b9a5ffe661 for the pc
(i440fx) board type.
For q35, the same approach doesn't work any longer, given that (a) we'd
like to keep the PCIEXBAR in the platform DSC a fixed-at-build PCD, and
(b) QEMU expects the PCIEXBAR to reside at a lower address than the 32-bit
PCI MMIO aperture.
Therefore, introduce a helper function for determining the 32-bit
"uncacheable" (MMIO) area base address:
- On q35, this function behaves statically. Furthermore, the MTRR setup
exploits that the range [0xB000_0000, 0xFFFF_FFFF] can be marked UC with
just two variable MTRRs (one at 0xB000_0000 (size 256MB), another at
0xC000_0000 (size 1GB)).
- On pc (i440fx), the function behaves dynamically, implementing the same
logic as commit 39b9a5ffe661 did. The PciBase value is adjusted to the
value calculated, similarly to commit 39b9a5ffe661. A further
simplification is that we show that the UC32 area size truncation to a
whole power of two automatically guarantees a >=2GB base address.
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1859
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2019-05-29 14:49:55 +02:00
|
|
|
|
2022-03-06 03:20:36 +01:00
|
|
|
InitializeRamRegions (&mPlatformInfoHob);
|
2009-05-27 23:10:18 +02:00
|
|
|
|
2022-03-06 03:20:36 +01:00
|
|
|
if (mPlatformInfoHob.BootMode != BOOT_ON_S3_RESUME) {
|
|
|
|
if (!mPlatformInfoHob.SmmSmramRequire) {
|
2017-03-12 22:01:40 +01:00
|
|
|
ReserveEmuVariableNvStore ();
|
|
|
|
}
|
2021-12-05 23:54:09 +01:00
|
|
|
|
2014-03-04 09:02:30 +01:00
|
|
|
PeiFvInitialization ();
|
OvmfPkg: improve SMM comms security with adaptive MemoryTypeInformation
* In the Intel whitepaper:
--v--
A Tour Beyond BIOS -- Secure SMM Communication
https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-Security-White-Papers
https://github.com/tianocore-docs/Docs/raw/master/White_Papers/A_Tour_Beyond_BIOS_Secure_SMM_Communication.pdf
--^--
bullet#3 in section "Assumption and Recommendation", and bullet#4 in "Call
for action", recommend enabling the (adaptive) Memory Type Information
feature.
* In the Intel whitepaper:
--v--
A Tour Beyond BIOS -- Memory Map and Practices in UEFI BIOS
https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-white-papers
https://github.com/tianocore-docs/Docs/raw/master/White_Papers/A_Tour_Beyond_BIOS_Memory_Map_And_Practices_in_UEFI_BIOS_V2.pdf
--^--
figure#6 describes the Memory Type Information feature in detail; namely
as a feedback loop between the Platform PEIM, the DXE IPL PEIM, the DXE
Core, and BDS.
Implement the missing PlatformPei functionality in OvmfPkg, for fulfilling
the Secure SMM Communication recommendation.
In the longer term, OVMF should install the WSMT ACPI table, and this
patch contributes to that.
Notes:
- the step in figure#6 where the UEFI variable is copied into the HOB is
covered by the DXE IPL PEIM, in the DxeLoadCore() function,
- "PcdResetOnMemoryTypeInformationChange" must be reverted to the DEC
default TRUE value, because both whitepapers indicate that BDS needs to
reset the system if the Memory Type Information changes.
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=386
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20200310222739.26717-6-lersek@redhat.com>
Acked-by: Leif Lindholm <leif@nuviainc.com>
2020-03-10 23:27:39 +01:00
|
|
|
MemTypeInfoInitialization ();
|
2022-03-06 03:20:36 +01:00
|
|
|
MemMapInitialization (&mPlatformInfoHob);
|
2015-09-15 10:35:14 +02:00
|
|
|
NoexecDxeInitialization ();
|
2014-03-04 09:02:30 +01:00
|
|
|
}
|
2009-05-27 23:10:18 +02:00
|
|
|
|
2018-10-02 14:17:25 +02:00
|
|
|
InstallClearCacheCallback ();
|
OvmfPkg/PlatformPei: Set memory encryption PCD when SEV is enabled
Secure Encrypted Virtualization (SEV) guest VMs have the concept of
private and shared memory. Private memory is encrypted with the
guest-specific key, while shared memory may be encrypted with hypervisor
key. Certain types of memory (namely instruction pages and guest page
tables) are always treated as private memory by the hardware.
For data memory, SEV guest VMs can choose which pages they would like
to be private. The choice is done using the standard CPU page tables
using the C-bit. When building the initial page table we mark all the
memory as private.
The patch sets the memory encryption PCD. The PCD is consumed by the
following edk2 modules, which manipulate page tables:
- PEI phase modules: CapsulePei, DxeIplPeim, S3Resume2Pei.
CapsulePei is not used by OVMF. DxeIplPeim consumes the PCD at the
end of the PEI phase, when it builds the initial page tables for the
DXE core / DXE phase. S3Resume2Pei does not consume the PCD in its
entry point function, only when DxeIplPeim branches to the S3 resume
path at the end of the PEI phase, and calls S3Resume2Pei's
EFI_PEI_S3_RESUME2_PPI.S3RestoreConfig2() member function.
Therefore it is safe to set the PCD for these modules in PlatformPei.
- DXE phase modules: BootScriptExecutorDxe, CpuDxe, PiSmmCpuDxeSmm.
They are all dispatched after the PEI phase, so setting the PCD for
them in PlatformPei is safe. (BootScriptExecutorDxe is launched "for
real" in the PEI phase during S3 resume, but it caches the PCD into a
static variable when its entry point is originally invoked in DXE.)
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2017-07-06 15:25:48 +02:00
|
|
|
AmdSevInitialize ();
|
2022-03-06 13:04:53 +01:00
|
|
|
if (mPlatformInfoHob.HostBridgeDevId == 0xffff) {
|
|
|
|
MiscInitializationForMicrovm (&mPlatformInfoHob);
|
|
|
|
} else {
|
|
|
|
MiscInitialization (&mPlatformInfoHob);
|
|
|
|
}
|
|
|
|
|
2016-07-07 15:02:11 +02:00
|
|
|
InstallFeatureControlCallback ();
|
2009-05-27 23:10:18 +02:00
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|