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"
|
|
|
|
|
2011-03-22 02:55:08 +01:00
|
|
|
EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = {
|
|
|
|
{
|
|
|
|
EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
|
|
|
|
&gEfiPeiMasterBootModePpiGuid,
|
|
|
|
NULL
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-03-06 15:09:10 +01:00
|
|
|
VOID
|
|
|
|
MemMapInitialization (
|
|
|
|
IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
|
|
|
|
)
|
|
|
|
{
|
|
|
|
RETURN_STATUS PcdStatus;
|
|
|
|
|
|
|
|
PlatformMemMapInitialization (PlatformInfoHob);
|
|
|
|
|
|
|
|
if (PlatformInfoHob->HostBridgeDevId == 0xffff /* microvm */) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PcdStatus = PcdSet64S (PcdPciMmio32Base, PlatformInfoHob->PcdPciMmio32Base);
|
|
|
|
ASSERT_RETURN_ERROR (PcdStatus);
|
|
|
|
PcdStatus = PcdSet64S (PcdPciMmio32Size, PlatformInfoHob->PcdPciMmio32Size);
|
|
|
|
ASSERT_RETURN_ERROR (PcdStatus);
|
|
|
|
|
|
|
|
PcdStatus = PcdSet64S (PcdPciIoBase, PlatformInfoHob->PcdPciIoBase);
|
|
|
|
ASSERT_RETURN_ERROR (PcdStatus);
|
|
|
|
PcdStatus = PcdSet64S (PcdPciIoSize, PlatformInfoHob->PcdPciIoSize);
|
|
|
|
ASSERT_RETURN_ERROR (PcdStatus);
|
|
|
|
}
|
|
|
|
|
2022-12-02 14:10:03 +01:00
|
|
|
STATIC
|
2015-09-15 10:35:14 +02:00
|
|
|
VOID
|
|
|
|
NoexecDxeInitialization (
|
2022-12-02 14:10:03 +01:00
|
|
|
IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
|
2015-09-15 10:35:14 +02:00
|
|
|
)
|
|
|
|
{
|
2022-03-06 15:20:22 +01:00
|
|
|
RETURN_STATUS Status;
|
|
|
|
|
2022-12-02 14:10:03 +01:00
|
|
|
Status = PlatformNoexecDxeInitialization (PlatformInfoHob);
|
2022-03-06 15:20:22 +01:00
|
|
|
if (!RETURN_ERROR (Status)) {
|
2022-12-02 14:10:03 +01:00
|
|
|
Status = PcdSetBoolS (PcdSetNxForStack, PlatformInfoHob->PcdSetNxForStack);
|
2022-03-06 15:20:22 +01:00
|
|
|
ASSERT_RETURN_ERROR (Status);
|
|
|
|
}
|
2015-09-15 10:35:14 +02:00
|
|
|
}
|
2009-05-27 23:10:18 +02:00
|
|
|
|
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)) {
|
2023-04-06 21:49:41 +02:00
|
|
|
DEBUG ((DEBUG_INFO, "%a: no etc/fdt found in fw_cfg, using dummy\n", __func__));
|
2021-12-13 09:16:56 +01:00
|
|
|
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) {
|
2023-04-06 21:49:41 +02:00
|
|
|
DEBUG ((DEBUG_INFO, "%a: AllocatePages failed\n", __func__));
|
2021-12-13 09:16:55 +01:00
|
|
|
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) {
|
2023-04-06 21:49:41 +02:00
|
|
|
DEBUG ((DEBUG_INFO, "%a: BuildGuidHob failed\n", __func__));
|
2021-12-13 09:16:55 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG ((
|
|
|
|
DEBUG_INFO,
|
|
|
|
"%a: fdt at 0x%x (size %d)\n",
|
2023-04-06 21:49:41 +02:00
|
|
|
__func__,
|
2021-12-13 09:16:55 +01:00
|
|
|
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);
|
|
|
|
|
2023-04-06 21:49:41 +02:00
|
|
|
DEBUG ((DEBUG_INFO, "%a: microvm\n", __func__));
|
2022-03-06 13:04:53 +01:00
|
|
|
//
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
2022-03-06 15:35:23 +01:00
|
|
|
VOID
|
|
|
|
MiscInitialization (
|
|
|
|
IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob
|
|
|
|
)
|
|
|
|
{
|
|
|
|
RETURN_STATUS PcdStatus;
|
|
|
|
|
|
|
|
PlatformMiscInitialization (PlatformInfoHob);
|
|
|
|
|
|
|
|
PcdStatus = PcdSet16S (PcdOvmfHostBridgePciDevId, PlatformInfoHob->HostBridgeDevId);
|
|
|
|
ASSERT_RETURN_ERROR (PcdStatus);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
)
|
|
|
|
{
|
2014-03-04 09:01:32 +01:00
|
|
|
EFI_STATUS Status;
|
|
|
|
|
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 (
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_PHYSICAL_ADDRESS VariableStore;
|
2016-10-21 11:59:36 +02:00
|
|
|
RETURN_STATUS PcdStatus;
|
2009-09-07 22:18:17 +02:00
|
|
|
|
2022-06-22 03:08:41 +02:00
|
|
|
VariableStore = (EFI_PHYSICAL_ADDRESS)(UINTN)PlatformReserveEmuVariableNvStore ();
|
|
|
|
PcdStatus = PcdSet64S (PcdEmuVariableNvStoreReserved, VariableStore);
|
|
|
|
|
2023-04-21 08:55:44 +02:00
|
|
|
if (FeaturePcdGet (PcdSecureBootSupported)) {
|
|
|
|
// restore emulated VarStore from pristine ROM copy
|
|
|
|
PlatformInitEmuVariableNvStore ((VOID *)(UINTN)VariableStore);
|
|
|
|
}
|
2022-06-22 03:08:41 +02:00
|
|
|
|
2016-10-21 11:59:36 +02:00
|
|
|
ASSERT_RETURN_ERROR (PcdStatus);
|
2009-09-07 22:18:17 +02:00
|
|
|
}
|
|
|
|
|
2022-12-02 14:10:04 +01:00
|
|
|
STATIC
|
2019-09-20 13:36:56 +02:00
|
|
|
VOID
|
|
|
|
Q35BoardVerification (
|
2022-12-02 14:10:04 +01:00
|
|
|
IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob
|
2019-09-20 13:36:56 +02:00
|
|
|
)
|
|
|
|
{
|
2022-12-02 14:10:04 +01:00
|
|
|
if (PlatformInfoHob->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",
|
2023-04-06 21:49:41 +02:00
|
|
|
__func__,
|
2022-12-02 14:10:04 +01:00
|
|
|
PlatformInfoHob->HostBridgeDevId,
|
2019-09-20 13:36:56 +02:00
|
|
|
INTEL_Q35_MCH_DEVICE_ID
|
|
|
|
));
|
|
|
|
ASSERT (FALSE);
|
|
|
|
CpuDeadLoop ();
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2022-01-20 04:04:17 +01:00
|
|
|
/**
|
|
|
|
* @brief Builds PlatformInfo Hob
|
|
|
|
*/
|
2022-12-02 14:10:05 +01:00
|
|
|
EFI_HOB_PLATFORM_INFO *
|
2022-01-20 04:04:17 +01:00
|
|
|
BuildPlatformInfoHob (
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
2022-12-02 14:10:05 +01:00
|
|
|
EFI_HOB_PLATFORM_INFO PlatformInfoHob;
|
|
|
|
EFI_HOB_GUID_TYPE *GuidHob;
|
|
|
|
|
|
|
|
ZeroMem (&PlatformInfoHob, sizeof PlatformInfoHob);
|
|
|
|
BuildGuidDataHob (&gUefiOvmfPkgPlatformInfoGuid, &PlatformInfoHob, sizeof (EFI_HOB_PLATFORM_INFO));
|
|
|
|
GuidHob = GetFirstGuidHob (&gUefiOvmfPkgPlatformInfoGuid);
|
|
|
|
return (EFI_HOB_PLATFORM_INFO *)GET_GUID_HOB_DATA (GuidHob);
|
2022-01-20 04:04:17 +01:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
)
|
|
|
|
{
|
2022-12-02 14:10:05 +01:00
|
|
|
EFI_HOB_PLATFORM_INFO *PlatformInfoHob;
|
|
|
|
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"));
|
2022-12-02 14:10:05 +01:00
|
|
|
PlatformInfoHob = BuildPlatformInfoHob ();
|
2009-05-27 23:10:18 +02:00
|
|
|
|
2022-12-02 14:10:05 +01:00
|
|
|
PlatformInfoHob->SmmSmramRequire = FeaturePcdGet (PcdSmmSmramRequire);
|
|
|
|
PlatformInfoHob->SevEsIsEnabled = MemEncryptSevEsIsEnabled ();
|
|
|
|
PlatformInfoHob->PcdPciMmio64Size = PcdGet64 (PcdPciMmio64Size);
|
|
|
|
PlatformInfoHob->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-12-02 14:10:05 +01:00
|
|
|
PlatformInfoHob->S3Supported = TRUE;
|
2022-03-06 03:20:36 +01:00
|
|
|
Status = PcdSetBoolS (PcdAcpiS3Enable, TRUE);
|
2016-04-07 12:19:23 +02:00
|
|
|
ASSERT_EFI_ERROR (Status);
|
2014-03-04 09:01:58 +01:00
|
|
|
}
|
|
|
|
|
2022-12-02 14:10:05 +01:00
|
|
|
BootModeInitialization (PlatformInfoHob);
|
2014-01-29 22:44:16 +01:00
|
|
|
|
2017-07-04 14:50:43 +02:00
|
|
|
//
|
|
|
|
// Query Host Bridge DID
|
|
|
|
//
|
2022-12-02 14:10:05 +01:00
|
|
|
PlatformInfoHob->HostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);
|
|
|
|
AddressWidthInitialization (PlatformInfoHob);
|
2017-07-04 14:50:43 +02:00
|
|
|
|
2022-12-02 14:10:05 +01:00
|
|
|
MaxCpuCountInitialization (PlatformInfoHob);
|
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-12-02 14:10:05 +01:00
|
|
|
if (PlatformInfoHob->SmmSmramRequire) {
|
|
|
|
Q35BoardVerification (PlatformInfoHob);
|
|
|
|
Q35TsegMbytesInitialization (PlatformInfoHob);
|
|
|
|
Q35SmramAtDefaultSmbaseInitialization (PlatformInfoHob);
|
2017-07-04 12:44:05 +02:00
|
|
|
}
|
|
|
|
|
2022-12-02 14:10:05 +01:00
|
|
|
PublishPeiMemory (PlatformInfoHob);
|
2014-01-29 22:44:09 +01:00
|
|
|
|
2022-12-02 14:10:05 +01:00
|
|
|
PlatformQemuUc32BaseInitialization (PlatformInfoHob);
|
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-12-02 14:10:05 +01:00
|
|
|
InitializeRamRegions (PlatformInfoHob);
|
2009-05-27 23:10:18 +02:00
|
|
|
|
2022-12-02 14:10:05 +01:00
|
|
|
if (PlatformInfoHob->BootMode != BOOT_ON_S3_RESUME) {
|
|
|
|
if (!PlatformInfoHob->SmmSmramRequire) {
|
2017-03-12 22:01:40 +01:00
|
|
|
ReserveEmuVariableNvStore ();
|
|
|
|
}
|
2021-12-05 23:54:09 +01:00
|
|
|
|
2022-12-02 14:10:05 +01:00
|
|
|
PeiFvInitialization (PlatformInfoHob);
|
|
|
|
MemTypeInfoInitialization (PlatformInfoHob);
|
|
|
|
MemMapInitialization (PlatformInfoHob);
|
|
|
|
NoexecDxeInitialization (PlatformInfoHob);
|
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 ();
|
2022-12-02 14:10:05 +01:00
|
|
|
AmdSevInitialize (PlatformInfoHob);
|
|
|
|
if (PlatformInfoHob->HostBridgeDevId == 0xffff) {
|
|
|
|
MiscInitializationForMicrovm (PlatformInfoHob);
|
2022-03-06 13:04:53 +01:00
|
|
|
} else {
|
2022-12-02 14:10:05 +01:00
|
|
|
MiscInitialization (PlatformInfoHob);
|
2022-03-06 13:04:53 +01:00
|
|
|
}
|
|
|
|
|
2022-01-20 04:04:17 +01:00
|
|
|
IntelTdxInitialize ();
|
2022-12-02 14:10:06 +01:00
|
|
|
InstallFeatureControlCallback (PlatformInfoHob);
|
2009-05-27 23:10:18 +02:00
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|