]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/XenPlatformPei/Xen.c
OvmfPkg/XenHypercallLib: Enable it in PEIM
[mirror_edk2.git] / OvmfPkg / XenPlatformPei / Xen.c
CommitLineData
3b96221f
AP
1/**@file\r
2 Xen Platform PEI support\r
3\r
4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
5 Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>\r
6 Copyright (c) 2019, Citrix Systems, Inc.\r
7\r
8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
9\r
10**/\r
11\r
12//\r
13// The package level header files this module uses\r
14//\r
15#include <PiPei.h>\r
16\r
17//\r
18// The Library classes this module consumes\r
19//\r
20#include <Library/DebugLib.h>\r
21#include <Library/HobLib.h>\r
22#include <Library/MemoryAllocationLib.h>\r
23#include <Library/PcdLib.h>\r
24#include <Guid/XenInfo.h>\r
25#include <IndustryStandard/E820.h>\r
26#include <Library/ResourcePublicationLib.h>\r
27#include <Library/MtrrLib.h>\r
60d26545 28#include <IndustryStandard/Xen/arch-x86/hvm/start_info.h>\r
3b96221f
AP
29\r
30#include "Platform.h"\r
31#include "Xen.h"\r
32\r
33STATIC UINT32 mXenLeaf = 0;\r
34\r
35EFI_XEN_INFO mXenInfo;\r
36\r
8651e1ce
AP
37//\r
38// Location of the firmware info struct setup by hvmloader.\r
39// Only the E820 table is used by OVMF.\r
40//\r
41EFI_XEN_OVMF_INFO *mXenHvmloaderInfo;\r
42\r
3b96221f
AP
43/**\r
44 Returns E820 map provided by Xen\r
45\r
46 @param Entries Pointer to E820 map\r
47 @param Count Number of entries\r
48\r
49 @return EFI_STATUS\r
50**/\r
51EFI_STATUS\r
52XenGetE820Map (\r
53 EFI_E820_ENTRY64 **Entries,\r
54 UINT32 *Count\r
55 )\r
56{\r
594b5002
AP
57 //\r
58 // Get E820 produced by hvmloader\r
59 //\r
60 if (mXenHvmloaderInfo != NULL) {\r
61 ASSERT (mXenHvmloaderInfo->E820 < MAX_ADDRESS);\r
62 *Entries = (EFI_E820_ENTRY64 *)(UINTN) mXenHvmloaderInfo->E820;\r
63 *Count = mXenHvmloaderInfo->E820EntriesCount;\r
64\r
65 return EFI_SUCCESS;\r
3b96221f
AP
66 }\r
67\r
594b5002 68 return EFI_NOT_FOUND;\r
3b96221f
AP
69}\r
70\r
71/**\r
72 Connects to the Hypervisor.\r
73\r
74 @param XenLeaf CPUID index used to connect.\r
75\r
76 @return EFI_STATUS\r
77\r
78**/\r
79EFI_STATUS\r
80XenConnect (\r
81 UINT32 XenLeaf\r
82 )\r
83{\r
84 UINT32 Index;\r
85 UINT32 TransferReg;\r
86 UINT32 TransferPages;\r
87 UINT32 XenVersion;\r
8651e1ce
AP
88 EFI_XEN_OVMF_INFO *Info;\r
89 CHAR8 Sig[sizeof (Info->Signature) + 1];\r
60d26545 90 UINT32 *PVHResetVectorData;\r
3b96221f
AP
91\r
92 AsmCpuid (XenLeaf + 2, &TransferPages, &TransferReg, NULL, NULL);\r
93 mXenInfo.HyperPages = AllocatePages (TransferPages);\r
94 if (!mXenInfo.HyperPages) {\r
95 return EFI_OUT_OF_RESOURCES;\r
96 }\r
97\r
98 for (Index = 0; Index < TransferPages; Index++) {\r
99 AsmWriteMsr64 (TransferReg,\r
100 (UINTN) mXenInfo.HyperPages +\r
101 (Index << EFI_PAGE_SHIFT) + Index);\r
102 }\r
103\r
104 AsmCpuid (XenLeaf + 1, &XenVersion, NULL, NULL, NULL);\r
105 DEBUG ((DEBUG_ERROR, "Detected Xen version %d.%d\n",\r
106 XenVersion >> 16, XenVersion & 0xFFFF));\r
107 mXenInfo.VersionMajor = (UINT16)(XenVersion >> 16);\r
108 mXenInfo.VersionMinor = (UINT16)(XenVersion & 0xFFFF);\r
109\r
8651e1ce
AP
110 //\r
111 // Check if there are information left by hvmloader\r
112 //\r
113\r
114 Info = (EFI_XEN_OVMF_INFO *)(UINTN) OVMF_INFO_PHYSICAL_ADDRESS;\r
115 //\r
116 // Copy the signature, and make it null-terminated.\r
117 //\r
118 AsciiStrnCpyS (Sig, sizeof (Sig), (CHAR8 *) &Info->Signature,\r
119 sizeof (Info->Signature));\r
120 if (AsciiStrCmp (Sig, "XenHVMOVMF") == 0) {\r
121 mXenHvmloaderInfo = Info;\r
122 } else {\r
123 mXenHvmloaderInfo = NULL;\r
124 }\r
3b96221f 125\r
60d26545
AP
126 mXenInfo.RsdpPvh = NULL;\r
127\r
128 //\r
129 // Locate and use information from the start of day structure if we have\r
130 // booted via the PVH entry point.\r
131 //\r
132\r
133 PVHResetVectorData = (VOID *)(UINTN) PcdGet32 (PcdXenPvhStartOfDayStructPtr);\r
134 //\r
135 // That magic value is written in XenResetVector/Ia32/XenPVHMain.asm\r
136 //\r
137 if (PVHResetVectorData[1] == SIGNATURE_32 ('X', 'P', 'V', 'H')) {\r
138 struct hvm_start_info *HVMStartInfo;\r
139\r
140 HVMStartInfo = (VOID *)(UINTN) PVHResetVectorData[0];\r
141 if (HVMStartInfo->magic == XEN_HVM_START_MAGIC_VALUE) {\r
142 ASSERT (HVMStartInfo->rsdp_paddr != 0);\r
143 if (HVMStartInfo->rsdp_paddr != 0) {\r
144 mXenInfo.RsdpPvh = (VOID *)(UINTN)HVMStartInfo->rsdp_paddr;\r
145 }\r
146 }\r
147 }\r
148\r
3b96221f
AP
149 BuildGuidDataHob (\r
150 &gEfiXenInfoGuid,\r
151 &mXenInfo,\r
152 sizeof(mXenInfo)\r
153 );\r
154\r
155 return EFI_SUCCESS;\r
156}\r
157\r
158/**\r
159 Figures out if we are running inside Xen HVM.\r
160\r
161 @retval TRUE Xen was detected\r
162 @retval FALSE Xen was not detected\r
163\r
164**/\r
165BOOLEAN\r
166XenDetect (\r
167 VOID\r
168 )\r
169{\r
170 UINT8 Signature[13];\r
171\r
172 if (mXenLeaf != 0) {\r
173 return TRUE;\r
174 }\r
175\r
176 Signature[12] = '\0';\r
177 for (mXenLeaf = 0x40000000; mXenLeaf < 0x40010000; mXenLeaf += 0x100) {\r
178 AsmCpuid (mXenLeaf,\r
179 NULL,\r
180 (UINT32 *) &Signature[0],\r
181 (UINT32 *) &Signature[4],\r
182 (UINT32 *) &Signature[8]);\r
183\r
184 if (!AsciiStrCmp ((CHAR8 *) Signature, "XenVMMXenVMM")) {\r
185 return TRUE;\r
186 }\r
187 }\r
188\r
189 mXenLeaf = 0;\r
190 return FALSE;\r
191}\r
192\r
193\r
194VOID\r
195XenPublishRamRegions (\r
196 VOID\r
197 )\r
198{\r
199 EFI_E820_ENTRY64 *E820Map;\r
200 UINT32 E820EntriesCount;\r
201 EFI_STATUS Status;\r
202\r
203 DEBUG ((DEBUG_INFO, "Using memory map provided by Xen\n"));\r
204\r
205 //\r
206 // Parse RAM in E820 map\r
207 //\r
208 E820EntriesCount = 0;\r
209 Status = XenGetE820Map (&E820Map, &E820EntriesCount);\r
210\r
211 ASSERT_EFI_ERROR (Status);\r
212\r
213 if (E820EntriesCount > 0) {\r
214 EFI_E820_ENTRY64 *Entry;\r
215 UINT32 Loop;\r
216\r
217 for (Loop = 0; Loop < E820EntriesCount; Loop++) {\r
218 Entry = E820Map + Loop;\r
219\r
220 //\r
221 // Only care about RAM\r
222 //\r
223 if (Entry->Type != EfiAcpiAddressRangeMemory) {\r
224 continue;\r
225 }\r
226\r
227 AddMemoryBaseSizeHob (Entry->BaseAddr, Entry->Length);\r
228\r
229 MtrrSetMemoryAttribute (Entry->BaseAddr, Entry->Length, CacheWriteBack);\r
230 }\r
231 }\r
232}\r
233\r
234\r
235/**\r
236 Perform Xen PEI initialization.\r
237\r
238 @return EFI_SUCCESS Xen initialized successfully\r
239 @return EFI_NOT_FOUND Not running under Xen\r
240\r
241**/\r
242EFI_STATUS\r
243InitializeXen (\r
244 VOID\r
245 )\r
246{\r
247 RETURN_STATUS PcdStatus;\r
248\r
249 if (mXenLeaf == 0) {\r
250 return EFI_NOT_FOUND;\r
251 }\r
252\r
253 XenConnect (mXenLeaf);\r
254\r
255 //\r
256 // Reserve away HVMLOADER reserved memory [0xFC000000,0xFD000000).\r
257 // This needs to match HVMLOADER RESERVED_MEMBASE/RESERVED_MEMSIZE.\r
258 //\r
259 AddReservedMemoryBaseSizeHob (0xFC000000, 0x1000000, FALSE);\r
260\r
261 PcdStatus = PcdSetBoolS (PcdPciDisableBusEnumeration, TRUE);\r
262 ASSERT_RETURN_ERROR (PcdStatus);\r
263\r
264 return EFI_SUCCESS;\r
265}\r