]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/PlatformPei/Platform.c
3b850c2c2626f7fd438914b6084556770509ded4
[mirror_edk2.git] / OvmfPkg / PlatformPei / Platform.c
1 /**@file
2 Platform PEI driver
3
4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 //
12 // The package level header files this module uses
13 //
14 #include <PiPei.h>
15
16 //
17 // The Library classes this module consumes
18 //
19 #include <Library/BaseLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/HobLib.h>
22 #include <Library/IoLib.h>
23 #include <Library/MemoryAllocationLib.h>
24 #include <Library/PcdLib.h>
25 #include <Library/PciLib.h>
26 #include <Library/PeimEntryPoint.h>
27 #include <Library/PeiServicesLib.h>
28 #include <Library/QemuFwCfgLib.h>
29 #include <Library/QemuFwCfgS3Lib.h>
30 #include <Library/QemuFwCfgSimpleParserLib.h>
31 #include <Library/ResourcePublicationLib.h>
32 #include <Ppi/MasterBootMode.h>
33 #include <IndustryStandard/I440FxPiix4.h>
34 #include <IndustryStandard/Pci22.h>
35 #include <IndustryStandard/Q35MchIch9.h>
36 #include <IndustryStandard/QemuCpuHotplug.h>
37 #include <OvmfPlatforms.h>
38
39 #include "Platform.h"
40 #include "Cmos.h"
41
42 EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = {
43 {
44 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
45 &gEfiPeiMasterBootModePpiGuid,
46 NULL
47 }
48 };
49
50
51 UINT16 mHostBridgeDevId;
52
53 EFI_BOOT_MODE mBootMode = BOOT_WITH_FULL_CONFIGURATION;
54
55 BOOLEAN mS3Supported = FALSE;
56
57 UINT32 mMaxCpuCount;
58
59 VOID
60 AddIoMemoryBaseSizeHob (
61 EFI_PHYSICAL_ADDRESS MemoryBase,
62 UINT64 MemorySize
63 )
64 {
65 BuildResourceDescriptorHob (
66 EFI_RESOURCE_MEMORY_MAPPED_IO,
67 EFI_RESOURCE_ATTRIBUTE_PRESENT |
68 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
69 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
70 EFI_RESOURCE_ATTRIBUTE_TESTED,
71 MemoryBase,
72 MemorySize
73 );
74 }
75
76 VOID
77 AddReservedMemoryBaseSizeHob (
78 EFI_PHYSICAL_ADDRESS MemoryBase,
79 UINT64 MemorySize,
80 BOOLEAN Cacheable
81 )
82 {
83 BuildResourceDescriptorHob (
84 EFI_RESOURCE_MEMORY_RESERVED,
85 EFI_RESOURCE_ATTRIBUTE_PRESENT |
86 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
87 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
88 (Cacheable ?
89 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
90 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
91 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE :
92 0
93 ) |
94 EFI_RESOURCE_ATTRIBUTE_TESTED,
95 MemoryBase,
96 MemorySize
97 );
98 }
99
100 VOID
101 AddIoMemoryRangeHob (
102 EFI_PHYSICAL_ADDRESS MemoryBase,
103 EFI_PHYSICAL_ADDRESS MemoryLimit
104 )
105 {
106 AddIoMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
107 }
108
109
110 VOID
111 AddMemoryBaseSizeHob (
112 EFI_PHYSICAL_ADDRESS MemoryBase,
113 UINT64 MemorySize
114 )
115 {
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,
125 MemoryBase,
126 MemorySize
127 );
128 }
129
130
131 VOID
132 AddMemoryRangeHob (
133 EFI_PHYSICAL_ADDRESS MemoryBase,
134 EFI_PHYSICAL_ADDRESS MemoryLimit
135 )
136 {
137 AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
138 }
139
140
141 VOID
142 MemMapInitialization (
143 VOID
144 )
145 {
146 UINT64 PciIoBase;
147 UINT64 PciIoSize;
148 RETURN_STATUS PcdStatus;
149
150 PciIoBase = 0xC000;
151 PciIoSize = 0x4000;
152
153 //
154 // Video memory + Legacy BIOS region
155 //
156 AddIoMemoryRangeHob (0x0A0000, BASE_1MB);
157
158 if (!mXen) {
159 UINT32 TopOfLowRam;
160 UINT64 PciExBarBase;
161 UINT32 PciBase;
162 UINT32 PciSize;
163
164 TopOfLowRam = GetSystemMemorySizeBelow4gb ();
165 PciExBarBase = 0;
166 if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
167 //
168 // The MMCONFIG area is expected to fall between the top of low RAM and
169 // the base of the 32-bit PCI host aperture.
170 //
171 PciExBarBase = FixedPcdGet64 (PcdPciExpressBaseAddress);
172 ASSERT (TopOfLowRam <= PciExBarBase);
173 ASSERT (PciExBarBase <= MAX_UINT32 - SIZE_256MB);
174 PciBase = (UINT32)(PciExBarBase + SIZE_256MB);
175 } else {
176 ASSERT (TopOfLowRam <= mQemuUc32Base);
177 PciBase = mQemuUc32Base;
178 }
179
180 //
181 // address purpose size
182 // ------------ -------- -------------------------
183 // max(top, 2g) PCI MMIO 0xFC000000 - max(top, 2g)
184 // 0xFC000000 gap 44 MB
185 // 0xFEC00000 IO-APIC 4 KB
186 // 0xFEC01000 gap 1020 KB
187 // 0xFED00000 HPET 1 KB
188 // 0xFED00400 gap 111 KB
189 // 0xFED1C000 gap (PIIX4) / RCRB (ICH9) 16 KB
190 // 0xFED20000 gap 896 KB
191 // 0xFEE00000 LAPIC 1 MB
192 //
193 PciSize = 0xFC000000 - PciBase;
194 AddIoMemoryBaseSizeHob (PciBase, PciSize);
195 PcdStatus = PcdSet64S (PcdPciMmio32Base, PciBase);
196 ASSERT_RETURN_ERROR (PcdStatus);
197 PcdStatus = PcdSet64S (PcdPciMmio32Size, PciSize);
198 ASSERT_RETURN_ERROR (PcdStatus);
199
200 AddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB);
201 AddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB);
202 if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
203 AddIoMemoryBaseSizeHob (ICH9_ROOT_COMPLEX_BASE, SIZE_16KB);
204 //
205 // Note: there should be an
206 //
207 // AddIoMemoryBaseSizeHob (PciExBarBase, SIZE_256MB);
208 //
209 // call below, just like the one above for RCBA. However, Linux insists
210 // that the MMCONFIG area be marked in the E820 or UEFI memory map as
211 // "reserved memory" -- Linux does not content itself with a simple gap
212 // in the memory map wherever the MCFG ACPI table points to.
213 //
214 // This appears to be a safety measure. The PCI Firmware Specification
215 // (rev 3.1) says in 4.1.2. "MCFG Table Description": "The resources can
216 // *optionally* be returned in [...] EFIGetMemoryMap as reserved memory
217 // [...]". (Emphasis added here.)
218 //
219 // Normally we add memory resource descriptor HOBs in
220 // QemuInitializeRam(), and pre-allocate from those with memory
221 // allocation HOBs in InitializeRamRegions(). However, the MMCONFIG area
222 // is most definitely not RAM; so, as an exception, cover it with
223 // uncacheable reserved memory right here.
224 //
225 AddReservedMemoryBaseSizeHob (PciExBarBase, SIZE_256MB, FALSE);
226 BuildMemoryAllocationHob (PciExBarBase, SIZE_256MB,
227 EfiReservedMemoryType);
228 }
229 AddIoMemoryBaseSizeHob (PcdGet32(PcdCpuLocalApicBaseAddress), SIZE_1MB);
230
231 //
232 // On Q35, the IO Port space is available for PCI resource allocations from
233 // 0x6000 up.
234 //
235 if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
236 PciIoBase = 0x6000;
237 PciIoSize = 0xA000;
238 ASSERT ((ICH9_PMBASE_VALUE & 0xF000) < PciIoBase);
239 }
240 }
241
242 //
243 // Add PCI IO Port space available for PCI resource allocations.
244 //
245 BuildResourceDescriptorHob (
246 EFI_RESOURCE_IO,
247 EFI_RESOURCE_ATTRIBUTE_PRESENT |
248 EFI_RESOURCE_ATTRIBUTE_INITIALIZED,
249 PciIoBase,
250 PciIoSize
251 );
252 PcdStatus = PcdSet64S (PcdPciIoBase, PciIoBase);
253 ASSERT_RETURN_ERROR (PcdStatus);
254 PcdStatus = PcdSet64S (PcdPciIoSize, PciIoSize);
255 ASSERT_RETURN_ERROR (PcdStatus);
256 }
257
258 #define UPDATE_BOOLEAN_PCD_FROM_FW_CFG(TokenName) \
259 do { \
260 BOOLEAN Setting; \
261 RETURN_STATUS PcdStatus; \
262 \
263 if (!RETURN_ERROR (QemuFwCfgParseBool ( \
264 "opt/ovmf/" #TokenName, &Setting))) { \
265 PcdStatus = PcdSetBoolS (TokenName, Setting); \
266 ASSERT_RETURN_ERROR (PcdStatus); \
267 } \
268 } while (0)
269
270 VOID
271 NoexecDxeInitialization (
272 VOID
273 )
274 {
275 UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdSetNxForStack);
276 }
277
278 VOID
279 PciExBarInitialization (
280 VOID
281 )
282 {
283 union {
284 UINT64 Uint64;
285 UINT32 Uint32[2];
286 } PciExBarBase;
287
288 //
289 // We only support the 256MB size for the MMCONFIG area:
290 // 256 buses * 32 devices * 8 functions * 4096 bytes config space.
291 //
292 // The masks used below enforce the Q35 requirements that the MMCONFIG area
293 // be (a) correctly aligned -- here at 256 MB --, (b) located under 64 GB.
294 //
295 // Note that (b) also ensures that the minimum address width we have
296 // determined in AddressWidthInitialization(), i.e., 36 bits, will suffice
297 // for DXE's page tables to cover the MMCONFIG area.
298 //
299 PciExBarBase.Uint64 = FixedPcdGet64 (PcdPciExpressBaseAddress);
300 ASSERT ((PciExBarBase.Uint32[1] & MCH_PCIEXBAR_HIGHMASK) == 0);
301 ASSERT ((PciExBarBase.Uint32[0] & MCH_PCIEXBAR_LOWMASK) == 0);
302
303 //
304 // Clear the PCIEXBAREN bit first, before programming the high register.
305 //
306 PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW), 0);
307
308 //
309 // Program the high register. Then program the low register, setting the
310 // MMCONFIG area size and enabling decoding at once.
311 //
312 PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_HIGH), PciExBarBase.Uint32[1]);
313 PciWrite32 (
314 DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW),
315 PciExBarBase.Uint32[0] | MCH_PCIEXBAR_BUS_FF | MCH_PCIEXBAR_EN
316 );
317 }
318
319 VOID
320 MiscInitialization (
321 VOID
322 )
323 {
324 UINTN PmCmd;
325 UINTN Pmba;
326 UINT32 PmbaAndVal;
327 UINT32 PmbaOrVal;
328 UINTN AcpiCtlReg;
329 UINT8 AcpiEnBit;
330 RETURN_STATUS PcdStatus;
331
332 //
333 // Disable A20 Mask
334 //
335 IoOr8 (0x92, BIT1);
336
337 //
338 // Build the CPU HOB with guest RAM size dependent address width and 16-bits
339 // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
340 // S3 resume as well, so we build it unconditionally.)
341 //
342 BuildCpuHob (mPhysMemAddressWidth, 16);
343
344 //
345 // Determine platform type and save Host Bridge DID to PCD
346 //
347 switch (mHostBridgeDevId) {
348 case INTEL_82441_DEVICE_ID:
349 PmCmd = POWER_MGMT_REGISTER_PIIX4 (PCI_COMMAND_OFFSET);
350 Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
351 PmbaAndVal = ~(UINT32)PIIX4_PMBA_MASK;
352 PmbaOrVal = PIIX4_PMBA_VALUE;
353 AcpiCtlReg = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMREGMISC);
354 AcpiEnBit = PIIX4_PMREGMISC_PMIOSE;
355 break;
356 case INTEL_Q35_MCH_DEVICE_ID:
357 PmCmd = POWER_MGMT_REGISTER_Q35 (PCI_COMMAND_OFFSET);
358 Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
359 PmbaAndVal = ~(UINT32)ICH9_PMBASE_MASK;
360 PmbaOrVal = ICH9_PMBASE_VALUE;
361 AcpiCtlReg = POWER_MGMT_REGISTER_Q35 (ICH9_ACPI_CNTL);
362 AcpiEnBit = ICH9_ACPI_CNTL_ACPI_EN;
363 break;
364 default:
365 DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
366 __FUNCTION__, mHostBridgeDevId));
367 ASSERT (FALSE);
368 return;
369 }
370 PcdStatus = PcdSet16S (PcdOvmfHostBridgePciDevId, mHostBridgeDevId);
371 ASSERT_RETURN_ERROR (PcdStatus);
372
373 //
374 // If the appropriate IOspace enable bit is set, assume the ACPI PMBA
375 // has been configured (e.g., by Xen) and skip the setup here.
376 // This matches the logic in AcpiTimerLibConstructor ().
377 //
378 if ((PciRead8 (AcpiCtlReg) & AcpiEnBit) == 0) {
379 //
380 // The PEI phase should be exited with fully accessibe ACPI PM IO space:
381 // 1. set PMBA
382 //
383 PciAndThenOr32 (Pmba, PmbaAndVal, PmbaOrVal);
384
385 //
386 // 2. set PCICMD/IOSE
387 //
388 PciOr8 (PmCmd, EFI_PCI_COMMAND_IO_SPACE);
389
390 //
391 // 3. set ACPI PM IO enable bit (PMREGMISC:PMIOSE or ACPI_CNTL:ACPI_EN)
392 //
393 PciOr8 (AcpiCtlReg, AcpiEnBit);
394 }
395
396 if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
397 //
398 // Set Root Complex Register Block BAR
399 //
400 PciWrite32 (
401 POWER_MGMT_REGISTER_Q35 (ICH9_RCBA),
402 ICH9_ROOT_COMPLEX_BASE | ICH9_RCBA_EN
403 );
404
405 //
406 // Set PCI Express Register Range Base Address
407 //
408 PciExBarInitialization ();
409 }
410 }
411
412
413 VOID
414 BootModeInitialization (
415 VOID
416 )
417 {
418 EFI_STATUS Status;
419
420 if (CmosRead8 (0xF) == 0xFE) {
421 mBootMode = BOOT_ON_S3_RESUME;
422 }
423 CmosWrite8 (0xF, 0x00);
424
425 Status = PeiServicesSetBootMode (mBootMode);
426 ASSERT_EFI_ERROR (Status);
427
428 Status = PeiServicesInstallPpi (mPpiBootMode);
429 ASSERT_EFI_ERROR (Status);
430 }
431
432
433 VOID
434 ReserveEmuVariableNvStore (
435 )
436 {
437 EFI_PHYSICAL_ADDRESS VariableStore;
438 RETURN_STATUS PcdStatus;
439
440 //
441 // Allocate storage for NV variables early on so it will be
442 // at a consistent address. Since VM memory is preserved
443 // across reboots, this allows the NV variable storage to survive
444 // a VM reboot.
445 //
446 VariableStore =
447 (EFI_PHYSICAL_ADDRESS)(UINTN)
448 AllocateRuntimePages (
449 EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize))
450 );
451 DEBUG ((EFI_D_INFO,
452 "Reserved variable store memory: 0x%lX; size: %dkb\n",
453 VariableStore,
454 (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / 1024
455 ));
456 PcdStatus = PcdSet64S (PcdEmuVariableNvStoreReserved, VariableStore);
457 ASSERT_RETURN_ERROR (PcdStatus);
458 }
459
460
461 VOID
462 DebugDumpCmos (
463 VOID
464 )
465 {
466 UINT32 Loop;
467
468 DEBUG ((EFI_D_INFO, "CMOS:\n"));
469
470 for (Loop = 0; Loop < 0x80; Loop++) {
471 if ((Loop % 0x10) == 0) {
472 DEBUG ((EFI_D_INFO, "%02x:", Loop));
473 }
474 DEBUG ((EFI_D_INFO, " %02x", CmosRead8 (Loop)));
475 if ((Loop % 0x10) == 0xf) {
476 DEBUG ((EFI_D_INFO, "\n"));
477 }
478 }
479 }
480
481
482 VOID
483 S3Verification (
484 VOID
485 )
486 {
487 #if defined (MDE_CPU_X64)
488 if (FeaturePcdGet (PcdSmmSmramRequire) && mS3Supported) {
489 DEBUG ((EFI_D_ERROR,
490 "%a: S3Resume2Pei doesn't support X64 PEI + SMM yet.\n", __FUNCTION__));
491 DEBUG ((EFI_D_ERROR,
492 "%a: Please disable S3 on the QEMU command line (see the README),\n",
493 __FUNCTION__));
494 DEBUG ((EFI_D_ERROR,
495 "%a: or build OVMF with \"OvmfPkgIa32X64.dsc\".\n", __FUNCTION__));
496 ASSERT (FALSE);
497 CpuDeadLoop ();
498 }
499 #endif
500 }
501
502
503 VOID
504 Q35BoardVerification (
505 VOID
506 )
507 {
508 if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
509 return;
510 }
511
512 DEBUG ((
513 DEBUG_ERROR,
514 "%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "
515 "only DID=0x%04x (Q35) is supported\n",
516 __FUNCTION__,
517 mHostBridgeDevId,
518 INTEL_Q35_MCH_DEVICE_ID
519 ));
520 ASSERT (FALSE);
521 CpuDeadLoop ();
522 }
523
524
525 /**
526 Fetch the boot CPU count and the possible CPU count from QEMU, and expose
527 them to UefiCpuPkg modules. Set the mMaxCpuCount variable.
528 **/
529 VOID
530 MaxCpuCountInitialization (
531 VOID
532 )
533 {
534 UINT16 BootCpuCount;
535 RETURN_STATUS PcdStatus;
536
537 //
538 // Try to fetch the boot CPU count.
539 //
540 QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount);
541 BootCpuCount = QemuFwCfgRead16 ();
542 if (BootCpuCount == 0) {
543 //
544 // QEMU doesn't report the boot CPU count. (BootCpuCount == 0) will let
545 // MpInitLib count APs up to (PcdCpuMaxLogicalProcessorNumber - 1), or
546 // until PcdCpuApInitTimeOutInMicroSeconds elapses (whichever is reached
547 // first).
548 //
549 DEBUG ((DEBUG_WARN, "%a: boot CPU count unavailable\n", __FUNCTION__));
550 mMaxCpuCount = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
551 } else {
552 //
553 // We will expose BootCpuCount to MpInitLib. MpInitLib will count APs up to
554 // (BootCpuCount - 1) precisely, regardless of timeout.
555 //
556 // Now try to fetch the possible CPU count.
557 //
558 UINTN CpuHpBase;
559 UINT32 CmdData2;
560
561 CpuHpBase = ((mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) ?
562 ICH9_CPU_HOTPLUG_BASE : PIIX4_CPU_HOTPLUG_BASE);
563
564 //
565 // If only legacy mode is available in the CPU hotplug register block, or
566 // the register block is completely missing, then the writes below are
567 // no-ops.
568 //
569 // 1. Switch the hotplug register block to modern mode.
570 //
571 IoWrite32 (CpuHpBase + QEMU_CPUHP_W_CPU_SEL, 0);
572 //
573 // 2. Select a valid CPU for deterministic reading of
574 // QEMU_CPUHP_R_CMD_DATA2.
575 //
576 // CPU#0 is always valid; it is the always present and non-removable
577 // BSP.
578 //
579 IoWrite32 (CpuHpBase + QEMU_CPUHP_W_CPU_SEL, 0);
580 //
581 // 3. Send a command after which QEMU_CPUHP_R_CMD_DATA2 is specified to
582 // read as zero, and which does not invalidate the selector. (The
583 // selector may change, but it must not become invalid.)
584 //
585 // Send QEMU_CPUHP_CMD_GET_PENDING, as it will prove useful later.
586 //
587 IoWrite8 (CpuHpBase + QEMU_CPUHP_W_CMD, QEMU_CPUHP_CMD_GET_PENDING);
588 //
589 // 4. Read QEMU_CPUHP_R_CMD_DATA2.
590 //
591 // If the register block is entirely missing, then this is an unassigned
592 // IO read, returning all-bits-one.
593 //
594 // If only legacy mode is available, then bit#0 stands for CPU#0 in the
595 // "CPU present bitmap". CPU#0 is always present.
596 //
597 // Otherwise, QEMU_CPUHP_R_CMD_DATA2 is either still reserved (returning
598 // all-bits-zero), or it is specified to read as zero after the above
599 // steps. Both cases confirm modern mode.
600 //
601 CmdData2 = IoRead32 (CpuHpBase + QEMU_CPUHP_R_CMD_DATA2);
602 DEBUG ((DEBUG_VERBOSE, "%a: CmdData2=0x%x\n", __FUNCTION__, CmdData2));
603 if (CmdData2 != 0) {
604 //
605 // QEMU doesn't support the modern CPU hotplug interface. Assume that the
606 // possible CPU count equals the boot CPU count (precluding hotplug).
607 //
608 DEBUG ((DEBUG_WARN, "%a: modern CPU hotplug interface unavailable\n",
609 __FUNCTION__));
610 mMaxCpuCount = BootCpuCount;
611 } else {
612 //
613 // Grab the possible CPU count from the modern CPU hotplug interface.
614 //
615 UINT32 Present, Possible, Selected;
616
617 Present = 0;
618 Possible = 0;
619
620 //
621 // We've sent QEMU_CPUHP_CMD_GET_PENDING last; this ensures
622 // QEMU_CPUHP_RW_CMD_DATA can now be read usefully. However,
623 // QEMU_CPUHP_CMD_GET_PENDING may have selected a CPU with actual pending
624 // hotplug events; therefore, select CPU#0 forcibly.
625 //
626 IoWrite32 (CpuHpBase + QEMU_CPUHP_W_CPU_SEL, Possible);
627
628 do {
629 UINT8 CpuStatus;
630
631 //
632 // Read the status of the currently selected CPU. This will help with a
633 // sanity check against "BootCpuCount".
634 //
635 CpuStatus = IoRead8 (CpuHpBase + QEMU_CPUHP_R_CPU_STAT);
636 if ((CpuStatus & QEMU_CPUHP_STAT_ENABLED) != 0) {
637 ++Present;
638 }
639 //
640 // Attempt to select the next CPU.
641 //
642 ++Possible;
643 IoWrite32 (CpuHpBase + QEMU_CPUHP_W_CPU_SEL, Possible);
644 //
645 // If the selection is successful, then the following read will return
646 // the selector (which we know is positive at this point). Otherwise,
647 // the read will return 0.
648 //
649 Selected = IoRead32 (CpuHpBase + QEMU_CPUHP_RW_CMD_DATA);
650 ASSERT (Selected == Possible || Selected == 0);
651 } while (Selected > 0);
652
653 //
654 // Sanity check: fw_cfg and the modern CPU hotplug interface should
655 // return the same boot CPU count.
656 //
657 if (BootCpuCount != Present) {
658 DEBUG ((DEBUG_WARN, "%a: QEMU v2.7 reset bug: BootCpuCount=%d "
659 "Present=%u\n", __FUNCTION__, BootCpuCount, Present));
660 //
661 // The handling of QemuFwCfgItemSmpCpuCount, across CPU hotplug plus
662 // platform reset (including S3), was corrected in QEMU commit
663 // e3cadac073a9 ("pc: fix FW_CFG_NB_CPUS to account for -device added
664 // CPUs", 2016-11-16), part of release v2.8.0.
665 //
666 BootCpuCount = (UINT16)Present;
667 }
668
669 mMaxCpuCount = Possible;
670 }
671 }
672
673 DEBUG ((DEBUG_INFO, "%a: BootCpuCount=%d mMaxCpuCount=%u\n", __FUNCTION__,
674 BootCpuCount, mMaxCpuCount));
675 ASSERT (BootCpuCount <= mMaxCpuCount);
676
677 PcdStatus = PcdSet32S (PcdCpuBootLogicalProcessorNumber, BootCpuCount);
678 ASSERT_RETURN_ERROR (PcdStatus);
679 PcdStatus = PcdSet32S (PcdCpuMaxLogicalProcessorNumber, mMaxCpuCount);
680 ASSERT_RETURN_ERROR (PcdStatus);
681 }
682
683
684 /**
685 Perform Platform PEI initialization.
686
687 @param FileHandle Handle of the file being invoked.
688 @param PeiServices Describes the list of possible PEI Services.
689
690 @return EFI_SUCCESS The PEIM initialized successfully.
691
692 **/
693 EFI_STATUS
694 EFIAPI
695 InitializePlatform (
696 IN EFI_PEI_FILE_HANDLE FileHandle,
697 IN CONST EFI_PEI_SERVICES **PeiServices
698 )
699 {
700 EFI_STATUS Status;
701
702 DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n"));
703
704 DebugDumpCmos ();
705
706 XenDetect ();
707
708 if (QemuFwCfgS3Enabled ()) {
709 DEBUG ((EFI_D_INFO, "S3 support was detected on QEMU\n"));
710 mS3Supported = TRUE;
711 Status = PcdSetBoolS (PcdAcpiS3Enable, TRUE);
712 ASSERT_EFI_ERROR (Status);
713 }
714
715 S3Verification ();
716 BootModeInitialization ();
717 AddressWidthInitialization ();
718
719 //
720 // Query Host Bridge DID
721 //
722 mHostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);
723
724 MaxCpuCountInitialization ();
725
726 if (FeaturePcdGet (PcdSmmSmramRequire)) {
727 Q35BoardVerification ();
728 Q35TsegMbytesInitialization ();
729 Q35SmramAtDefaultSmbaseInitialization ();
730 }
731
732 PublishPeiMemory ();
733
734 QemuUc32BaseInitialization ();
735
736 InitializeRamRegions ();
737
738 if (mXen) {
739 DEBUG ((EFI_D_INFO, "Xen was detected\n"));
740 InitializeXen ();
741 }
742
743 if (mBootMode != BOOT_ON_S3_RESUME) {
744 if (!FeaturePcdGet (PcdSmmSmramRequire)) {
745 ReserveEmuVariableNvStore ();
746 }
747 PeiFvInitialization ();
748 MemTypeInfoInitialization ();
749 MemMapInitialization ();
750 NoexecDxeInitialization ();
751 }
752
753 InstallClearCacheCallback ();
754 AmdSevInitialize ();
755 MiscInitialization ();
756 InstallFeatureControlCallback ();
757
758 return EFI_SUCCESS;
759 }