From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smic.int.bsdio.com (smic.int.bsdio.com [65.103.231.193]) by mx.groups.io with SMTP id smtpd.web10.801.1586992288031394249 for ; Wed, 15 Apr 2020 16:11:28 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=none, err=permanent DNS error (domain: smic.int.bsdio.com, ip: 65.103.231.193, mailfrom: bcran@smic.int.bsdio.com) Received: from smic.int.bsdio.com (localhost [127.0.0.1]) by smic.int.bsdio.com (8.15.2/8.15.2) with ESMTPS id 03FNA9ud068041 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NO); Wed, 15 Apr 2020 17:10:09 -0600 (MDT) (envelope-from bcran@smic.int.bsdio.com) Received: (from bcran@localhost) by smic.int.bsdio.com (8.15.2/8.15.2/Submit) id 03FNA9Kl067516; Wed, 15 Apr 2020 17:10:09 -0600 (MDT) (envelope-from bcran) From: "Rebecca Cran" To: devel@edk2.groups.io Cc: Jordan Justen , Laszlo Ersek , Ard Biesheuvel , Rebecca Cran Subject: [PATCH 09/13] OvmfPkg: Add bhyve support to PlatformPei Date: Wed, 15 Apr 2020 17:09:35 -0600 Message-Id: <15a4708f1a85e227e14bd4259e9ade484458555b.1586991816.git.rebecca@bsdio.com> X-Mailer: git-send-email 2.26.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Signed-off-by: Rebecca Cran --- OvmfPkg/PlatformPei/MemDetectBhyve.c | 631 +++++++++++++++++++++++ OvmfPkg/PlatformPei/PlatformBhyve.c | 612 ++++++++++++++++++++++ OvmfPkg/PlatformPei/PlatformPeiBhyve.inf | 119 +++++ 3 files changed, 1362 insertions(+) create mode 100644 OvmfPkg/PlatformPei/MemDetectBhyve.c create mode 100644 OvmfPkg/PlatformPei/PlatformBhyve.c create mode 100644 OvmfPkg/PlatformPei/PlatformPeiBhyve.inf diff --git a/OvmfPkg/PlatformPei/MemDetectBhyve.c b/OvmfPkg/PlatformPei/Mem= DetectBhyve.c new file mode 100644 index 0000000000..1e18886248 --- /dev/null +++ b/OvmfPkg/PlatformPei/MemDetectBhyve.c @@ -0,0 +1,631 @@ +/**@file=0D + Memory Detection for Virtual Machines.=0D +=0D + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
=0D + This program and the accompanying materials=0D + are licensed and made available under the terms and conditions of the BS= D License=0D + which accompanies this distribution. The full text of the license may b= e found at=0D + http://opensource.org/licenses/bsd-license.php=0D +=0D + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,=0D + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED.=0D +=0D +Module Name:=0D +=0D + MemDetect.c=0D +=0D +**/=0D +=0D +//=0D +// The package level header files this module uses=0D +//=0D +#include =0D +#include =0D +#include =0D +=0D +//=0D +// The Library classes this module consumes=0D +//=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +#include "Platform.h"=0D +#include "Cmos.h"=0D +=0D +UINT8 mPhysMemAddressWidth;=0D +=0D +STATIC UINT32 mS3AcpiReservedMemoryBase;=0D +STATIC UINT32 mS3AcpiReservedMemorySize;=0D +=0D +STATIC UINT16 mQ35TsegMbytes;=0D +=0D +BOOLEAN mQ35SmramAtDefaultSmbase =3D FALSE;=0D +=0D +VOID=0D +Q35TsegMbytesInitialization (=0D + VOID=0D + )=0D +{=0D + UINT16 ExtendedTsegMbytes;=0D + RETURN_STATUS PcdStatus;=0D +=0D + if (mHostBridgeDevId !=3D INTEL_Q35_MCH_DEVICE_ID) {=0D + DEBUG ((=0D + DEBUG_ERROR,=0D + "%a: no TSEG (SMRAM) on host bridge DID=3D0x%04x; "=0D + "only DID=3D0x%04x (Q35) is supported\n",=0D + __FUNCTION__,=0D + mHostBridgeDevId,=0D + INTEL_Q35_MCH_DEVICE_ID=0D + ));=0D + ASSERT (FALSE);=0D + CpuDeadLoop ();=0D + }=0D +=0D + //=0D + // Check if QEMU offers an extended TSEG.=0D + //=0D + // This can be seen from writing MCH_EXT_TSEG_MB_QUERY to the MCH_EXT_TS= EG_MB=0D + // register, and reading back the register.=0D + //=0D + // On a QEMU machine type that does not offer an extended TSEG, the init= ial=0D + // write overwrites whatever value a malicious guest OS may have placed = in=0D + // the (unimplemented) register, before entering S3 or rebooting.=0D + // Subsequently, the read returns MCH_EXT_TSEG_MB_QUERY unchanged.=0D + //=0D + // On a QEMU machine type that offers an extended TSEG, the initial writ= e=0D + // triggers an update to the register. Subsequently, the value read back= =0D + // (which is guaranteed to differ from MCH_EXT_TSEG_MB_QUERY) tells us t= he=0D + // number of megabytes.=0D + //=0D + PciWrite16 (DRAMC_REGISTER_Q35 (MCH_EXT_TSEG_MB), MCH_EXT_TSEG_MB_QUERY)= ;=0D + ExtendedTsegMbytes =3D PciRead16 (DRAMC_REGISTER_Q35 (MCH_EXT_TSEG_MB));= =0D + if (ExtendedTsegMbytes =3D=3D MCH_EXT_TSEG_MB_QUERY) {=0D + mQ35TsegMbytes =3D PcdGet16 (PcdQ35TsegMbytes);=0D + return;=0D + }=0D +=0D + DEBUG ((=0D + DEBUG_INFO,=0D + "%a: QEMU offers an extended TSEG (%d MB)\n",=0D + __FUNCTION__,=0D + ExtendedTsegMbytes=0D + ));=0D + PcdStatus =3D PcdSet16S (PcdQ35TsegMbytes, ExtendedTsegMbytes);=0D + ASSERT_RETURN_ERROR (PcdStatus);=0D + mQ35TsegMbytes =3D ExtendedTsegMbytes;=0D +}=0D +=0D +=0D +UINT32=0D +GetSystemMemorySizeBelow4gb (=0D + VOID=0D + )=0D +{=0D + UINT8 Cmos0x34;=0D + UINT8 Cmos0x35;=0D +=0D + //=0D + // CMOS 0x34/0x35 specifies the system memory above 16 MB.=0D + // * CMOS(0x35) is the high byte=0D + // * CMOS(0x34) is the low byte=0D + // * The size is specified in 64kb chunks=0D + // * Since this is memory above 16MB, the 16MB must be added=0D + // into the calculation to get the total memory size.=0D + //=0D +=0D + Cmos0x34 =3D (UINT8) CmosRead8 (0x34);=0D + Cmos0x35 =3D (UINT8) CmosRead8 (0x35);=0D +=0D + return (UINT32) (((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB= );=0D +}=0D +=0D +=0D +STATIC=0D +UINT64=0D +GetSystemMemorySizeAbove4gb (=0D + )=0D +{=0D + UINT32 Size;=0D + UINTN CmosIndex;=0D +=0D + //=0D + // CMOS 0x5b-0x5d specifies the system memory above 4GB MB.=0D + // * CMOS(0x5d) is the most significant size byte=0D + // * CMOS(0x5c) is the middle size byte=0D + // * CMOS(0x5b) is the least significant size byte=0D + // * The size is specified in 64kb chunks=0D + //=0D +=0D + Size =3D 0;=0D + for (CmosIndex =3D 0x5d; CmosIndex >=3D 0x5b; CmosIndex--) {=0D + Size =3D (UINT32) (Size << 8) + (UINT32) CmosRead8 (CmosIndex);=0D + }=0D +=0D + return LShiftU64 (Size, 16);=0D +}=0D +=0D +=0D +/**=0D + Return the highest address that DXE could possibly use, plus one.=0D +**/=0D +STATIC=0D +UINT64=0D +GetFirstNonAddress (=0D + VOID=0D + )=0D +{=0D + UINT64 FirstNonAddress;=0D + UINT64 Pci64Base, Pci64Size;=0D + RETURN_STATUS PcdStatus;=0D +=0D + FirstNonAddress =3D BASE_4GB + GetSystemMemorySizeAbove4gb ();=0D +=0D + //=0D + // If DXE is 32-bit, then we're done; PciBusDxe will degrade 64-bit MMIO= =0D + // resources to 32-bit anyway. See DegradeResource() in=0D + // "PciResourceSupport.c".=0D + //=0D +#ifdef MDE_CPU_IA32=0D + if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {=0D + return FirstNonAddress;=0D + }=0D +#endif=0D +=0D + //=0D + // Otherwise, in order to calculate the highest address plus one, we mus= t=0D + // consider the 64-bit PCI host aperture too. Fetch the default size.=0D + //=0D + Pci64Size =3D PcdGet64 (PcdPciMmio64Size);=0D +=0D + if (Pci64Size =3D=3D 0) {=0D + if (mBootMode !=3D BOOT_ON_S3_RESUME) {=0D + DEBUG ((DEBUG_INFO, "%a: disabling 64-bit PCI host aperture\n",=0D + __FUNCTION__));=0D + PcdStatus =3D PcdSet64S (PcdPciMmio64Size, 0);=0D + ASSERT_RETURN_ERROR (PcdStatus);=0D + }=0D +=0D + //=0D + // There's nothing more to do; the amount of memory above 4GB fully=0D + // determines the highest address plus one. The memory hotplug area (s= ee=0D + // below) plays no role for the firmware in this case.=0D + //=0D + return FirstNonAddress;=0D + }=0D +=0D + //=0D + // SeaBIOS aligns both boundaries of the 64-bit PCI host aperture to 1GB= , so=0D + // that the host can map it with 1GB hugepages. Follow suit.=0D + //=0D + Pci64Base =3D ALIGN_VALUE (FirstNonAddress, (UINT64)SIZE_1GB);=0D + Pci64Size =3D ALIGN_VALUE (Pci64Size, (UINT64)SIZE_1GB);=0D +=0D + //=0D + // The 64-bit PCI host aperture should also be "naturally" aligned. The= =0D + // alignment is determined by rounding the size of the aperture down to = the=0D + // next smaller or equal power of two. That is, align the aperture by th= e=0D + // largest BAR size that can fit into it.=0D + //=0D + Pci64Base =3D ALIGN_VALUE (Pci64Base, GetPowerOfTwo64 (Pci64Size));=0D +=0D + if (mBootMode !=3D BOOT_ON_S3_RESUME) {=0D + //=0D + // The core PciHostBridgeDxe driver will automatically add this range = to=0D + // the GCD memory space map through our PciHostBridgeLib instance; her= e we=0D + // only need to set the PCDs.=0D + //=0D + PcdStatus =3D PcdSet64S (PcdPciMmio64Base, Pci64Base);=0D + ASSERT_RETURN_ERROR (PcdStatus);=0D + PcdStatus =3D PcdSet64S (PcdPciMmio64Size, Pci64Size);=0D + ASSERT_RETURN_ERROR (PcdStatus);=0D +=0D + DEBUG ((DEBUG_INFO, "%a: Pci64Base=3D0x%Lx Pci64Size=3D0x%Lx\n",=0D + __FUNCTION__, Pci64Base, Pci64Size));=0D + }=0D +=0D + //=0D + // The useful address space ends with the 64-bit PCI host aperture.=0D + //=0D + FirstNonAddress =3D Pci64Base + Pci64Size;=0D + return FirstNonAddress;=0D +}=0D +=0D +=0D +/**=0D + Initialize the mPhysMemAddressWidth variable, based on guest RAM size.=0D +**/=0D +VOID=0D +AddressWidthInitialization (=0D + VOID=0D + )=0D +{=0D + UINT64 FirstNonAddress;=0D +=0D + //=0D + // As guest-physical memory size grows, the permanent PEI RAM requiremen= ts=0D + // are dominated by the identity-mapping page tables built by the DXE IP= L.=0D + // The DXL IPL keys off of the physical address bits advertized in the C= PU=0D + // HOB. To conserve memory, we calculate the minimum address width here.= =0D + //=0D + FirstNonAddress =3D GetFirstNonAddress ();=0D + mPhysMemAddressWidth =3D (UINT8)HighBitSet64 (FirstNonAddress);=0D +=0D + //=0D + // If FirstNonAddress is not an integral power of two, then we need an=0D + // additional bit.=0D + //=0D + if ((FirstNonAddress & (FirstNonAddress - 1)) !=3D 0) {=0D + ++mPhysMemAddressWidth;=0D + }=0D +=0D + //=0D + // The minimum address width is 36 (covers up to and excluding 64 GB, wh= ich=0D + // is the maximum for Ia32 + PAE). The theoretical architecture maximum = for=0D + // X64 long mode is 52 bits, but the DXE IPL clamps that down to 48 bits= . We=0D + // can simply assert that here, since 48 bits are good enough for 256 TB= .=0D + //=0D + if (mPhysMemAddressWidth <=3D 36) {=0D + mPhysMemAddressWidth =3D 36;=0D + }=0D + ASSERT (mPhysMemAddressWidth <=3D 48);=0D +}=0D +=0D +=0D +/**=0D + Calculate the cap for the permanent PEI memory.=0D +**/=0D +STATIC=0D +UINT32=0D +GetPeiMemoryCap (=0D + VOID=0D + )=0D +{=0D + BOOLEAN Page1GSupport;=0D + UINT32 RegEax;=0D + UINT32 RegEdx;=0D + UINT32 Pml4Entries;=0D + UINT32 PdpEntries;=0D + UINTN TotalPages;=0D +=0D + //=0D + // If DXE is 32-bit, then just return the traditional 64 MB cap.=0D + //=0D +#ifdef MDE_CPU_IA32=0D + if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {=0D + return SIZE_64MB;=0D + }=0D +#endif=0D +=0D + //=0D + // Dependent on physical address width, PEI memory allocations can be=0D + // dominated by the page tables built for 64-bit DXE. So we key the cap = off=0D + // of those. The code below is based on CreateIdentityMappingPageTables(= ) in=0D + // "MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c".=0D + //=0D + Page1GSupport =3D FALSE;=0D + if (PcdGetBool (PcdUse1GPageTable)) {=0D + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);=0D + if (RegEax >=3D 0x80000001) {=0D + AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);=0D + if ((RegEdx & BIT26) !=3D 0) {=0D + Page1GSupport =3D TRUE;=0D + }=0D + }=0D + }=0D +=0D + if (mPhysMemAddressWidth <=3D 39) {=0D + Pml4Entries =3D 1;=0D + PdpEntries =3D 1 << (mPhysMemAddressWidth - 30);=0D + ASSERT (PdpEntries <=3D 0x200);=0D + } else {=0D + Pml4Entries =3D 1 << (mPhysMemAddressWidth - 39);=0D + ASSERT (Pml4Entries <=3D 0x200);=0D + PdpEntries =3D 512;=0D + }=0D +=0D + TotalPages =3D Page1GSupport ? Pml4Entries + 1 :=0D + (PdpEntries + 1) * Pml4Entries + 1;=0D + ASSERT (TotalPages <=3D 0x40201);=0D +=0D + //=0D + // Add 64 MB for miscellaneous allocations. Note that for=0D + // mPhysMemAddressWidth values close to 36, the cap will actually be=0D + // dominated by this increment.=0D + //=0D + return (UINT32)(EFI_PAGES_TO_SIZE (TotalPages) + SIZE_64MB);=0D +}=0D +=0D +=0D +/**=0D + Publish PEI core memory=0D +=0D + @return EFI_SUCCESS The PEIM initialized successfully.=0D +=0D +**/=0D +EFI_STATUS=0D +PublishPeiMemory (=0D + VOID=0D + )=0D +{=0D + EFI_STATUS Status;=0D + EFI_PHYSICAL_ADDRESS MemoryBase;=0D + UINT64 MemorySize;=0D + UINT32 LowerMemorySize;=0D + UINT32 PeiMemoryCap;=0D +=0D + LowerMemorySize =3D GetSystemMemorySizeBelow4gb ();=0D + if (FeaturePcdGet (PcdSmmSmramRequire)) {=0D + //=0D + // TSEG is chipped from the end of low RAM=0D + //=0D + LowerMemorySize -=3D mQ35TsegMbytes * SIZE_1MB;=0D + }=0D +=0D + //=0D + // If S3 is supported, then the S3 permanent PEI memory is placed next,= =0D + // downwards. Its size is primarily dictated by CpuMpPei. The formula be= low=0D + // is an approximation.=0D + //=0D + if (mS3Supported) {=0D + mS3AcpiReservedMemorySize =3D SIZE_512KB +=0D + mMaxCpuCount *=0D + PcdGet32 (PcdCpuApStackSize);=0D + mS3AcpiReservedMemoryBase =3D LowerMemorySize - mS3AcpiReservedMemoryS= ize;=0D + LowerMemorySize =3D mS3AcpiReservedMemoryBase;=0D + }=0D +=0D + if (mBootMode =3D=3D BOOT_ON_S3_RESUME) {=0D + MemoryBase =3D mS3AcpiReservedMemoryBase;=0D + MemorySize =3D mS3AcpiReservedMemorySize;=0D + } else {=0D + PeiMemoryCap =3D GetPeiMemoryCap ();=0D + DEBUG ((DEBUG_INFO, "%a: mPhysMemAddressWidth=3D%d PeiMemoryCap=3D%u K= B\n",=0D + __FUNCTION__, mPhysMemAddressWidth, PeiMemoryCap >> 10));=0D +=0D + //=0D + // Determine the range of memory to use during PEI=0D + //=0D + // Technically we could lay the permanent PEI RAM over SEC's temporary= =0D + // decompression and scratch buffer even if "secure S3" is needed, sin= ce=0D + // their lifetimes don't overlap. However, PeiFvInitialization() will = cover=0D + // RAM up to PcdOvmfDecompressionScratchEnd with an EfiACPIMemoryNVS m= emory=0D + // allocation HOB, and other allocations served from the permanent PEI= RAM=0D + // shouldn't overlap with that HOB.=0D + //=0D + MemoryBase =3D mS3Supported && FeaturePcdGet (PcdSmmSmramRequire) ?=0D + PcdGet32 (PcdOvmfDecompressionScratchEnd) :=0D + PcdGet32 (PcdOvmfDxeMemFvBase) + PcdGet32 (PcdOvmfDxeMemFvSize);=0D + MemorySize =3D LowerMemorySize - MemoryBase;=0D + if (MemorySize > PeiMemoryCap) {=0D + MemoryBase =3D LowerMemorySize - PeiMemoryCap;=0D + MemorySize =3D PeiMemoryCap;=0D + }=0D + }=0D +=0D + //=0D + // Publish this memory to the PEI Core=0D + //=0D + Status =3D PublishSystemMemory(MemoryBase, MemorySize);=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + return Status;=0D +}=0D +=0D +=0D +/**=0D + Peform Memory Detection for QEMU / KVM=0D +=0D +**/=0D +STATIC=0D +VOID=0D +QemuInitializeRam (=0D + VOID=0D + )=0D +{=0D + UINT64 LowerMemorySize;=0D + UINT64 UpperMemorySize;=0D + MTRR_SETTINGS MtrrSettings;=0D + EFI_STATUS Status;=0D +=0D + DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));=0D +=0D + //=0D + // Determine total memory size available=0D + //=0D + LowerMemorySize =3D GetSystemMemorySizeBelow4gb ();=0D + UpperMemorySize =3D GetSystemMemorySizeAbove4gb ();=0D +=0D + if (mBootMode =3D=3D BOOT_ON_S3_RESUME) {=0D + //=0D + // Create the following memory HOB as an exception on the S3 boot path= .=0D + //=0D + // Normally we'd create memory HOBs only on the normal boot path. Howe= ver,=0D + // CpuMpPei specifically needs such a low-memory HOB on the S3 path as= =0D + // well, for "borrowing" a subset of it temporarily, for the AP startu= p=0D + // vector.=0D + //=0D + // CpuMpPei saves the original contents of the borrowed area in perman= ent=0D + // PEI RAM, in a backup buffer allocated with the normal PEI services.= =0D + // CpuMpPei restores the original contents ("returns" the borrowed are= a) at=0D + // End-of-PEI. End-of-PEI in turn is emitted by S3Resume2Pei before=0D + // transferring control to the OS's wakeup vector in the FACS.=0D + //=0D + // We expect any other PEIMs that "borrow" memory similarly to CpuMpPe= i to=0D + // restore the original contents. Furthermore, we expect all such PEIM= s=0D + // (CpuMpPei included) to claim the borrowed areas by producing memory= =0D + // allocation HOBs, and to honor preexistent memory allocation HOBs wh= en=0D + // looking for an area to borrow.=0D + //=0D + AddMemoryRangeHob (0, BASE_512KB + BASE_128KB);=0D + } else {=0D + //=0D + // Create memory HOBs=0D + //=0D + AddMemoryRangeHob (0, BASE_512KB + BASE_128KB);=0D +=0D + if (FeaturePcdGet (PcdSmmSmramRequire)) {=0D + UINT32 TsegSize;=0D +=0D + TsegSize =3D mQ35TsegMbytes * SIZE_1MB;=0D + AddMemoryRangeHob (BASE_1MB, LowerMemorySize - TsegSize);=0D + AddReservedMemoryBaseSizeHob (LowerMemorySize - TsegSize, TsegSize,= =0D + TRUE);=0D + } else {=0D + AddMemoryRangeHob (BASE_1MB, LowerMemorySize);=0D + }=0D +=0D + if (UpperMemorySize !=3D 0) {=0D + AddMemoryBaseSizeHob (BASE_4GB, UpperMemorySize);=0D + }=0D + }=0D +=0D + //=0D + // We'd like to keep the following ranges uncached:=0D + // - [640 KB, 1 MB)=0D + // - [LowerMemorySize, 4 GB)=0D + //=0D + // Everything else should be WB. Unfortunately, programming the inverse = (ie.=0D + // keeping the default UC, and configuring the complement set of the abo= ve as=0D + // WB) is not reliable in general, because the end of the upper RAM can = have=0D + // practically any alignment, and we may not have enough variable MTRRs = to=0D + // cover it exactly.=0D + //=0D + if (IsMtrrSupported ()) {=0D + MtrrGetAllMtrrs (&MtrrSettings);=0D +=0D + //=0D + // MTRRs disabled, fixed MTRRs disabled, default type is uncached=0D + //=0D + ASSERT ((MtrrSettings.MtrrDefType & BIT11) =3D=3D 0);=0D + ASSERT ((MtrrSettings.MtrrDefType & BIT10) =3D=3D 0);=0D + ASSERT ((MtrrSettings.MtrrDefType & 0xFF) =3D=3D 0);=0D +=0D + //=0D + // flip default type to writeback=0D + //=0D + SetMem (&MtrrSettings.Fixed, sizeof MtrrSettings.Fixed, 0x06);=0D + ZeroMem (&MtrrSettings.Variables, sizeof MtrrSettings.Variables);=0D + MtrrSettings.MtrrDefType |=3D BIT11 | BIT10 | 6;=0D + MtrrSetAllMtrrs (&MtrrSettings);=0D +=0D + //=0D + // Set memory range from 640KB to 1MB to uncacheable=0D + //=0D + Status =3D MtrrSetMemoryAttribute (BASE_512KB + BASE_128KB,=0D + BASE_1MB - (BASE_512KB + BASE_128KB), CacheUncacheable);=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + //=0D + // Set memory range from the "top of lower RAM" (RAM below 4GB) to 4GB= as=0D + // uncacheable=0D + //=0D + Status =3D MtrrSetMemoryAttribute (LowerMemorySize,=0D + SIZE_4GB - LowerMemorySize, CacheUncacheable);=0D + ASSERT_EFI_ERROR (Status);=0D + }=0D +}=0D +=0D +/**=0D + Publish system RAM and reserve memory regions=0D +=0D +**/=0D +VOID=0D +InitializeRamRegions (=0D + VOID=0D + )=0D +{=0D + QemuInitializeRam ();=0D +=0D + if (mS3Supported && mBootMode !=3D BOOT_ON_S3_RESUME) {=0D + //=0D + // This is the memory range that will be used for PEI on S3 resume=0D + //=0D + BuildMemoryAllocationHob (=0D + mS3AcpiReservedMemoryBase,=0D + mS3AcpiReservedMemorySize,=0D + EfiACPIMemoryNVS=0D + );=0D +=0D + //=0D + // Cover the initial RAM area used as stack and temporary PEI heap.=0D + //=0D + // This is reserved as ACPI NVS so it can be used on S3 resume.=0D + //=0D + BuildMemoryAllocationHob (=0D + PcdGet32 (PcdOvmfSecPeiTempRamBase),=0D + PcdGet32 (PcdOvmfSecPeiTempRamSize),=0D + EfiACPIMemoryNVS=0D + );=0D +=0D + //=0D + // SEC stores its table of GUIDed section handlers here.=0D + //=0D + BuildMemoryAllocationHob (=0D + PcdGet64 (PcdGuidedExtractHandlerTableAddress),=0D + PcdGet32 (PcdGuidedExtractHandlerTableSize),=0D + EfiACPIMemoryNVS=0D + );=0D +=0D +#ifdef MDE_CPU_X64=0D + //=0D + // Reserve the initial page tables built by the reset vector code.=0D + //=0D + // Since this memory range will be used by the Reset Vector on S3=0D + // resume, it must be reserved as ACPI NVS.=0D + //=0D + BuildMemoryAllocationHob (=0D + (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdOvmfSecPageTablesBase),=0D + (UINT64)(UINTN) PcdGet32 (PcdOvmfSecPageTablesSize),=0D + EfiACPIMemoryNVS=0D + );=0D +#endif=0D + }=0D +=0D + if (mBootMode !=3D BOOT_ON_S3_RESUME) {=0D + if (!FeaturePcdGet (PcdSmmSmramRequire)) {=0D + //=0D + // Reserve the lock box storage area=0D + //=0D + // Since this memory range will be used on S3 resume, it must be=0D + // reserved as ACPI NVS.=0D + //=0D + // If S3 is unsupported, then various drivers might still write to t= he=0D + // LockBox area. We ought to prevent DXE from serving allocation req= uests=0D + // such that they would overlap the LockBox storage.=0D + //=0D + ZeroMem (=0D + (VOID*)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageBase),=0D + (UINTN) PcdGet32 (PcdOvmfLockBoxStorageSize)=0D + );=0D + BuildMemoryAllocationHob (=0D + (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageBase)= ,=0D + (UINT64)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageSize),=0D + mS3Supported ? EfiACPIMemoryNVS : EfiBootServicesData=0D + );=0D + }=0D +=0D + if (FeaturePcdGet (PcdSmmSmramRequire)) {=0D + UINT32 TsegSize;=0D +=0D + //=0D + // Make sure the TSEG area that we reported as a reserved memory res= ource=0D + // cannot be used for reserved memory allocations.=0D + //=0D + TsegSize =3D mQ35TsegMbytes * SIZE_1MB;=0D + BuildMemoryAllocationHob (=0D + GetSystemMemorySizeBelow4gb() - TsegSize,=0D + TsegSize,=0D + EfiReservedMemoryType=0D + );=0D + }=0D + }=0D +}=0D diff --git a/OvmfPkg/PlatformPei/PlatformBhyve.c b/OvmfPkg/PlatformPei/Plat= formBhyve.c new file mode 100644 index 0000000000..10719d6f08 --- /dev/null +++ b/OvmfPkg/PlatformPei/PlatformBhyve.c @@ -0,0 +1,612 @@ +/**@file=0D + Platform PEI driver=0D +=0D + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
=0D + Copyright (c) 2011, Andrei Warkentin =0D +=0D + This program and the accompanying materials=0D + are licensed and made available under the terms and conditions of the BS= D License=0D + which accompanies this distribution. The full text of the license may b= e found at=0D + http://opensource.org/licenses/bsd-license.php=0D +=0D + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,=0D + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED.=0D +=0D +**/=0D +=0D +//=0D +// The package level header files this module uses=0D +//=0D +#include =0D +=0D +//=0D +// The Library classes this module consumes=0D +//=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +#include "Platform.h"=0D +#include "Cmos.h"=0D +=0D +EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] =3D {=0D + { EfiACPIMemoryNVS, 0x004 },=0D + { EfiACPIReclaimMemory, 0x008 },=0D + { EfiReservedMemoryType, 0x004 },=0D + { EfiRuntimeServicesData, 0x024 },=0D + { EfiRuntimeServicesCode, 0x030 },=0D + { EfiBootServicesCode, 0x180 },=0D + { EfiBootServicesData, 0xF00 },=0D + { EfiMaxMemoryType, 0x000 }=0D +};=0D +=0D +=0D +EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] =3D {=0D + {=0D + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,=0D + &gEfiPeiMasterBootModePpiGuid,=0D + NULL=0D + }=0D +};=0D +=0D +=0D +UINT16 mHostBridgeDevId;=0D +=0D +EFI_BOOT_MODE mBootMode =3D BOOT_WITH_FULL_CONFIGURATION;=0D +=0D +BOOLEAN mS3Supported =3D FALSE;=0D +=0D +UINT32 mMaxCpuCount;=0D +=0D +VOID=0D +AddIoMemoryBaseSizeHob (=0D + EFI_PHYSICAL_ADDRESS MemoryBase,=0D + UINT64 MemorySize=0D + )=0D +{=0D + BuildResourceDescriptorHob (=0D + EFI_RESOURCE_MEMORY_MAPPED_IO,=0D + EFI_RESOURCE_ATTRIBUTE_PRESENT |=0D + EFI_RESOURCE_ATTRIBUTE_INITIALIZED |=0D + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |=0D + EFI_RESOURCE_ATTRIBUTE_TESTED,=0D + MemoryBase,=0D + MemorySize=0D + );=0D +}=0D +=0D +VOID=0D +AddReservedMemoryBaseSizeHob (=0D + EFI_PHYSICAL_ADDRESS MemoryBase,=0D + UINT64 MemorySize,=0D + BOOLEAN Cacheable=0D + )=0D +{=0D + BuildResourceDescriptorHob (=0D + EFI_RESOURCE_MEMORY_RESERVED,=0D + EFI_RESOURCE_ATTRIBUTE_PRESENT |=0D + EFI_RESOURCE_ATTRIBUTE_INITIALIZED |=0D + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |=0D + (Cacheable ?=0D + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |=0D + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |=0D + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE :=0D + 0=0D + ) |=0D + EFI_RESOURCE_ATTRIBUTE_TESTED,=0D + MemoryBase,=0D + MemorySize=0D + );=0D +}=0D +=0D +VOID=0D +AddIoMemoryRangeHob (=0D + EFI_PHYSICAL_ADDRESS MemoryBase,=0D + EFI_PHYSICAL_ADDRESS MemoryLimit=0D + )=0D +{=0D + AddIoMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));= =0D +}=0D +=0D +=0D +VOID=0D +AddMemoryBaseSizeHob (=0D + EFI_PHYSICAL_ADDRESS MemoryBase,=0D + UINT64 MemorySize=0D + )=0D +{=0D + BuildResourceDescriptorHob (=0D + EFI_RESOURCE_SYSTEM_MEMORY,=0D + EFI_RESOURCE_ATTRIBUTE_PRESENT |=0D + EFI_RESOURCE_ATTRIBUTE_INITIALIZED |=0D + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |=0D + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |=0D + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |=0D + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |=0D + EFI_RESOURCE_ATTRIBUTE_TESTED,=0D + MemoryBase,=0D + MemorySize=0D + );=0D +}=0D +=0D +=0D +VOID=0D +AddMemoryRangeHob (=0D + EFI_PHYSICAL_ADDRESS MemoryBase,=0D + EFI_PHYSICAL_ADDRESS MemoryLimit=0D + )=0D +{=0D + AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));=0D +}=0D +=0D +=0D +VOID=0D +MemMapInitialization (=0D + VOID=0D + )=0D +{=0D + UINT64 PciIoBase;=0D + UINT64 PciIoSize;=0D + RETURN_STATUS PcdStatus;=0D +=0D + PciIoBase =3D 0xC000;=0D + PciIoSize =3D 0x4000;=0D +=0D + //=0D + // Create Memory Type Information HOB=0D + //=0D + BuildGuidDataHob (=0D + &gEfiMemoryTypeInformationGuid,=0D + mDefaultMemoryTypeInformation,=0D + sizeof(mDefaultMemoryTypeInformation)=0D + );=0D +=0D + //=0D + // Video memory + Legacy BIOS region=0D + //=0D + AddIoMemoryRangeHob (0x0A0000, BASE_1MB);=0D +=0D + if (TRUE) {=0D + UINT32 TopOfLowRam;=0D + UINT64 PciExBarBase;=0D + UINT32 PciBase;=0D + UINT32 PciSize;=0D +=0D + TopOfLowRam =3D GetSystemMemorySizeBelow4gb ();=0D + PciExBarBase =3D 0;=0D + if (mHostBridgeDevId =3D=3D INTEL_Q35_MCH_DEVICE_ID) {=0D + //=0D + // The MMCONFIG area is expected to fall between the top of low RAM = and=0D + // the base of the 32-bit PCI host aperture.=0D + //=0D + PciExBarBase =3D FixedPcdGet64 (PcdPciExpressBaseAddress);=0D + ASSERT (TopOfLowRam <=3D PciExBarBase);=0D + ASSERT (PciExBarBase <=3D MAX_UINT32 - SIZE_256MB);=0D + PciBase =3D (UINT32)(PciExBarBase + SIZE_256MB);=0D + } else {=0D + PciBase =3D (TopOfLowRam < BASE_2GB) ? BASE_2GB : TopOfLowRam;=0D + }=0D +=0D + //=0D + // address purpose size=0D + // ------------ -------- -------------------------=0D + // max(top, 2g) PCI MMIO 0xFC000000 - max(top, 2g)=0D + // 0xFC000000 gap 44 MB=0D + // 0xFEC00000 IO-APIC 4 KB=0D + // 0xFEC01000 gap 1020 KB=0D + // 0xFED00000 HPET 1 KB=0D + // 0xFED00400 gap 111 KB=0D + // 0xFED1C000 gap (PIIX4) / RCRB (ICH9) 16 KB=0D + // 0xFED20000 gap 896 KB=0D + // 0xFEE00000 LAPIC 1 MB=0D + //=0D + PciSize =3D 0xFC000000 - PciBase;=0D + AddIoMemoryBaseSizeHob (PciBase, PciSize);=0D + PcdStatus =3D PcdSet64S (PcdPciMmio32Base, PciBase);=0D + ASSERT_RETURN_ERROR (PcdStatus);=0D + PcdStatus =3D PcdSet64S (PcdPciMmio32Size, PciSize);=0D + ASSERT_RETURN_ERROR (PcdStatus);=0D +=0D + AddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB);=0D + AddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB);=0D + if (mHostBridgeDevId =3D=3D INTEL_Q35_MCH_DEVICE_ID) {=0D + AddIoMemoryBaseSizeHob (ICH9_ROOT_COMPLEX_BASE, SIZE_16KB);=0D + //=0D + // Note: there should be an=0D + //=0D + // AddIoMemoryBaseSizeHob (PciExBarBase, SIZE_256MB);=0D + //=0D + // call below, just like the one above for RCBA. However, Linux insi= sts=0D + // that the MMCONFIG area be marked in the E820 or UEFI memory map a= s=0D + // "reserved memory" -- Linux does not content itself with a simple = gap=0D + // in the memory map wherever the MCFG ACPI table points to.=0D + //=0D + // This appears to be a safety measure. The PCI Firmware Specificati= on=0D + // (rev 3.1) says in 4.1.2. "MCFG Table Description": "The resources= can=0D + // *optionally* be returned in [...] EFIGetMemoryMap as reserved mem= ory=0D + // [...]". (Emphasis added here.)=0D + //=0D + // Normally we add memory resource descriptor HOBs in=0D + // QemuInitializeRam(), and pre-allocate from those with memory=0D + // allocation HOBs in InitializeRamRegions(). However, the MMCONFIG = area=0D + // is most definitely not RAM; so, as an exception, cover it with=0D + // uncacheable reserved memory right here.=0D + //=0D + AddReservedMemoryBaseSizeHob (PciExBarBase, SIZE_256MB, FALSE);=0D + BuildMemoryAllocationHob (PciExBarBase, SIZE_256MB,=0D + EfiReservedMemoryType);=0D + }=0D + AddIoMemoryBaseSizeHob (PcdGet32(PcdCpuLocalApicBaseAddress), SIZE_1MB= );=0D +=0D + //=0D + // On Q35, the IO Port space is available for PCI resource allocations= from=0D + // 0x6000 up.=0D + //=0D + if (mHostBridgeDevId =3D=3D INTEL_Q35_MCH_DEVICE_ID) {=0D + PciIoBase =3D 0x6000;=0D + PciIoSize =3D 0xA000;=0D + ASSERT ((ICH9_PMBASE_VALUE & 0xF000) < PciIoBase);=0D + }=0D + }=0D +=0D + //=0D + // Add PCI IO Port space available for PCI resource allocations.=0D + //=0D + BuildResourceDescriptorHob (=0D + EFI_RESOURCE_IO,=0D + EFI_RESOURCE_ATTRIBUTE_PRESENT |=0D + EFI_RESOURCE_ATTRIBUTE_INITIALIZED,=0D + PciIoBase,=0D + PciIoSize=0D + );=0D + PcdStatus =3D PcdSet64S (PcdPciIoBase, PciIoBase);=0D + ASSERT_RETURN_ERROR (PcdStatus);=0D + PcdStatus =3D PcdSet64S (PcdPciIoSize, PciIoSize);=0D + ASSERT_RETURN_ERROR (PcdStatus);=0D +}=0D +=0D +VOID=0D +NoexecDxeInitialization (=0D + VOID=0D + )=0D +{=0D +}=0D +=0D +VOID=0D +PciExBarInitialization (=0D + VOID=0D + )=0D +{=0D + union {=0D + UINT64 Uint64;=0D + UINT32 Uint32[2];=0D + } PciExBarBase;=0D +=0D + //=0D + // We only support the 256MB size for the MMCONFIG area:=0D + // 256 buses * 32 devices * 8 functions * 4096 bytes config space.=0D + //=0D + // The masks used below enforce the Q35 requirements that the MMCONFIG a= rea=0D + // be (a) correctly aligned -- here at 256 MB --, (b) located under 64 G= B.=0D + //=0D + // Note that (b) also ensures that the minimum address width we have=0D + // determined in AddressWidthInitialization(), i.e., 36 bits, will suffi= ce=0D + // for DXE's page tables to cover the MMCONFIG area.=0D + //=0D + PciExBarBase.Uint64 =3D FixedPcdGet64 (PcdPciExpressBaseAddress);=0D + ASSERT ((PciExBarBase.Uint32[1] & MCH_PCIEXBAR_HIGHMASK) =3D=3D 0);=0D + ASSERT ((PciExBarBase.Uint32[0] & MCH_PCIEXBAR_LOWMASK) =3D=3D 0);=0D +=0D + //=0D + // Clear the PCIEXBAREN bit first, before programming the high register.= =0D + //=0D + PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW), 0);=0D +=0D + //=0D + // Program the high register. Then program the low register, setting the= =0D + // MMCONFIG area size and enabling decoding at once.=0D + //=0D + PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_HIGH), PciExBarBase.Uint32[= 1]);=0D + PciWrite32 (=0D + DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW),=0D + PciExBarBase.Uint32[0] | MCH_PCIEXBAR_BUS_FF | MCH_PCIEXBAR_EN=0D + );=0D +}=0D +=0D +VOID=0D +MiscInitialization (=0D + VOID=0D + )=0D +{=0D + UINTN PmCmd;=0D + UINTN Pmba;=0D + UINT32 PmbaAndVal;=0D + UINT32 PmbaOrVal;=0D + UINTN AcpiCtlReg;=0D + UINT8 AcpiEnBit;=0D + RETURN_STATUS PcdStatus;=0D +=0D + //=0D + // Disable A20 Mask=0D + //=0D + IoOr8 (0x92, BIT1);=0D +=0D + //=0D + // Build the CPU HOB with guest RAM size dependent address width and 16-= bits=0D + // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed dur= ing=0D + // S3 resume as well, so we build it unconditionally.)=0D + //=0D + BuildCpuHob (mPhysMemAddressWidth, 16);=0D +=0D + //=0D + // Determine platform type and save Host Bridge DID to PCD=0D + //=0D + switch (mHostBridgeDevId) {=0D + case 0x1275: // BHYVE=0D + case INTEL_82441_DEVICE_ID:=0D + PmCmd =3D POWER_MGMT_REGISTER_PIIX4 (PCI_COMMAND_OFFSET);=0D + Pmba =3D POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);=0D + PmbaAndVal =3D ~(UINT32)PIIX4_PMBA_MASK;=0D + PmbaOrVal =3D PIIX4_PMBA_VALUE;=0D + AcpiCtlReg =3D POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMREGMISC);=0D + AcpiEnBit =3D PIIX4_PMREGMISC_PMIOSE;=0D + break;=0D + case INTEL_Q35_MCH_DEVICE_ID:=0D + PmCmd =3D POWER_MGMT_REGISTER_Q35 (PCI_COMMAND_OFFSET);=0D + Pmba =3D POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);=0D + PmbaAndVal =3D ~(UINT32)ICH9_PMBASE_MASK;=0D + PmbaOrVal =3D ICH9_PMBASE_VALUE;=0D + AcpiCtlReg =3D POWER_MGMT_REGISTER_Q35 (ICH9_ACPI_CNTL);=0D + AcpiEnBit =3D ICH9_ACPI_CNTL_ACPI_EN;=0D + break;=0D + default:=0D + DEBUG ((DEBUG_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",= =0D + __FUNCTION__, mHostBridgeDevId));=0D + ASSERT (FALSE);=0D + return;=0D + }=0D + PcdStatus =3D PcdSet16S (PcdOvmfHostBridgePciDevId, mHostBridgeDevId);=0D + ASSERT_RETURN_ERROR (PcdStatus);=0D +=0D + //=0D + // If the appropriate IOspace enable bit is set, assume the ACPI PMBA=0D + // has been configured (e.g., by Xen) and skip the setup here.=0D + // This matches the logic in AcpiTimerLibConstructor ().=0D + //=0D + if ((PciRead8 (AcpiCtlReg) & AcpiEnBit) =3D=3D 0) {=0D + //=0D + // The PEI phase should be exited with fully accessibe ACPI PM IO spac= e:=0D + // 1. set PMBA=0D + //=0D + PciAndThenOr32 (Pmba, PmbaAndVal, PmbaOrVal);=0D +=0D + //=0D + // 2. set PCICMD/IOSE=0D + //=0D + PciOr8 (PmCmd, EFI_PCI_COMMAND_IO_SPACE);=0D +=0D + //=0D + // 3. set ACPI PM IO enable bit (PMREGMISC:PMIOSE or ACPI_CNTL:ACPI_EN= )=0D + //=0D + PciOr8 (AcpiCtlReg, AcpiEnBit);=0D + }=0D +=0D + if (mHostBridgeDevId =3D=3D INTEL_Q35_MCH_DEVICE_ID) {=0D + //=0D + // Set Root Complex Register Block BAR=0D + //=0D + PciWrite32 (=0D + POWER_MGMT_REGISTER_Q35 (ICH9_RCBA),=0D + ICH9_ROOT_COMPLEX_BASE | ICH9_RCBA_EN=0D + );=0D +=0D + //=0D + // Set PCI Express Register Range Base Address=0D + //=0D + PciExBarInitialization ();=0D + }=0D +}=0D +=0D +=0D +VOID=0D +BootModeInitialization (=0D + VOID=0D + )=0D +{=0D + EFI_STATUS Status;=0D +=0D + if (CmosRead8 (0xF) =3D=3D 0xFE) {=0D + mBootMode =3D BOOT_ON_S3_RESUME;=0D + }=0D + CmosWrite8 (0xF, 0x00);=0D +=0D + Status =3D PeiServicesSetBootMode (mBootMode);=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + Status =3D PeiServicesInstallPpi (mPpiBootMode);=0D + ASSERT_EFI_ERROR (Status);=0D +}=0D +=0D +=0D +VOID=0D +ReserveEmuVariableNvStore (=0D + )=0D +{=0D + EFI_PHYSICAL_ADDRESS VariableStore;=0D + RETURN_STATUS PcdStatus;=0D +=0D + //=0D + // Allocate storage for NV variables early on so it will be=0D + // at a consistent address. Since VM memory is preserved=0D + // across reboots, this allows the NV variable storage to survive=0D + // a VM reboot.=0D + //=0D + VariableStore =3D=0D + (EFI_PHYSICAL_ADDRESS)(UINTN)=0D + AllocateRuntimePages (=0D + EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize))=0D + );=0D + DEBUG ((DEBUG_INFO,=0D + "Reserved variable store memory: 0x%lX; size: %dkb\n",=0D + VariableStore,=0D + (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / 1024=0D + ));=0D + PcdStatus =3D PcdSet64S (PcdEmuVariableNvStoreReserved, VariableStore);= =0D + ASSERT_RETURN_ERROR (PcdStatus);=0D +}=0D +=0D +=0D +VOID=0D +DebugDumpCmos (=0D + VOID=0D + )=0D +{=0D + UINT32 Loop;=0D +=0D + DEBUG ((DEBUG_INFO, "CMOS:\n"));=0D +=0D + for (Loop =3D 0; Loop < 0x80; Loop++) {=0D + if ((Loop % 0x10) =3D=3D 0) {=0D + DEBUG ((DEBUG_INFO, "%02x:", Loop));=0D + }=0D + DEBUG ((DEBUG_INFO, " %02x", CmosRead8 (Loop)));=0D + if ((Loop % 0x10) =3D=3D 0xf) {=0D + DEBUG ((DEBUG_INFO, "\n"));=0D + }=0D + }=0D +}=0D +=0D +=0D +VOID=0D +S3Verification (=0D + VOID=0D + )=0D +{=0D +#if defined (MDE_CPU_X64)=0D + if (FeaturePcdGet (PcdSmmSmramRequire) && mS3Supported) {=0D + DEBUG ((DEBUG_ERROR,=0D + "%a: S3Resume2Pei doesn't support X64 PEI + SMM yet.\n", __FUNCTION_= _));=0D + DEBUG ((DEBUG_ERROR,=0D + "%a: Please disable S3 on the QEMU command line (see the README),\n"= ,=0D + __FUNCTION__));=0D + DEBUG ((DEBUG_ERROR,=0D + "%a: or build OVMF with \"OvmfPkgIa32X64.dsc\".\n", __FUNCTION__));= =0D + ASSERT (FALSE);=0D + CpuDeadLoop ();=0D + }=0D +#endif=0D +}=0D +=0D +=0D +/**=0D + Fetch the number of boot CPUs from QEMU and expose it to UefiCpuPkg modu= les.=0D + Set the mMaxCpuCount variable.=0D +**/=0D +VOID=0D +MaxCpuCountInitialization (=0D + VOID=0D + )=0D +{=0D + UINT16 ProcessorCount =3D 0;=0D + RETURN_STATUS PcdStatus;=0D +=0D + //=0D + // If the fw_cfg key or fw_cfg entirely is unavailable, load mMaxCpuCoun= t=0D + // from the PCD default. No change to PCDs.=0D + //=0D + if (ProcessorCount =3D=3D 0) {=0D + mMaxCpuCount =3D PcdGet32 (PcdCpuMaxLogicalProcessorNumber);=0D + return;=0D + }=0D + //=0D + // Otherwise, set mMaxCpuCount to the value reported by QEMU.=0D + //=0D + mMaxCpuCount =3D ProcessorCount;=0D + //=0D + // Additionally, tell UefiCpuPkg modules (a) the exact number of VCPUs, = (b)=0D + // to wait, in the initial AP bringup, exactly as long as it takes for a= ll of=0D + // the APs to report in. For this, we set the longest representable time= out=0D + // (approx. 71 minutes).=0D + //=0D + PcdStatus =3D PcdSet32S (PcdCpuMaxLogicalProcessorNumber, ProcessorCount= );=0D + ASSERT_RETURN_ERROR (PcdStatus);=0D + PcdStatus =3D PcdSet32S (PcdCpuApInitTimeOutInMicroSeconds, MAX_UINT32);= =0D + ASSERT_RETURN_ERROR (PcdStatus);=0D + DEBUG ((DEBUG_INFO, "%a: QEMU reports %d processor(s)\n", __FUNCTION__,= =0D + ProcessorCount));=0D +}=0D +=0D +=0D +/**=0D + Perform Platform PEI initialization.=0D +=0D + @param FileHandle Handle of the file being invoked.=0D + @param PeiServices Describes the list of possible PEI Services.=0D +=0D + @return EFI_SUCCESS The PEIM initialized successfully.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +InitializePlatform (=0D + IN EFI_PEI_FILE_HANDLE FileHandle,=0D + IN CONST EFI_PEI_SERVICES **PeiServices=0D + )=0D +{=0D + DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n"));=0D +=0D + //=0D + // Initialize Local APIC Timer hardware and disable Local APIC Timer=0D + // interrupts before initializing the Debug Agent and the debug timer is= =0D + // enabled.=0D + //=0D + InitializeApicTimer (0, MAX_UINT32, TRUE, 5);=0D + DisableApicTimerInterrupt ();=0D +=0D + DebugDumpCmos ();=0D +=0D + BootModeInitialization ();=0D + AddressWidthInitialization ();=0D + MaxCpuCountInitialization ();=0D +=0D + //=0D + // Query Host Bridge DID=0D + //=0D + mHostBridgeDevId =3D PciRead16 (OVMF_HOSTBRIDGE_DID);=0D +=0D + if (FeaturePcdGet (PcdSmmSmramRequire)) {=0D + Q35TsegMbytesInitialization ();=0D + }=0D +=0D + PublishPeiMemory ();=0D +=0D + InitializeRamRegions ();=0D +=0D + if (mBootMode !=3D BOOT_ON_S3_RESUME) {=0D + if (!FeaturePcdGet (PcdSmmSmramRequire)) {=0D + ReserveEmuVariableNvStore ();=0D + }=0D + PeiFvInitialization ();=0D + MemMapInitialization ();=0D + NoexecDxeInitialization ();=0D + }=0D +=0D + InstallClearCacheCallback ();=0D + AmdSevInitialize ();=0D + MiscInitialization ();=0D + InstallFeatureControlCallback ();=0D +=0D + return EFI_SUCCESS;=0D +}=0D diff --git a/OvmfPkg/PlatformPei/PlatformPeiBhyve.inf b/OvmfPkg/PlatformPei= /PlatformPeiBhyve.inf new file mode 100644 index 0000000000..bf2d2a2798 --- /dev/null +++ b/OvmfPkg/PlatformPei/PlatformPeiBhyve.inf @@ -0,0 +1,119 @@ +## @file=0D +# Platform PEI driver=0D +#=0D +# This module provides platform specific function to detect boot mode.=0D +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
= =0D +#=0D +# This program and the accompanying materials=0D +# are licensed and made available under the terms and conditions of the B= SD License=0D +# which accompanies this distribution. The full text of the license may b= e found at=0D +# http://opensource.org/licenses/bsd-license.php=0D +#=0D +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,=0D +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IM= PLIED.=0D +#=0D +##=0D +=0D +[Defines]=0D + INF_VERSION =3D 0x00010005=0D + BASE_NAME =3D PlatformPei=0D + FILE_GUID =3D 222c386d-5abc-4fb4-b124-fbb82488acf4= =0D + MODULE_TYPE =3D PEIM=0D + VERSION_STRING =3D 1.0=0D + ENTRY_POINT =3D InitializePlatform=0D +=0D +#=0D +# The following information is for reference only and not required by the = build tools.=0D +#=0D +# VALID_ARCHITECTURES =3D IA32 X64 EBC=0D +#=0D +=0D +[Sources]=0D + AmdSev.c=0D + ClearCache.c=0D + Cmos.c=0D + Cmos.h=0D + FeatureControl.c=0D + Fv.c=0D + MemDetectBhyve.c=0D + PlatformBhyve.c=0D + Platform.h=0D +=0D +[Packages]=0D + MdePkg/MdePkg.dec=0D + MdeModulePkg/MdeModulePkg.dec=0D + SecurityPkg/SecurityPkg.dec=0D + UefiCpuPkg/UefiCpuPkg.dec=0D + OvmfPkg/OvmfPkg.dec=0D +=0D +[Guids]=0D + gEfiMemoryTypeInformationGuid=0D +=0D +[LibraryClasses]=0D + BaseLib=0D + CacheMaintenanceLib=0D + DebugLib=0D + HobLib=0D + IoLib=0D + PciLib=0D + ResourcePublicationLib=0D + PeiServicesLib=0D + PeiServicesTablePointerLib=0D + PeimEntryPoint=0D + QemuFwCfgLib=0D + QemuFwCfgS3Lib=0D + MtrrLib=0D + MemEncryptSevLib=0D + PcdLib=0D + LocalApicLib=0D +=0D +[Pcd]=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageBase=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageSize=0D + gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId=0D + gUefiOvmfPkgTokenSpaceGuid.PcdPciIoBase=0D + gUefiOvmfPkgTokenSpaceGuid.PcdPciIoSize=0D + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Base=0D + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Size=0D + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Base=0D + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Size=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecompressionScratchEnd=0D + gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegMbytes=0D + gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask=0D + gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy=0D + gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress=0D + gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber=0D + gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds=0D + gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize=0D +=0D +[FixedPcd]=0D + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress=0D +=0D +[FeaturePcd]=0D + gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire=0D +=0D +[Ppis]=0D + gEfiPeiMasterBootModePpiGuid=0D + gEfiPeiMpServicesPpiGuid=0D +=0D +[Depex]=0D + TRUE=0D +=0D --=20 2.26.1