4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
12 // The package level header files this module uses
17 // The Library classes this module consumes
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/BaseLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/HobLib.h>
23 #include <Library/IoLib.h>
24 #include <Library/MemoryAllocationLib.h>
25 #include <Library/PcdLib.h>
26 #include <Library/PciLib.h>
27 #include <Library/PeimEntryPoint.h>
28 #include <Library/PeiServicesLib.h>
29 #include <Library/QemuFwCfgLib.h>
30 #include <Library/QemuFwCfgS3Lib.h>
31 #include <Library/QemuFwCfgSimpleParserLib.h>
32 #include <Library/ResourcePublicationLib.h>
33 #include <Ppi/MasterBootMode.h>
34 #include <IndustryStandard/I440FxPiix4.h>
35 #include <IndustryStandard/Microvm.h>
36 #include <IndustryStandard/Pci22.h>
37 #include <IndustryStandard/Q35MchIch9.h>
38 #include <IndustryStandard/QemuCpuHotplug.h>
39 #include <OvmfPlatforms.h>
44 EFI_PEI_PPI_DESCRIPTOR mPpiBootMode
[] = {
46 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
47 &gEfiPeiMasterBootModePpiGuid
,
52 UINT16 mHostBridgeDevId
;
54 EFI_BOOT_MODE mBootMode
= BOOT_WITH_FULL_CONFIGURATION
;
56 BOOLEAN mS3Supported
= FALSE
;
61 AddIoMemoryBaseSizeHob (
62 EFI_PHYSICAL_ADDRESS MemoryBase
,
66 BuildResourceDescriptorHob (
67 EFI_RESOURCE_MEMORY_MAPPED_IO
,
68 EFI_RESOURCE_ATTRIBUTE_PRESENT
|
69 EFI_RESOURCE_ATTRIBUTE_INITIALIZED
|
70 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
|
71 EFI_RESOURCE_ATTRIBUTE_TESTED
,
78 AddReservedMemoryBaseSizeHob (
79 EFI_PHYSICAL_ADDRESS MemoryBase
,
84 BuildResourceDescriptorHob (
85 EFI_RESOURCE_MEMORY_RESERVED
,
86 EFI_RESOURCE_ATTRIBUTE_PRESENT
|
87 EFI_RESOURCE_ATTRIBUTE_INITIALIZED
|
88 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
|
90 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
|
91 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
|
92 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
:
95 EFI_RESOURCE_ATTRIBUTE_TESTED
,
102 AddIoMemoryRangeHob (
103 EFI_PHYSICAL_ADDRESS MemoryBase
,
104 EFI_PHYSICAL_ADDRESS MemoryLimit
107 AddIoMemoryBaseSizeHob (MemoryBase
, (UINT64
)(MemoryLimit
- MemoryBase
));
111 AddMemoryBaseSizeHob (
112 EFI_PHYSICAL_ADDRESS MemoryBase
,
116 BuildResourceDescriptorHob (
117 EFI_RESOURCE_SYSTEM_MEMORY
,
118 EFI_RESOURCE_ATTRIBUTE_PRESENT
|
119 EFI_RESOURCE_ATTRIBUTE_INITIALIZED
|
120 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
|
121 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
|
122 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
|
123 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
|
124 EFI_RESOURCE_ATTRIBUTE_TESTED
,
132 EFI_PHYSICAL_ADDRESS MemoryBase
,
133 EFI_PHYSICAL_ADDRESS MemoryLimit
136 AddMemoryBaseSizeHob (MemoryBase
, (UINT64
)(MemoryLimit
- MemoryBase
));
140 MemMapInitialization (
146 RETURN_STATUS PcdStatus
;
156 // Video memory + Legacy BIOS region
158 AddIoMemoryRangeHob (0x0A0000, BASE_1MB
);
160 if (mHostBridgeDevId
== 0xffff /* microvm */) {
161 AddIoMemoryBaseSizeHob (MICROVM_GED_MMIO_BASE
, SIZE_4KB
);
162 AddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB
); /* ioapic #1 */
163 AddIoMemoryBaseSizeHob (0xFEC10000, SIZE_4KB
); /* ioapic #2 */
167 TopOfLowRam
= GetSystemMemorySizeBelow4gb ();
169 if (mHostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
171 // The MMCONFIG area is expected to fall between the top of low RAM and
172 // the base of the 32-bit PCI host aperture.
174 PciExBarBase
= FixedPcdGet64 (PcdPciExpressBaseAddress
);
175 ASSERT (TopOfLowRam
<= PciExBarBase
);
176 ASSERT (PciExBarBase
<= MAX_UINT32
- SIZE_256MB
);
177 PciBase
= (UINT32
)(PciExBarBase
+ SIZE_256MB
);
179 ASSERT (TopOfLowRam
<= mQemuUc32Base
);
180 PciBase
= mQemuUc32Base
;
184 // address purpose size
185 // ------------ -------- -------------------------
186 // max(top, 2g) PCI MMIO 0xFC000000 - max(top, 2g)
187 // 0xFC000000 gap 44 MB
188 // 0xFEC00000 IO-APIC 4 KB
189 // 0xFEC01000 gap 1020 KB
190 // 0xFED00000 HPET 1 KB
191 // 0xFED00400 gap 111 KB
192 // 0xFED1C000 gap (PIIX4) / RCRB (ICH9) 16 KB
193 // 0xFED20000 gap 896 KB
194 // 0xFEE00000 LAPIC 1 MB
196 PciSize
= 0xFC000000 - PciBase
;
197 AddIoMemoryBaseSizeHob (PciBase
, PciSize
);
198 PcdStatus
= PcdSet64S (PcdPciMmio32Base
, PciBase
);
199 ASSERT_RETURN_ERROR (PcdStatus
);
200 PcdStatus
= PcdSet64S (PcdPciMmio32Size
, PciSize
);
201 ASSERT_RETURN_ERROR (PcdStatus
);
203 AddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB
);
204 AddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB
);
205 if (mHostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
206 AddIoMemoryBaseSizeHob (ICH9_ROOT_COMPLEX_BASE
, SIZE_16KB
);
208 // Note: there should be an
210 // AddIoMemoryBaseSizeHob (PciExBarBase, SIZE_256MB);
212 // call below, just like the one above for RCBA. However, Linux insists
213 // that the MMCONFIG area be marked in the E820 or UEFI memory map as
214 // "reserved memory" -- Linux does not content itself with a simple gap
215 // in the memory map wherever the MCFG ACPI table points to.
217 // This appears to be a safety measure. The PCI Firmware Specification
218 // (rev 3.1) says in 4.1.2. "MCFG Table Description": "The resources can
219 // *optionally* be returned in [...] EFIGetMemoryMap as reserved memory
220 // [...]". (Emphasis added here.)
222 // Normally we add memory resource descriptor HOBs in
223 // QemuInitializeRam(), and pre-allocate from those with memory
224 // allocation HOBs in InitializeRamRegions(). However, the MMCONFIG area
225 // is most definitely not RAM; so, as an exception, cover it with
226 // uncacheable reserved memory right here.
228 AddReservedMemoryBaseSizeHob (PciExBarBase
, SIZE_256MB
, FALSE
);
229 BuildMemoryAllocationHob (
232 EfiReservedMemoryType
236 AddIoMemoryBaseSizeHob (PcdGet32 (PcdCpuLocalApicBaseAddress
), SIZE_1MB
);
239 // On Q35, the IO Port space is available for PCI resource allocations from
242 if (mHostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
245 ASSERT ((ICH9_PMBASE_VALUE
& 0xF000) < PciIoBase
);
249 // Add PCI IO Port space available for PCI resource allocations.
251 BuildResourceDescriptorHob (
253 EFI_RESOURCE_ATTRIBUTE_PRESENT
|
254 EFI_RESOURCE_ATTRIBUTE_INITIALIZED
,
258 PcdStatus
= PcdSet64S (PcdPciIoBase
, PciIoBase
);
259 ASSERT_RETURN_ERROR (PcdStatus
);
260 PcdStatus
= PcdSet64S (PcdPciIoSize
, PciIoSize
);
261 ASSERT_RETURN_ERROR (PcdStatus
);
264 #define UPDATE_BOOLEAN_PCD_FROM_FW_CFG(TokenName) \
267 RETURN_STATUS PcdStatus; \
269 if (!RETURN_ERROR (QemuFwCfgParseBool ( \
270 "opt/ovmf/" #TokenName, &Setting))) { \
271 PcdStatus = PcdSetBoolS (TokenName, Setting); \
272 ASSERT_RETURN_ERROR (PcdStatus); \
277 NoexecDxeInitialization (
281 UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdSetNxForStack
);
285 PciExBarInitialization (
295 // We only support the 256MB size for the MMCONFIG area:
296 // 256 buses * 32 devices * 8 functions * 4096 bytes config space.
298 // The masks used below enforce the Q35 requirements that the MMCONFIG area
299 // be (a) correctly aligned -- here at 256 MB --, (b) located under 64 GB.
301 // Note that (b) also ensures that the minimum address width we have
302 // determined in AddressWidthInitialization(), i.e., 36 bits, will suffice
303 // for DXE's page tables to cover the MMCONFIG area.
305 PciExBarBase
.Uint64
= FixedPcdGet64 (PcdPciExpressBaseAddress
);
306 ASSERT ((PciExBarBase
.Uint32
[1] & MCH_PCIEXBAR_HIGHMASK
) == 0);
307 ASSERT ((PciExBarBase
.Uint32
[0] & MCH_PCIEXBAR_LOWMASK
) == 0);
310 // Clear the PCIEXBAREN bit first, before programming the high register.
312 PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW
), 0);
315 // Program the high register. Then program the low register, setting the
316 // MMCONFIG area size and enabling decoding at once.
318 PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_HIGH
), PciExBarBase
.Uint32
[1]);
320 DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW
),
321 PciExBarBase
.Uint32
[0] | MCH_PCIEXBAR_BUS_FF
| MCH_PCIEXBAR_EN
325 static const UINT8 EmptyFdt
[] = {
326 0xd0, 0x0d, 0xfe, 0xed, 0x00, 0x00, 0x00, 0x48,
327 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x48,
328 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x11,
329 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
333 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
334 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09,
338 MicrovmInitialization (
342 FIRMWARE_CONFIG_ITEM FdtItem
;
349 Status
= QemuFwCfgFindFile ("etc/fdt", &FdtItem
, &FdtSize
);
350 if (EFI_ERROR (Status
)) {
351 DEBUG ((DEBUG_INFO
, "%a: no etc/fdt found in fw_cfg, using dummy\n", __FUNCTION__
));
353 FdtSize
= sizeof (EmptyFdt
);
356 FdtPages
= EFI_SIZE_TO_PAGES (FdtSize
);
357 NewBase
= AllocatePages (FdtPages
);
358 if (NewBase
== NULL
) {
359 DEBUG ((DEBUG_INFO
, "%a: AllocatePages failed\n", __FUNCTION__
));
364 QemuFwCfgSelectItem (FdtItem
);
365 QemuFwCfgReadBytes (FdtSize
, NewBase
);
367 CopyMem (NewBase
, EmptyFdt
, FdtSize
);
370 FdtHobData
= BuildGuidHob (&gFdtHobGuid
, sizeof (*FdtHobData
));
371 if (FdtHobData
== NULL
) {
372 DEBUG ((DEBUG_INFO
, "%a: BuildGuidHob failed\n", __FUNCTION__
));
378 "%a: fdt at 0x%x (size %d)\n",
383 *FdtHobData
= (UINTN
)NewBase
;
397 RETURN_STATUS PcdStatus
;
405 // Build the CPU HOB with guest RAM size dependent address width and 16-bits
406 // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
407 // S3 resume as well, so we build it unconditionally.)
409 BuildCpuHob (mPhysMemAddressWidth
, 16);
412 // Determine platform type and save Host Bridge DID to PCD
414 switch (mHostBridgeDevId
) {
415 case INTEL_82441_DEVICE_ID
:
416 PmCmd
= POWER_MGMT_REGISTER_PIIX4 (PCI_COMMAND_OFFSET
);
417 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
418 PmbaAndVal
= ~(UINT32
)PIIX4_PMBA_MASK
;
419 PmbaOrVal
= PIIX4_PMBA_VALUE
;
420 AcpiCtlReg
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMREGMISC
);
421 AcpiEnBit
= PIIX4_PMREGMISC_PMIOSE
;
423 case INTEL_Q35_MCH_DEVICE_ID
:
424 PmCmd
= POWER_MGMT_REGISTER_Q35 (PCI_COMMAND_OFFSET
);
425 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
426 PmbaAndVal
= ~(UINT32
)ICH9_PMBASE_MASK
;
427 PmbaOrVal
= ICH9_PMBASE_VALUE
;
428 AcpiCtlReg
= POWER_MGMT_REGISTER_Q35 (ICH9_ACPI_CNTL
);
429 AcpiEnBit
= ICH9_ACPI_CNTL_ACPI_EN
;
431 case 0xffff: /* microvm */
432 DEBUG ((DEBUG_INFO
, "%a: microvm\n", __FUNCTION__
));
433 MicrovmInitialization ();
434 PcdStatus
= PcdSet16S (
435 PcdOvmfHostBridgePciDevId
,
436 MICROVM_PSEUDO_DEVICE_ID
438 ASSERT_RETURN_ERROR (PcdStatus
);
440 case CLOUDHV_DEVICE_ID
:
441 DEBUG ((DEBUG_INFO
, "%a: Cloud Hypervisor host bridge\n", __FUNCTION__
));
442 PcdStatus
= PcdSet16S (
443 PcdOvmfHostBridgePciDevId
,
446 ASSERT_RETURN_ERROR (PcdStatus
);
451 "%a: Unknown Host Bridge Device ID: 0x%04x\n",
459 PcdStatus
= PcdSet16S (PcdOvmfHostBridgePciDevId
, mHostBridgeDevId
);
460 ASSERT_RETURN_ERROR (PcdStatus
);
463 // If the appropriate IOspace enable bit is set, assume the ACPI PMBA has
464 // been configured and skip the setup here. This matches the logic in
465 // AcpiTimerLibConstructor ().
467 if ((PciRead8 (AcpiCtlReg
) & AcpiEnBit
) == 0) {
469 // The PEI phase should be exited with fully accessibe ACPI PM IO space:
472 PciAndThenOr32 (Pmba
, PmbaAndVal
, PmbaOrVal
);
475 // 2. set PCICMD/IOSE
477 PciOr8 (PmCmd
, EFI_PCI_COMMAND_IO_SPACE
);
480 // 3. set ACPI PM IO enable bit (PMREGMISC:PMIOSE or ACPI_CNTL:ACPI_EN)
482 PciOr8 (AcpiCtlReg
, AcpiEnBit
);
485 if (mHostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
487 // Set Root Complex Register Block BAR
490 POWER_MGMT_REGISTER_Q35 (ICH9_RCBA
),
491 ICH9_ROOT_COMPLEX_BASE
| ICH9_RCBA_EN
495 // Set PCI Express Register Range Base Address
497 PciExBarInitialization ();
502 BootModeInitialization (
508 if (CmosRead8 (0xF) == 0xFE) {
509 mBootMode
= BOOT_ON_S3_RESUME
;
512 CmosWrite8 (0xF, 0x00);
514 Status
= PeiServicesSetBootMode (mBootMode
);
515 ASSERT_EFI_ERROR (Status
);
517 Status
= PeiServicesInstallPpi (mPpiBootMode
);
518 ASSERT_EFI_ERROR (Status
);
522 ReserveEmuVariableNvStore (
525 EFI_PHYSICAL_ADDRESS VariableStore
;
526 RETURN_STATUS PcdStatus
;
529 // Allocate storage for NV variables early on so it will be
530 // at a consistent address. Since VM memory is preserved
531 // across reboots, this allows the NV variable storage to survive
535 (EFI_PHYSICAL_ADDRESS
)(UINTN
)
536 AllocateRuntimePages (
537 EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize
))
541 "Reserved variable store memory: 0x%lX; size: %dkb\n",
543 (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize
)) / 1024
545 PcdStatus
= PcdSet64S (PcdEmuVariableNvStoreReserved
, VariableStore
);
546 ASSERT_RETURN_ERROR (PcdStatus
);
556 DEBUG ((DEBUG_INFO
, "CMOS:\n"));
558 for (Loop
= 0; Loop
< 0x80; Loop
++) {
559 if ((Loop
% 0x10) == 0) {
560 DEBUG ((DEBUG_INFO
, "%02x:", Loop
));
563 DEBUG ((DEBUG_INFO
, " %02x", CmosRead8 (Loop
)));
564 if ((Loop
% 0x10) == 0xf) {
565 DEBUG ((DEBUG_INFO
, "\n"));
575 #if defined (MDE_CPU_X64)
576 if (FeaturePcdGet (PcdSmmSmramRequire
) && mS3Supported
) {
579 "%a: S3Resume2Pei doesn't support X64 PEI + SMM yet.\n",
584 "%a: Please disable S3 on the QEMU command line (see the README),\n",
589 "%a: or build OVMF with \"OvmfPkgIa32X64.dsc\".\n",
600 Q35BoardVerification (
604 if (mHostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
610 "%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "
611 "only DID=0x%04x (Q35) is supported\n",
614 INTEL_Q35_MCH_DEVICE_ID
621 Fetch the boot CPU count and the possible CPU count from QEMU, and expose
622 them to UefiCpuPkg modules. Set the mMaxCpuCount variable.
625 MaxCpuCountInitialization (
630 RETURN_STATUS PcdStatus
;
633 // Try to fetch the boot CPU count.
635 QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount
);
636 BootCpuCount
= QemuFwCfgRead16 ();
637 if (BootCpuCount
== 0) {
639 // QEMU doesn't report the boot CPU count. (BootCpuCount == 0) will let
640 // MpInitLib count APs up to (PcdCpuMaxLogicalProcessorNumber - 1), or
641 // until PcdCpuApInitTimeOutInMicroSeconds elapses (whichever is reached
644 DEBUG ((DEBUG_WARN
, "%a: boot CPU count unavailable\n", __FUNCTION__
));
645 mMaxCpuCount
= PcdGet32 (PcdCpuMaxLogicalProcessorNumber
);
648 // We will expose BootCpuCount to MpInitLib. MpInitLib will count APs up to
649 // (BootCpuCount - 1) precisely, regardless of timeout.
651 // Now try to fetch the possible CPU count.
656 CpuHpBase
= ((mHostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) ?
657 ICH9_CPU_HOTPLUG_BASE
: PIIX4_CPU_HOTPLUG_BASE
);
660 // If only legacy mode is available in the CPU hotplug register block, or
661 // the register block is completely missing, then the writes below are
664 // 1. Switch the hotplug register block to modern mode.
666 IoWrite32 (CpuHpBase
+ QEMU_CPUHP_W_CPU_SEL
, 0);
668 // 2. Select a valid CPU for deterministic reading of
669 // QEMU_CPUHP_R_CMD_DATA2.
671 // CPU#0 is always valid; it is the always present and non-removable
674 IoWrite32 (CpuHpBase
+ QEMU_CPUHP_W_CPU_SEL
, 0);
676 // 3. Send a command after which QEMU_CPUHP_R_CMD_DATA2 is specified to
677 // read as zero, and which does not invalidate the selector. (The
678 // selector may change, but it must not become invalid.)
680 // Send QEMU_CPUHP_CMD_GET_PENDING, as it will prove useful later.
682 IoWrite8 (CpuHpBase
+ QEMU_CPUHP_W_CMD
, QEMU_CPUHP_CMD_GET_PENDING
);
684 // 4. Read QEMU_CPUHP_R_CMD_DATA2.
686 // If the register block is entirely missing, then this is an unassigned
687 // IO read, returning all-bits-one.
689 // If only legacy mode is available, then bit#0 stands for CPU#0 in the
690 // "CPU present bitmap". CPU#0 is always present.
692 // Otherwise, QEMU_CPUHP_R_CMD_DATA2 is either still reserved (returning
693 // all-bits-zero), or it is specified to read as zero after the above
694 // steps. Both cases confirm modern mode.
696 CmdData2
= IoRead32 (CpuHpBase
+ QEMU_CPUHP_R_CMD_DATA2
);
697 DEBUG ((DEBUG_VERBOSE
, "%a: CmdData2=0x%x\n", __FUNCTION__
, CmdData2
));
700 // QEMU doesn't support the modern CPU hotplug interface. Assume that the
701 // possible CPU count equals the boot CPU count (precluding hotplug).
705 "%a: modern CPU hotplug interface unavailable\n",
708 mMaxCpuCount
= BootCpuCount
;
711 // Grab the possible CPU count from the modern CPU hotplug interface.
713 UINT32 Present
, Possible
, Selected
;
719 // We've sent QEMU_CPUHP_CMD_GET_PENDING last; this ensures
720 // QEMU_CPUHP_RW_CMD_DATA can now be read usefully. However,
721 // QEMU_CPUHP_CMD_GET_PENDING may have selected a CPU with actual pending
722 // hotplug events; therefore, select CPU#0 forcibly.
724 IoWrite32 (CpuHpBase
+ QEMU_CPUHP_W_CPU_SEL
, Possible
);
730 // Read the status of the currently selected CPU. This will help with a
731 // sanity check against "BootCpuCount".
733 CpuStatus
= IoRead8 (CpuHpBase
+ QEMU_CPUHP_R_CPU_STAT
);
734 if ((CpuStatus
& QEMU_CPUHP_STAT_ENABLED
) != 0) {
739 // Attempt to select the next CPU.
742 IoWrite32 (CpuHpBase
+ QEMU_CPUHP_W_CPU_SEL
, Possible
);
744 // If the selection is successful, then the following read will return
745 // the selector (which we know is positive at this point). Otherwise,
746 // the read will return 0.
748 Selected
= IoRead32 (CpuHpBase
+ QEMU_CPUHP_RW_CMD_DATA
);
749 ASSERT (Selected
== Possible
|| Selected
== 0);
750 } while (Selected
> 0);
753 // Sanity check: fw_cfg and the modern CPU hotplug interface should
754 // return the same boot CPU count.
756 if (BootCpuCount
!= Present
) {
759 "%a: QEMU v2.7 reset bug: BootCpuCount=%d "
766 // The handling of QemuFwCfgItemSmpCpuCount, across CPU hotplug plus
767 // platform reset (including S3), was corrected in QEMU commit
768 // e3cadac073a9 ("pc: fix FW_CFG_NB_CPUS to account for -device added
769 // CPUs", 2016-11-16), part of release v2.8.0.
771 BootCpuCount
= (UINT16
)Present
;
774 mMaxCpuCount
= Possible
;
780 "%a: BootCpuCount=%d mMaxCpuCount=%u\n",
785 ASSERT (BootCpuCount
<= mMaxCpuCount
);
787 PcdStatus
= PcdSet32S (PcdCpuBootLogicalProcessorNumber
, BootCpuCount
);
788 ASSERT_RETURN_ERROR (PcdStatus
);
789 PcdStatus
= PcdSet32S (PcdCpuMaxLogicalProcessorNumber
, mMaxCpuCount
);
790 ASSERT_RETURN_ERROR (PcdStatus
);
794 Perform Platform PEI initialization.
796 @param FileHandle Handle of the file being invoked.
797 @param PeiServices Describes the list of possible PEI Services.
799 @return EFI_SUCCESS The PEIM initialized successfully.
805 IN EFI_PEI_FILE_HANDLE FileHandle
,
806 IN CONST EFI_PEI_SERVICES
**PeiServices
811 DEBUG ((DEBUG_INFO
, "Platform PEIM Loaded\n"));
815 if (QemuFwCfgS3Enabled ()) {
816 DEBUG ((DEBUG_INFO
, "S3 support was detected on QEMU\n"));
818 Status
= PcdSetBoolS (PcdAcpiS3Enable
, TRUE
);
819 ASSERT_EFI_ERROR (Status
);
823 BootModeInitialization ();
824 AddressWidthInitialization ();
827 // Query Host Bridge DID
829 mHostBridgeDevId
= PciRead16 (OVMF_HOSTBRIDGE_DID
);
831 MaxCpuCountInitialization ();
833 if (FeaturePcdGet (PcdSmmSmramRequire
)) {
834 Q35BoardVerification ();
835 Q35TsegMbytesInitialization ();
836 Q35SmramAtDefaultSmbaseInitialization ();
841 QemuUc32BaseInitialization ();
843 InitializeRamRegions ();
845 if (mBootMode
!= BOOT_ON_S3_RESUME
) {
846 if (!FeaturePcdGet (PcdSmmSmramRequire
)) {
847 ReserveEmuVariableNvStore ();
850 PeiFvInitialization ();
851 MemTypeInfoInitialization ();
852 MemMapInitialization ();
853 NoexecDxeInitialization ();
856 InstallClearCacheCallback ();
858 MiscInitialization ();
859 InstallFeatureControlCallback ();