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 (at) 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 37 BOOLEAN mXen = FALSE; 38 39 STATIC UINT32 mXenLeaf = 0; 40 41 EFI_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 **/ 51 EFI_STATUS 52 XenGetE820Map ( 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 **/ 79 EFI_STATUS 80 XenConnect ( 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 **/ 126 BOOLEAN 127 XenDetect ( 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 156 VOID 157 XenPublishRamRegions ( 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 **/ 211 EFI_STATUS 212 InitializeXen ( 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