2 Xen Platform PEI support
4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>
6 Copyright (c) 2019, Citrix Systems, Inc.
8 SPDX-License-Identifier: BSD-2-Clause-Patent
13 // The package level header files this module uses
18 // The Library classes this module consumes
20 #include <Library/DebugLib.h>
21 #include <Library/HobLib.h>
22 #include <Library/MemoryAllocationLib.h>
23 #include <Library/PcdLib.h>
24 #include <Guid/XenInfo.h>
25 #include <IndustryStandard/E820.h>
26 #include <Library/ResourcePublicationLib.h>
27 #include <Library/MtrrLib.h>
32 STATIC UINT32 mXenLeaf
= 0;
34 EFI_XEN_INFO mXenInfo
;
37 // Location of the firmware info struct setup by hvmloader.
38 // Only the E820 table is used by OVMF.
40 EFI_XEN_OVMF_INFO
*mXenHvmloaderInfo
;
43 Returns E820 map provided by Xen
45 @param Entries Pointer to E820 map
46 @param Count Number of entries
52 EFI_E820_ENTRY64
**Entries
,
56 EFI_XEN_OVMF_INFO
*Info
=
57 (EFI_XEN_OVMF_INFO
*)(UINTN
) OVMF_INFO_PHYSICAL_ADDRESS
;
59 if (AsciiStrCmp ((CHAR8
*) Info
->Signature
, "XenHVMOVMF")) {
63 ASSERT (Info
->E820
< MAX_ADDRESS
);
64 *Entries
= (EFI_E820_ENTRY64
*)(UINTN
) Info
->E820
;
65 *Count
= Info
->E820EntriesCount
;
71 Connects to the Hypervisor.
73 @param XenLeaf CPUID index used to connect.
87 EFI_XEN_OVMF_INFO
*Info
;
88 CHAR8 Sig
[sizeof (Info
->Signature
) + 1];
90 AsmCpuid (XenLeaf
+ 2, &TransferPages
, &TransferReg
, NULL
, NULL
);
91 mXenInfo
.HyperPages
= AllocatePages (TransferPages
);
92 if (!mXenInfo
.HyperPages
) {
93 return EFI_OUT_OF_RESOURCES
;
96 for (Index
= 0; Index
< TransferPages
; Index
++) {
97 AsmWriteMsr64 (TransferReg
,
98 (UINTN
) mXenInfo
.HyperPages
+
99 (Index
<< EFI_PAGE_SHIFT
) + Index
);
102 AsmCpuid (XenLeaf
+ 1, &XenVersion
, NULL
, NULL
, NULL
);
103 DEBUG ((DEBUG_ERROR
, "Detected Xen version %d.%d\n",
104 XenVersion
>> 16, XenVersion
& 0xFFFF));
105 mXenInfo
.VersionMajor
= (UINT16
)(XenVersion
>> 16);
106 mXenInfo
.VersionMinor
= (UINT16
)(XenVersion
& 0xFFFF);
109 // Check if there are information left by hvmloader
112 Info
= (EFI_XEN_OVMF_INFO
*)(UINTN
) OVMF_INFO_PHYSICAL_ADDRESS
;
114 // Copy the signature, and make it null-terminated.
116 AsciiStrnCpyS (Sig
, sizeof (Sig
), (CHAR8
*) &Info
->Signature
,
117 sizeof (Info
->Signature
));
118 if (AsciiStrCmp (Sig
, "XenHVMOVMF") == 0) {
119 mXenHvmloaderInfo
= Info
;
121 mXenHvmloaderInfo
= NULL
;
134 Figures out if we are running inside Xen HVM.
136 @retval TRUE Xen was detected
137 @retval FALSE Xen was not detected
151 Signature
[12] = '\0';
152 for (mXenLeaf
= 0x40000000; mXenLeaf
< 0x40010000; mXenLeaf
+= 0x100) {
155 (UINT32
*) &Signature
[0],
156 (UINT32
*) &Signature
[4],
157 (UINT32
*) &Signature
[8]);
159 if (!AsciiStrCmp ((CHAR8
*) Signature
, "XenVMMXenVMM")) {
170 XenPublishRamRegions (
174 EFI_E820_ENTRY64
*E820Map
;
175 UINT32 E820EntriesCount
;
178 DEBUG ((DEBUG_INFO
, "Using memory map provided by Xen\n"));
181 // Parse RAM in E820 map
183 E820EntriesCount
= 0;
184 Status
= XenGetE820Map (&E820Map
, &E820EntriesCount
);
186 ASSERT_EFI_ERROR (Status
);
188 if (E820EntriesCount
> 0) {
189 EFI_E820_ENTRY64
*Entry
;
192 for (Loop
= 0; Loop
< E820EntriesCount
; Loop
++) {
193 Entry
= E820Map
+ Loop
;
196 // Only care about RAM
198 if (Entry
->Type
!= EfiAcpiAddressRangeMemory
) {
202 AddMemoryBaseSizeHob (Entry
->BaseAddr
, Entry
->Length
);
204 MtrrSetMemoryAttribute (Entry
->BaseAddr
, Entry
->Length
, CacheWriteBack
);
211 Perform Xen PEI initialization.
213 @return EFI_SUCCESS Xen initialized successfully
214 @return EFI_NOT_FOUND Not running under Xen
222 RETURN_STATUS PcdStatus
;
225 return EFI_NOT_FOUND
;
228 XenConnect (mXenLeaf
);
231 // Reserve away HVMLOADER reserved memory [0xFC000000,0xFD000000).
232 // This needs to match HVMLOADER RESERVED_MEMBASE/RESERVED_MEMSIZE.
234 AddReservedMemoryBaseSizeHob (0xFC000000, 0x1000000, FALSE
);
236 PcdStatus
= PcdSetBoolS (PcdPciDisableBusEnumeration
, TRUE
);
237 ASSERT_RETURN_ERROR (PcdStatus
);