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