From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=softfail (domain: citrix.com, ip: , mailfrom: anthony.perard@citrix.com) Received: from esa2.hc3370-68.iphmx.com (esa2.hc3370-68.iphmx.com []) by groups.io with SMTP; Thu, 04 Jul 2019 07:42:40 -0700 Authentication-Results: esa2.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=anthony.perard@citrix.com; spf=Pass smtp.mailfrom=anthony.perard@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa2.hc3370-68.iphmx.com: no sender authenticity information available from domain of anthony.perard@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa2.hc3370-68.iphmx.com; envelope-from="anthony.perard@citrix.com"; x-sender="anthony.perard@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa2.hc3370-68.iphmx.com: domain of anthony.perard@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa2.hc3370-68.iphmx.com; envelope-from="anthony.perard@citrix.com"; x-sender="anthony.perard@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ~all" Received-SPF: None (esa2.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa2.hc3370-68.iphmx.com; envelope-from="anthony.perard@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: EnsohF4y4H+z7i0GlObMcXj5tbs21bWA4PGpOMVJjEh84q14bSs11MgGLAKQNLgd50KDYQXSl/ jYhqrIvoPTViPfcIfby4guXNohAp+mLYoiNi/0k9Yp2tir6TPcwcs/6aWyEgq44lT6va4uj/jD bTvE4qd7+NcIlFID9Iv1JxmGLZgr6KjiAw1bB1+QBlrcttoY8EiIsHH5rLwAcMR/w+/eBVb3w6 KpYyDBlt4cXWvnfsAXkxGpo89SHcdCzSoDkjpvoW08krQbC7UIUkU5wWvIfUipMQp6LZ7lZ2K1 mGU= X-SBRS: 2.7 X-MesageID: 2588788 X-Ironport-Server: esa2.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.63,451,1557201600"; d="scan'208";a="2588788" From: "Anthony PERARD" To: CC: , Ard Biesheuvel , Jordan Justen , Laszlo Ersek , Julien Grall , Anthony PERARD Subject: [PATCH v3 04/35] OvmfPkg: Introduce XenPlatformPei Date: Thu, 4 Jul 2019 15:42:02 +0100 Message-ID: <20190704144233.27968-5-anthony.perard@citrix.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20190704144233.27968-1-anthony.perard@citrix.com> References: <20190704144233.27968-1-anthony.perard@citrix.com> MIME-Version: 1.0 Return-Path: anthony.perard@citrix.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain Introduce XenPlatformPei, a copy of OvmfPkg/PlatformPei without some of QEMU specific initialization, Xen does not support QemuFwCfg. This new module will be adjusted to accommodate Xen PVH. fw_cfg dependents that have been removed, which are dynamically skipped when running PlatformPei on Xen: - GetFirstNonAddress(): controlling the 64-bit PCI MMIO aperture via the (experimental) "opt/ovmf/X-PciMmio64Mb" file - GetFirstNonAddress(): honoring the hotplug DIMM area ("etc/reserved-memory-end") in the placement of the 64-bit PCI MMIO aperture - NoexecDxeInitialization() is removed, so PcdPropertiesTableEnable and PcdSetNxForStack are left constant FALSE (not set dynamically from fw_cfg "opt/ovmf/PcdXxxx") - MaxCpuCountInitialization(), PublishPeiMemory(): the max CPU count is not taken from the QemuFwCfgItemSmpCpuCount fw_cfg key; PcdCpuMaxLogicalProcessorNumber is used intact and PcdCpuApInitTimeOutInMicroSeconds is never changed or used. - InitializeXenPlatform(), S3Verification(): S3 is assumed disabled (not consulting "etc/system-states" via QemuFwCfgS3Enabled()). - InstallFeatureControlCallback(): the feature control MSR is not set from "etc/msr_feature_control" (also removed FeatureControl.c as there is nothing been executed) Also removed: - SMRAM/TSEG-related low mem size adjusting (PcdSmmSmramRequire is assumed FALSE) in PublishPeiMemory(), - QemuInitializeRam() entirely, Xen related changes: - Have removed the module variable mXen, as it should be always true. - Have the platform PEI initialization fails if Xen has not been detected. Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3D1689 Signed-off-by: Anthony PERARD Reviewed-by: Laszlo Ersek --- Notes: v3: - fix coding style in new code (use DEBUG_xxx, add ASSERT before CpuDeadLoop) - rebased, SPDX OvmfPkg/OvmfXen.dsc | 2 +- OvmfPkg/OvmfXen.fdf | 2 +- OvmfPkg/XenPlatformPei/XenPlatformPei.inf | 96 +++++ OvmfPkg/XenPlatformPei/Cmos.h | 52 +++ OvmfPkg/XenPlatformPei/Platform.h | 108 ++++++ OvmfPkg/XenPlatformPei/Xen.h | 39 ++ OvmfPkg/XenPlatformPei/AmdSev.c | 64 ++++ OvmfPkg/XenPlatformPei/ClearCache.c | 112 ++++++ OvmfPkg/XenPlatformPei/Cmos.c | 60 +++ OvmfPkg/XenPlatformPei/Fv.c | 76 ++++ OvmfPkg/XenPlatformPei/MemDetect.c | 421 ++++++++++++++++++++ OvmfPkg/XenPlatformPei/Platform.c | 444 ++++++++++++++++++++++ OvmfPkg/XenPlatformPei/Xen.c | 219 +++++++++++ 13 files changed, 1693 insertions(+), 2 deletions(-) create mode 100644 OvmfPkg/XenPlatformPei/XenPlatformPei.inf create mode 100644 OvmfPkg/XenPlatformPei/Cmos.h create mode 100644 OvmfPkg/XenPlatformPei/Platform.h create mode 100644 OvmfPkg/XenPlatformPei/Xen.h create mode 100644 OvmfPkg/XenPlatformPei/AmdSev.c create mode 100644 OvmfPkg/XenPlatformPei/ClearCache.c create mode 100644 OvmfPkg/XenPlatformPei/Cmos.c create mode 100644 OvmfPkg/XenPlatformPei/Fv.c create mode 100644 OvmfPkg/XenPlatformPei/MemDetect.c create mode 100644 OvmfPkg/XenPlatformPei/Platform.c create mode 100644 OvmfPkg/XenPlatformPei/Xen.c diff --git a/OvmfPkg/OvmfXen.dsc b/OvmfPkg/OvmfXen.dsc index cab54da3e8..9f79d455fa 100644 --- a/OvmfPkg/OvmfXen.dsc +++ b/OvmfPkg/OvmfXen.dsc @@ -523,7 +523,7 @@ [Components] }=0D MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf=0D =0D - OvmfPkg/PlatformPei/PlatformPei.inf=0D + OvmfPkg/XenPlatformPei/XenPlatformPei.inf=0D UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf=0D UefiCpuPkg/CpuMpPei/CpuMpPei.inf=0D =0D diff --git a/OvmfPkg/OvmfXen.fdf b/OvmfPkg/OvmfXen.fdf index 6fc8479aae..2ceff7baa2 100644 --- a/OvmfPkg/OvmfXen.fdf +++ b/OvmfPkg/OvmfXen.fdf @@ -152,7 +152,7 @@ [FV.PEIFV] INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf=0D INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRou= terPei.inf=0D INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf= =0D -INF OvmfPkg/PlatformPei/PlatformPei.inf=0D +INF OvmfPkg/XenPlatformPei/XenPlatformPei.inf=0D INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf=0D INF UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf=0D INF UefiCpuPkg/CpuMpPei/CpuMpPei.inf=0D diff --git a/OvmfPkg/XenPlatformPei/XenPlatformPei.inf b/OvmfPkg/XenPlatfor= mPei/XenPlatformPei.inf new file mode 100644 index 0000000000..d1265c365a --- /dev/null +++ b/OvmfPkg/XenPlatformPei/XenPlatformPei.inf @@ -0,0 +1,96 @@ +## @file=0D +# Platform PEI driver=0D +#=0D +# This module provides platform specific function to detect boot mode.=0D +# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
= =0D +# Copyright (c) 2019, Citrix Systems, Inc.=0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +##=0D +=0D +[Defines]=0D + INF_VERSION =3D 0x00010005=0D + BASE_NAME =3D XenPlatformPei=0D + FILE_GUID =3D f112a6ee-993a-4f0b-8295-e52029d9b4ba= =0D + MODULE_TYPE =3D PEIM=0D + VERSION_STRING =3D 1.0=0D + ENTRY_POINT =3D InitializeXenPlatform=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 + Fv.c=0D + MemDetect.c=0D + Platform.c=0D + Platform.h=0D + Xen.c=0D + Xen.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 + gEfiXenInfoGuid=0D +=0D +[LibraryClasses]=0D + BaseLib=0D + CacheMaintenanceLib=0D + DebugLib=0D + HobLib=0D + IoLib=0D + PciLib=0D + ResourcePublicationLib=0D + PeiServicesLib=0D + PeimEntryPoint=0D + MtrrLib=0D + MemEncryptSevLib=0D + PcdLib=0D +=0D +[Pcd]=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageBase=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageSize=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId=0D + gUefiOvmfPkgTokenSpaceGuid.PcdPciIoBase=0D + gUefiOvmfPkgTokenSpaceGuid.PcdPciIoSize=0D + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Base=0D + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Size=0D + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Base=0D + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Size=0D + gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegMbytes=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask=0D + gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy=0D + gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress=0D +=0D +[FixedPcd]=0D + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress=0D +=0D +[Ppis]=0D + gEfiPeiMasterBootModePpiGuid=0D + gEfiPeiMpServicesPpiGuid=0D +=0D +[Depex]=0D + TRUE=0D +=0D diff --git a/OvmfPkg/XenPlatformPei/Cmos.h b/OvmfPkg/XenPlatformPei/Cmos.h new file mode 100644 index 0000000000..80ffcb002f --- /dev/null +++ b/OvmfPkg/XenPlatformPei/Cmos.h @@ -0,0 +1,52 @@ +/** @file=0D + PC/AT CMOS access routines=0D +=0D + Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
=0D + Copyright (c) 2019, Citrix Systems, Inc.=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#ifndef __CMOS_H__=0D +#define __CMOS_H__=0D +=0D +/**=0D + Reads 8-bits of CMOS data.=0D +=0D + Reads the 8-bits of CMOS data at the location specified by Index.=0D + The 8-bit read value is returned.=0D +=0D + @param Index The CMOS location to read.=0D +=0D + @return The value read.=0D +=0D +**/=0D +UINT8=0D +EFIAPI=0D +CmosRead8 (=0D + IN UINTN Index=0D + );=0D +=0D +/**=0D + Writes 8-bits of CMOS data.=0D +=0D + Writes 8-bits of CMOS data to the location specified by Index=0D + with the value specified by Value and returns Value.=0D +=0D + @param Index The CMOS location to write.=0D + @param Value The value to write to CMOS.=0D +=0D + @return The value written to CMOS.=0D +=0D +**/=0D +UINT8=0D +EFIAPI=0D +CmosWrite8 (=0D + IN UINTN Index,=0D + IN UINT8 Value=0D + );=0D +=0D +=0D +#endif=0D +=0D diff --git a/OvmfPkg/XenPlatformPei/Platform.h b/OvmfPkg/XenPlatformPei/Pla= tform.h new file mode 100644 index 0000000000..77427496c0 --- /dev/null +++ b/OvmfPkg/XenPlatformPei/Platform.h @@ -0,0 +1,108 @@ +/** @file=0D + Platform PEI module include file.=0D +=0D + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
=0D + Copyright (c) 2019, Citrix Systems, Inc.=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#ifndef _PLATFORM_PEI_H_INCLUDED_=0D +#define _PLATFORM_PEI_H_INCLUDED_=0D +=0D +#include =0D +=0D +VOID=0D +AddIoMemoryBaseSizeHob (=0D + EFI_PHYSICAL_ADDRESS MemoryBase,=0D + UINT64 MemorySize=0D + );=0D +=0D +VOID=0D +AddIoMemoryRangeHob (=0D + EFI_PHYSICAL_ADDRESS MemoryBase,=0D + EFI_PHYSICAL_ADDRESS MemoryLimit=0D + );=0D +=0D +VOID=0D +AddMemoryBaseSizeHob (=0D + EFI_PHYSICAL_ADDRESS MemoryBase,=0D + UINT64 MemorySize=0D + );=0D +=0D +VOID=0D +AddMemoryRangeHob (=0D + EFI_PHYSICAL_ADDRESS MemoryBase,=0D + EFI_PHYSICAL_ADDRESS MemoryLimit=0D + );=0D +=0D +VOID=0D +AddReservedMemoryBaseSizeHob (=0D + EFI_PHYSICAL_ADDRESS MemoryBase,=0D + UINT64 MemorySize,=0D + BOOLEAN Cacheable=0D + );=0D +=0D +VOID=0D +AddressWidthInitialization (=0D + VOID=0D + );=0D +=0D +VOID=0D +Q35TsegMbytesInitialization (=0D + VOID=0D + );=0D +=0D +EFI_STATUS=0D +PublishPeiMemory (=0D + VOID=0D + );=0D +=0D +UINT32=0D +GetSystemMemorySizeBelow4gb (=0D + VOID=0D + );=0D +=0D +VOID=0D +InitializeRamRegions (=0D + VOID=0D + );=0D +=0D +EFI_STATUS=0D +PeiFvInitialization (=0D + VOID=0D + );=0D +=0D +VOID=0D +InstallClearCacheCallback (=0D + VOID=0D + );=0D +=0D +EFI_STATUS=0D +InitializeXen (=0D + VOID=0D + );=0D +=0D +BOOLEAN=0D +XenDetect (=0D + VOID=0D + );=0D +=0D +VOID=0D +AmdSevInitialize (=0D + VOID=0D + );=0D +=0D +VOID=0D +XenPublishRamRegions (=0D + VOID=0D + );=0D +=0D +extern EFI_BOOT_MODE mBootMode;=0D +=0D +extern UINT8 mPhysMemAddressWidth;=0D +=0D +extern UINT16 mHostBridgeDevId;=0D +=0D +#endif // _PLATFORM_PEI_H_INCLUDED_=0D diff --git a/OvmfPkg/XenPlatformPei/Xen.h b/OvmfPkg/XenPlatformPei/Xen.h new file mode 100644 index 0000000000..2605481280 --- /dev/null +++ b/OvmfPkg/XenPlatformPei/Xen.h @@ -0,0 +1,39 @@ +/** @file=0D + Ovmf info structure passed by Xen=0D +=0D +Copyright (c) 2013, Citrix Systems UK Ltd.
=0D +=0D +SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#ifndef __XEN_H__=0D +#define __XEN_H__=0D +=0D +#include =0D +=0D +// Physical address of OVMF info=0D +#define OVMF_INFO_PHYSICAL_ADDRESS 0x00001000=0D +=0D +// This structure must match the definition on Xen side=0D +#pragma pack(1)=0D +typedef struct {=0D + CHAR8 Signature[14]; // XenHVMOVMF\0=0D + UINT8 Length; // Length of this structure=0D + UINT8 Checksum; // Set such that the sum over bytes 0..length =3D= =3D 0=0D + //=0D + // Physical address of an array of TablesCount elements.=0D + //=0D + // Each element contains the physical address of a BIOS table.=0D + //=0D + EFI_PHYSICAL_ADDRESS Tables;=0D + UINT32 TablesCount;=0D + //=0D + // Physical address of the E820 table, contains E820EntriesCount entries= .=0D + //=0D + EFI_PHYSICAL_ADDRESS E820;=0D + UINT32 E820EntriesCount;=0D +} EFI_XEN_OVMF_INFO;=0D +#pragma pack()=0D +=0D +#endif /* __XEN_H__ */=0D diff --git a/OvmfPkg/XenPlatformPei/AmdSev.c b/OvmfPkg/XenPlatformPei/AmdSe= v.c new file mode 100644 index 0000000000..7ebbb5cc1f --- /dev/null +++ b/OvmfPkg/XenPlatformPei/AmdSev.c @@ -0,0 +1,64 @@ +/**@file=0D + Initialize Secure Encrypted Virtualization (SEV) support=0D +=0D + Copyright (c) 2017, Advanced Micro Devices. All rights reserved.
=0D + Copyright (c) 2019, Citrix Systems, Inc.=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +//=0D +// The package level header files this module uses=0D +//=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +#include "Platform.h"=0D +=0D +/**=0D +=0D + Function checks if SEV support is available, if present then it sets=0D + the dynamic PcdPteMemoryEncryptionAddressOrMask with memory encryption m= ask.=0D +=0D + **/=0D +VOID=0D +AmdSevInitialize (=0D + VOID=0D + )=0D +{=0D + CPUID_MEMORY_ENCRYPTION_INFO_EBX Ebx;=0D + UINT64 EncryptionMask;=0D + RETURN_STATUS PcdStatus;=0D +=0D + //=0D + // Check if SEV is enabled=0D + //=0D + if (!MemEncryptSevIsEnabled ()) {=0D + return;=0D + }=0D +=0D + //=0D + // CPUID Fn8000_001F[EBX] Bit 0:5 (memory encryption bit position)=0D + //=0D + AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, NULL, &Ebx.Uint32, NULL, NULL);= =0D + EncryptionMask =3D LShiftU64 (1, Ebx.Bits.PtePosBits);=0D +=0D + //=0D + // Set Memory Encryption Mask PCD=0D + //=0D + PcdStatus =3D PcdSet64S (PcdPteMemoryEncryptionAddressOrMask, Encryption= Mask);=0D + ASSERT_RETURN_ERROR (PcdStatus);=0D +=0D + DEBUG ((DEBUG_INFO, "SEV is enabled (mask 0x%lx)\n", EncryptionMask));=0D +=0D + //=0D + // Set Pcd to Deny the execution of option ROM when security=0D + // violation.=0D + //=0D + PcdStatus =3D PcdSet32S (PcdOptionRomImageVerificationPolicy, 0x4);=0D + ASSERT_RETURN_ERROR (PcdStatus);=0D +}=0D diff --git a/OvmfPkg/XenPlatformPei/ClearCache.c b/OvmfPkg/XenPlatformPei/C= learCache.c new file mode 100644 index 0000000000..fab53633a9 --- /dev/null +++ b/OvmfPkg/XenPlatformPei/ClearCache.c @@ -0,0 +1,112 @@ +/**@file=0D + Install a callback to clear cache on all processors.=0D + This is for conformance with the TCG "Platform Reset Attack Mitigation=0D + Specification". Because clearing the CPU caches at boot doesn't impact=0D + performance significantly, do it unconditionally, for simplicity's=0D + sake.=0D +=0D + Copyright (C) 2018, Red Hat, Inc.=0D + Copyright (c) 2019, Citrix Systems, Inc.=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +**/=0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +#include "Platform.h"=0D +=0D +/**=0D + Invalidate data & instruction caches.=0D + All APs execute this function in parallel. The BSP executes the function= =0D + separately.=0D +=0D + @param[in,out] WorkSpace Pointer to the input/output argument workspace= =0D + shared by all processors.=0D +**/=0D +STATIC=0D +VOID=0D +EFIAPI=0D +ClearCache (=0D + IN OUT VOID *WorkSpace=0D + )=0D +{=0D + WriteBackInvalidateDataCache ();=0D + InvalidateInstructionCache ();=0D +}=0D +=0D +/**=0D + Notification function called when EFI_PEI_MP_SERVICES_PPI becomes availa= ble.=0D +=0D + @param[in] PeiServices Indirect reference to the PEI Services Table= .=0D + @param[in] NotifyDescriptor Address of the notification descriptor data= =0D + structure.=0D + @param[in] Ppi Address of the PPI that was installed.=0D +=0D + @return Status of the notification. The status code returned from this= =0D + function is ignored.=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +EFIAPI=0D +ClearCacheOnMpServicesAvailable (=0D + IN EFI_PEI_SERVICES **PeiServices,=0D + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,=0D + IN VOID *Ppi=0D + )=0D +{=0D + EFI_PEI_MP_SERVICES_PPI *MpServices;=0D + EFI_STATUS Status;=0D +=0D + DEBUG ((DEBUG_INFO, "%a: %a\n", gEfiCallerBaseName, __FUNCTION__));=0D +=0D + //=0D + // Clear cache on all the APs in parallel.=0D + //=0D + MpServices =3D Ppi;=0D + Status =3D MpServices->StartupAllAPs (=0D + (CONST EFI_PEI_SERVICES **)PeiServices,=0D + MpServices,=0D + ClearCache, // Procedure=0D + FALSE, // SingleThread=0D + 0, // TimeoutInMicroSeconds: in= f.=0D + NULL // ProcedureArgument=0D + );=0D + if (EFI_ERROR (Status) && Status !=3D EFI_NOT_STARTED) {=0D + DEBUG ((DEBUG_ERROR, "%a: StartupAllAps(): %r\n", __FUNCTION__, Status= ));=0D + return Status;=0D + }=0D +=0D + //=0D + // Now clear cache on the BSP too.=0D + //=0D + ClearCache (NULL);=0D + return EFI_SUCCESS;=0D +}=0D +=0D +//=0D +// Notification object for registering the callback, for when=0D +// EFI_PEI_MP_SERVICES_PPI becomes available.=0D +//=0D +STATIC CONST EFI_PEI_NOTIFY_DESCRIPTOR mMpServicesNotify =3D {=0D + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | // Flags=0D + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,=0D + &gEfiPeiMpServicesPpiGuid, // Guid=0D + ClearCacheOnMpServicesAvailable // Notify=0D +};=0D +=0D +VOID=0D +InstallClearCacheCallback (=0D + VOID=0D + )=0D +{=0D + EFI_STATUS Status;=0D +=0D + Status =3D PeiServicesNotifyPpi (&mMpServicesNotify);=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((DEBUG_ERROR, "%a: failed to set up MP Services callback: %r\n"= ,=0D + __FUNCTION__, Status));=0D + }=0D +}=0D diff --git a/OvmfPkg/XenPlatformPei/Cmos.c b/OvmfPkg/XenPlatformPei/Cmos.c new file mode 100644 index 0000000000..5d9ee67cd8 --- /dev/null +++ b/OvmfPkg/XenPlatformPei/Cmos.c @@ -0,0 +1,60 @@ +/** @file=0D + PC/AT CMOS access routines=0D +=0D + Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
=0D + Copyright (c) 2019, Citrix Systems, Inc.=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +=0D +#include "Cmos.h"=0D +#include "Library/IoLib.h"=0D +=0D +/**=0D + Reads 8-bits of CMOS data.=0D +=0D + Reads the 8-bits of CMOS data at the location specified by Index.=0D + The 8-bit read value is returned.=0D +=0D + @param Index The CMOS location to read.=0D +=0D + @return The value read.=0D +=0D +**/=0D +UINT8=0D +EFIAPI=0D +CmosRead8 (=0D + IN UINTN Index=0D + )=0D +{=0D + IoWrite8 (0x70, (UINT8) Index);=0D + return IoRead8 (0x71);=0D +}=0D +=0D +=0D +/**=0D + Writes 8-bits of CMOS data.=0D +=0D + Writes 8-bits of CMOS data to the location specified by Index=0D + with the value specified by Value and returns Value.=0D +=0D + @param Index The CMOS location to write.=0D + @param Value The value to write to CMOS.=0D +=0D + @return The value written to CMOS.=0D +=0D +**/=0D +UINT8=0D +EFIAPI=0D +CmosWrite8 (=0D + IN UINTN Index,=0D + IN UINT8 Value=0D + )=0D +{=0D + IoWrite8 (0x70, (UINT8) Index);=0D + IoWrite8 (0x71, Value);=0D + return Value;=0D +}=0D +=0D diff --git a/OvmfPkg/XenPlatformPei/Fv.c b/OvmfPkg/XenPlatformPei/Fv.c new file mode 100644 index 0000000000..fac1ffc9fd --- /dev/null +++ b/OvmfPkg/XenPlatformPei/Fv.c @@ -0,0 +1,76 @@ +/** @file=0D + Build FV related hobs for platform.=0D +=0D + Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
=0D + Copyright (c) 2019, Citrix Systems, Inc.=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include "PiPei.h"=0D +#include "Platform.h"=0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +=0D +/**=0D + Publish PEI & DXE (Decompressed) Memory based FVs to let PEI=0D + and DXE know about them.=0D +=0D + @retval EFI_SUCCESS Platform PEI FVs were initialized successfully.=0D +=0D +**/=0D +EFI_STATUS=0D +PeiFvInitialization (=0D + VOID=0D + )=0D +{=0D + DEBUG ((EFI_D_INFO, "Platform PEI Firmware Volume Initialization\n"));=0D +=0D + //=0D + // Create a memory allocation HOB for the PEI FV.=0D + //=0D + // Allocate as ACPI NVS is S3 is supported=0D + //=0D + BuildMemoryAllocationHob (=0D + PcdGet32 (PcdOvmfPeiMemFvBase),=0D + PcdGet32 (PcdOvmfPeiMemFvSize),=0D + EfiBootServicesData=0D + );=0D +=0D + //=0D + // Let DXE know about the DXE FV=0D + //=0D + BuildFvHob (PcdGet32 (PcdOvmfDxeMemFvBase), PcdGet32 (PcdOvmfDxeMemFvSiz= e));=0D +=0D + //=0D + // Create a memory allocation HOB for the DXE FV.=0D + //=0D + // If "secure" S3 is needed, then SEC will decompress both PEI and DXE=0D + // firmware volumes at S3 resume too, hence we need to keep away the OS = from=0D + // DXEFV as well. Otherwise we only need to keep away DXE itself from th= e=0D + // DXEFV area.=0D + //=0D + BuildMemoryAllocationHob (=0D + PcdGet32 (PcdOvmfDxeMemFvBase),=0D + PcdGet32 (PcdOvmfDxeMemFvSize),=0D + EfiBootServicesData=0D + );=0D +=0D + //=0D + // Let PEI know about the DXE FV so it can find the DXE Core=0D + //=0D + PeiServicesInstallFvInfoPpi (=0D + NULL,=0D + (VOID *)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase),=0D + PcdGet32 (PcdOvmfDxeMemFvSize),=0D + NULL,=0D + NULL=0D + );=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D diff --git a/OvmfPkg/XenPlatformPei/MemDetect.c b/OvmfPkg/XenPlatformPei/Me= mDetect.c new file mode 100644 index 0000000000..cb7dd93ad6 --- /dev/null +++ b/OvmfPkg/XenPlatformPei/MemDetect.c @@ -0,0 +1,421 @@ +/**@file=0D + Memory Detection for Virtual Machines.=0D +=0D + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
=0D + Copyright (c) 2019, Citrix Systems, Inc.=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=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 +=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 +=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 +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 ((EFI_D_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 ((EFI_D_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 +=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 ((EFI_D_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 + MemoryBase =3D=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 + Publish system RAM and reserve memory regions=0D +=0D +**/=0D +VOID=0D +InitializeRamRegions (=0D + VOID=0D + )=0D +{=0D + XenPublishRamRegions ();=0D +=0D + if (mBootMode !=3D BOOT_ON_S3_RESUME) {=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 the= =0D + // LockBox area. We ought to prevent DXE from serving allocation reque= sts=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 + EfiBootServicesData=0D + );=0D + }=0D +}=0D diff --git a/OvmfPkg/XenPlatformPei/Platform.c b/OvmfPkg/XenPlatformPei/Pla= tform.c new file mode 100644 index 0000000000..c97a2fb6c1 --- /dev/null +++ b/OvmfPkg/XenPlatformPei/Platform.c @@ -0,0 +1,444 @@ +/**@file=0D + Platform PEI driver=0D +=0D + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
=0D + Copyright (c) 2011, Andrei Warkentin =0D + Copyright (c) 2019, Citrix Systems, Inc.=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=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 +=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 +=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 + //=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 +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 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 ((EFI_D_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 ((EFI_D_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 ((EFI_D_INFO, "CMOS:\n"));=0D +=0D + for (Loop =3D 0; Loop < 0x80; Loop++) {=0D + if ((Loop % 0x10) =3D=3D 0) {=0D + DEBUG ((EFI_D_INFO, "%02x:", Loop));=0D + }=0D + DEBUG ((EFI_D_INFO, " %02x", CmosRead8 (Loop)));=0D + if ((Loop % 0x10) =3D=3D 0xf) {=0D + DEBUG ((EFI_D_INFO, "\n"));=0D + }=0D + }=0D +}=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 +InitializeXenPlatform (=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 + DebugDumpCmos ();=0D +=0D + if (!XenDetect ()) {=0D + DEBUG ((DEBUG_ERROR, "ERROR: Xen isn't detected\n"));=0D + ASSERT (FALSE);=0D + CpuDeadLoop ();=0D + }=0D +=0D + BootModeInitialization ();=0D + AddressWidthInitialization ();=0D +=0D + //=0D + // Query Host Bridge DID=0D + //=0D + mHostBridgeDevId =3D PciRead16 (OVMF_HOSTBRIDGE_DID);=0D +=0D + PublishPeiMemory ();=0D +=0D + InitializeRamRegions ();=0D +=0D + InitializeXen ();=0D +=0D + if (mBootMode !=3D BOOT_ON_S3_RESUME) {=0D + ReserveEmuVariableNvStore ();=0D + PeiFvInitialization ();=0D + MemMapInitialization ();=0D + }=0D +=0D + InstallClearCacheCallback ();=0D + AmdSevInitialize ();=0D + MiscInitialization ();=0D +=0D + return EFI_SUCCESS;=0D +}=0D diff --git a/OvmfPkg/XenPlatformPei/Xen.c b/OvmfPkg/XenPlatformPei/Xen.c new file mode 100644 index 0000000000..81042ab94f --- /dev/null +++ b/OvmfPkg/XenPlatformPei/Xen.c @@ -0,0 +1,219 @@ +/**@file=0D + Xen Platform PEI support=0D +=0D + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
=0D + Copyright (c) 2011, Andrei Warkentin =0D + Copyright (c) 2019, Citrix Systems, Inc.=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=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 +=0D +#include "Platform.h"=0D +#include "Xen.h"=0D +=0D +STATIC UINT32 mXenLeaf =3D 0;=0D +=0D +EFI_XEN_INFO mXenInfo;=0D +=0D +/**=0D + Returns E820 map provided by Xen=0D +=0D + @param Entries Pointer to E820 map=0D + @param Count Number of entries=0D +=0D + @return EFI_STATUS=0D +**/=0D +EFI_STATUS=0D +XenGetE820Map (=0D + EFI_E820_ENTRY64 **Entries,=0D + UINT32 *Count=0D + )=0D +{=0D + EFI_XEN_OVMF_INFO *Info =3D=0D + (EFI_XEN_OVMF_INFO *)(UINTN) OVMF_INFO_PHYSICAL_ADDRESS;=0D +=0D + if (AsciiStrCmp ((CHAR8 *) Info->Signature, "XenHVMOVMF")) {=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + ASSERT (Info->E820 < MAX_ADDRESS);=0D + *Entries =3D (EFI_E820_ENTRY64 *)(UINTN) Info->E820;=0D + *Count =3D Info->E820EntriesCount;=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Connects to the Hypervisor.=0D + =0D + @param XenLeaf CPUID index used to connect.=0D +=0D + @return EFI_STATUS=0D +=0D +**/=0D +EFI_STATUS=0D +XenConnect (=0D + UINT32 XenLeaf=0D + )=0D +{=0D + UINT32 Index;=0D + UINT32 TransferReg;=0D + UINT32 TransferPages;=0D + UINT32 XenVersion;=0D +=0D + AsmCpuid (XenLeaf + 2, &TransferPages, &TransferReg, NULL, NULL);=0D + mXenInfo.HyperPages =3D AllocatePages (TransferPages);=0D + if (!mXenInfo.HyperPages) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D + for (Index =3D 0; Index < TransferPages; Index++) {=0D + AsmWriteMsr64 (TransferReg,=0D + (UINTN) mXenInfo.HyperPages +=0D + (Index << EFI_PAGE_SHIFT) + Index);=0D + }=0D +=0D + AsmCpuid (XenLeaf + 1, &XenVersion, NULL, NULL, NULL);=0D + DEBUG ((EFI_D_ERROR, "Detected Xen version %d.%d\n",=0D + XenVersion >> 16, XenVersion & 0xFFFF));=0D + mXenInfo.VersionMajor =3D (UINT16)(XenVersion >> 16);=0D + mXenInfo.VersionMinor =3D (UINT16)(XenVersion & 0xFFFF);=0D +=0D + /* TBD: Locate hvm_info and reserve it away. */=0D + mXenInfo.HvmInfo =3D NULL;=0D +=0D + BuildGuidDataHob (=0D + &gEfiXenInfoGuid,=0D + &mXenInfo,=0D + sizeof(mXenInfo)=0D + );=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Figures out if we are running inside Xen HVM.=0D +=0D + @retval TRUE Xen was detected=0D + @retval FALSE Xen was not detected=0D +=0D +**/=0D +BOOLEAN=0D +XenDetect (=0D + VOID=0D + )=0D +{=0D + UINT8 Signature[13];=0D +=0D + if (mXenLeaf !=3D 0) {=0D + return TRUE;=0D + }=0D +=0D + Signature[12] =3D '\0';=0D + for (mXenLeaf =3D 0x40000000; mXenLeaf < 0x40010000; mXenLeaf +=3D 0x100= ) {=0D + AsmCpuid (mXenLeaf,=0D + NULL,=0D + (UINT32 *) &Signature[0],=0D + (UINT32 *) &Signature[4],=0D + (UINT32 *) &Signature[8]);=0D +=0D + if (!AsciiStrCmp ((CHAR8 *) Signature, "XenVMMXenVMM")) {=0D + return TRUE;=0D + }=0D + }=0D +=0D + mXenLeaf =3D 0;=0D + return FALSE;=0D +}=0D +=0D +=0D +VOID=0D +XenPublishRamRegions (=0D + VOID=0D + )=0D +{=0D + EFI_E820_ENTRY64 *E820Map;=0D + UINT32 E820EntriesCount;=0D + EFI_STATUS Status;=0D +=0D + DEBUG ((EFI_D_INFO, "Using memory map provided by Xen\n"));=0D +=0D + //=0D + // Parse RAM in E820 map=0D + //=0D + E820EntriesCount =3D 0;=0D + Status =3D XenGetE820Map (&E820Map, &E820EntriesCount);=0D +=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + if (E820EntriesCount > 0) {=0D + EFI_E820_ENTRY64 *Entry;=0D + UINT32 Loop;=0D +=0D + for (Loop =3D 0; Loop < E820EntriesCount; Loop++) {=0D + Entry =3D E820Map + Loop;=0D +=0D + //=0D + // Only care about RAM=0D + //=0D + if (Entry->Type !=3D EfiAcpiAddressRangeMemory) {=0D + continue;=0D + }=0D +=0D + AddMemoryBaseSizeHob (Entry->BaseAddr, Entry->Length);=0D +=0D + MtrrSetMemoryAttribute (Entry->BaseAddr, Entry->Length, CacheWriteBa= ck);=0D + }=0D + }=0D +}=0D +=0D +=0D +/**=0D + Perform Xen PEI initialization.=0D +=0D + @return EFI_SUCCESS Xen initialized successfully=0D + @return EFI_NOT_FOUND Not running under Xen=0D +=0D +**/=0D +EFI_STATUS=0D +InitializeXen (=0D + VOID=0D + )=0D +{=0D + RETURN_STATUS PcdStatus;=0D +=0D + if (mXenLeaf =3D=3D 0) {=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + XenConnect (mXenLeaf);=0D +=0D + //=0D + // Reserve away HVMLOADER reserved memory [0xFC000000,0xFD000000).=0D + // This needs to match HVMLOADER RESERVED_MEMBASE/RESERVED_MEMSIZE.=0D + //=0D + AddReservedMemoryBaseSizeHob (0xFC000000, 0x1000000, FALSE);=0D +=0D + PcdStatus =3D PcdSetBoolS (PcdPciDisableBusEnumeration, TRUE);=0D + ASSERT_RETURN_ERROR (PcdStatus);=0D +=0D + return EFI_SUCCESS;=0D +}=0D --=20 Anthony PERARD