1/**@file 2 Xen Platform PEI support 3 4 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR> 5 Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com> 6 7 This program and the accompanying materials 8 are licensed and made available under the terms and conditions of the BSD License 9 which accompanies this distribution. The full text of the license may be found at 10 http://opensource.org/licenses/bsd-license.php 11 12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 14 15**/ 16 17// 18// The package level header files this module uses 19// 20#include <PiPei.h> 21 22// 23// The Library classes this module consumes 24// 25#include <Library/DebugLib.h> 26#include <Library/HobLib.h> 27#include <Library/MemoryAllocationLib.h> 28#include <Library/PcdLib.h> 29#include <Guid/XenInfo.h> 30#include <IndustryStandard/E820.h> 31#include <Library/ResourcePublicationLib.h> 32#include <Library/MtrrLib.h> 33 34#include "Platform.h" 35#include "Xen.h" 36 37BOOLEAN mXen = FALSE; 38 39STATIC UINT32 mXenLeaf = 0; 40 41EFI_XEN_INFO mXenInfo; 42 43/** 44 Returns E820 map provided by Xen 45 46 @param Entries Pointer to E820 map 47 @param Count Number of entries 48 49 @return EFI_STATUS 50**/ 51EFI_STATUS 52XenGetE820Map ( 53 EFI_E820_ENTRY64 **Entries, 54 UINT32 *Count 55 ) 56{ 57 EFI_XEN_OVMF_INFO *Info = 58 (EFI_XEN_OVMF_INFO *)(UINTN) OVMF_INFO_PHYSICAL_ADDRESS; 59 60 if (AsciiStrCmp ((CHAR8 *) Info->Signature, "XenHVMOVMF")) { 61 return EFI_NOT_FOUND; 62 } 63 64 ASSERT (Info->E820 < MAX_ADDRESS); 65 *Entries = (EFI_E820_ENTRY64 *)(UINTN) Info->E820; 66 *Count = Info->E820EntriesCount; 67 68 return EFI_SUCCESS; 69} 70 71/** 72 Connects to the Hypervisor. 73 74 @param XenLeaf CPUID index used to connect. 75 76 @return EFI_STATUS 77 78**/ 79EFI_STATUS 80XenConnect ( 81 UINT32 XenLeaf 82 ) 83{ 84 UINT32 Index; 85 UINT32 TransferReg; 86 UINT32 TransferPages; 87 UINT32 XenVersion; 88 89 AsmCpuid (XenLeaf + 2, &TransferPages, &TransferReg, NULL, NULL); 90 mXenInfo.HyperPages = AllocatePages (TransferPages); 91 if (!mXenInfo.HyperPages) { 92 return EFI_OUT_OF_RESOURCES; 93 } 94 95 for (Index = 0; Index < TransferPages; Index++) { 96 AsmWriteMsr64 (TransferReg, 97 (UINTN) mXenInfo.HyperPages + 98 (Index << EFI_PAGE_SHIFT) + Index); 99 } 100 101 AsmCpuid (XenLeaf + 1, &XenVersion, NULL, NULL, NULL); 102 DEBUG ((EFI_D_ERROR, "Detected Xen version %d.%d\n", 103 XenVersion >> 16, XenVersion & 0xFFFF)); 104 mXenInfo.VersionMajor = (UINT16)(XenVersion >> 16); 105 mXenInfo.VersionMinor = (UINT16)(XenVersion & 0xFFFF); 106 107 /* TBD: Locate hvm_info and reserve it away. */ 108 mXenInfo.HvmInfo = NULL; 109 110 BuildGuidDataHob ( 111 &gEfiXenInfoGuid, 112 &mXenInfo, 113 sizeof(mXenInfo) 114 ); 115 116 return EFI_SUCCESS; 117} 118 119/** 120 Figures out if we are running inside Xen HVM. 121 122 @retval TRUE Xen was detected 123 @retval FALSE Xen was not detected 124 125**/ 126BOOLEAN 127XenDetect ( 128 VOID 129 ) 130{ 131 UINT8 Signature[13]; 132 133 if (mXenLeaf != 0) { 134 return TRUE; 135 } 136 137 Signature[12] = '\0'; 138 for (mXenLeaf = 0x40000000; mXenLeaf < 0x40010000; mXenLeaf += 0x100) { 139 AsmCpuid (mXenLeaf, 140 NULL, 141 (UINT32 *) &Signature[0], 142 (UINT32 *) &Signature[4], 143 (UINT32 *) &Signature[8]); 144 145 if (!AsciiStrCmp ((CHAR8 *) Signature, "XenVMMXenVMM")) { 146 mXen = TRUE; 147 return TRUE; 148 } 149 } 150 151 mXenLeaf = 0; 152 return FALSE; 153} 154 155 156VOID 157XenPublishRamRegions ( 158 VOID 159 ) 160{ 161 EFI_E820_ENTRY64 *E820Map; 162 UINT32 E820EntriesCount; 163 EFI_STATUS Status; 164 165 if (!mXen) { 166 return; 167 } 168 169 DEBUG ((EFI_D_INFO, "Using memory map provided by Xen\n")); 170 171 // 172 // Parse RAM in E820 map 173 // 174 Status = XenGetE820Map (&E820Map, &E820EntriesCount); 175 176 ASSERT_EFI_ERROR (Status); 177 178 if (E820EntriesCount > 0) { 179 EFI_E820_ENTRY64 *Entry; 180 UINT32 Loop; 181 182 for (Loop = 0; Loop < E820EntriesCount; Loop++) { 183 Entry = E820Map + Loop; 184 185 // 186 // Only care about RAM 187 // 188 if (Entry->Type != EfiAcpiAddressRangeMemory) { 189 continue; 190 } 191 192 if (Entry->BaseAddr >= BASE_4GB) { 193 AddUntestedMemoryBaseSizeHob (Entry->BaseAddr, Entry->Length); 194 } else { 195 AddMemoryBaseSizeHob (Entry->BaseAddr, Entry->Length); 196 } 197 198 MtrrSetMemoryAttribute (Entry->BaseAddr, Entry->Length, CacheWriteBack); 199 } 200 } 201} 202 203 204/** 205 Perform Xen PEI initialization. 206 207 @return EFI_SUCCESS Xen initialized successfully 208 @return EFI_NOT_FOUND Not running under Xen 209 210**/ 211EFI_STATUS 212InitializeXen ( 213 VOID 214 ) 215{ 216 if (mXenLeaf == 0) { 217 return EFI_NOT_FOUND; 218 } 219 220 XenConnect (mXenLeaf); 221 222 // 223 // Reserve away HVMLOADER reserved memory [0xFC000000,0xFD000000). 224 // This needs to match HVMLOADER RESERVED_MEMBASE/RESERVED_MEMSIZE. 225 // 226 AddReservedMemoryBaseSizeHob (0xFC000000, 0x1000000, FALSE); 227 228 PcdSetBool (PcdPciDisableBusEnumeration, TRUE); 229 230 return EFI_SUCCESS; 231} 232