]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/XenPlatformPei/Xen.c
OvmfPkg: Import XENMEM_memory_map hypercall to Xen/memory.h
[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
80b619d5 29#include <Library/XenHypercallLib.h>\r
3b96221f
AP
30\r
31#include "Platform.h"\r
32#include "Xen.h"\r
33\r
34STATIC UINT32 mXenLeaf = 0;\r
35\r
36EFI_XEN_INFO mXenInfo;\r
37\r
8651e1ce
AP
38//\r
39// Location of the firmware info struct setup by hvmloader.\r
40// Only the E820 table is used by OVMF.\r
41//\r
42EFI_XEN_OVMF_INFO *mXenHvmloaderInfo;\r
43\r
3b96221f
AP
44/**\r
45 Returns E820 map provided by Xen\r
46\r
47 @param Entries Pointer to E820 map\r
48 @param Count Number of entries\r
49\r
50 @return EFI_STATUS\r
51**/\r
52EFI_STATUS\r
53XenGetE820Map (\r
54 EFI_E820_ENTRY64 **Entries,\r
55 UINT32 *Count\r
56 )\r
57{\r
594b5002
AP
58 //\r
59 // Get E820 produced by hvmloader\r
60 //\r
61 if (mXenHvmloaderInfo != NULL) {\r
62 ASSERT (mXenHvmloaderInfo->E820 < MAX_ADDRESS);\r
63 *Entries = (EFI_E820_ENTRY64 *)(UINTN) mXenHvmloaderInfo->E820;\r
64 *Count = mXenHvmloaderInfo->E820EntriesCount;\r
65\r
66 return EFI_SUCCESS;\r
3b96221f
AP
67 }\r
68\r
594b5002 69 return EFI_NOT_FOUND;\r
3b96221f
AP
70}\r
71\r
72/**\r
73 Connects to the Hypervisor.\r
74\r
3b96221f
AP
75 @return EFI_STATUS\r
76\r
77**/\r
78EFI_STATUS\r
79XenConnect (\r
3b96221f
AP
80 )\r
81{\r
82 UINT32 Index;\r
83 UINT32 TransferReg;\r
84 UINT32 TransferPages;\r
85 UINT32 XenVersion;\r
8651e1ce
AP
86 EFI_XEN_OVMF_INFO *Info;\r
87 CHAR8 Sig[sizeof (Info->Signature) + 1];\r
60d26545 88 UINT32 *PVHResetVectorData;\r
80b619d5 89 RETURN_STATUS Status;\r
3b96221f 90\r
12998837
AP
91 ASSERT (mXenLeaf != 0);\r
92\r
93 //\r
94 // Prepare HyperPages to be able to make hypercalls\r
95 //\r
96\r
97 AsmCpuid (mXenLeaf + 2, &TransferPages, &TransferReg, NULL, NULL);\r
3b96221f
AP
98 mXenInfo.HyperPages = AllocatePages (TransferPages);\r
99 if (!mXenInfo.HyperPages) {\r
100 return EFI_OUT_OF_RESOURCES;\r
101 }\r
102\r
103 for (Index = 0; Index < TransferPages; Index++) {\r
104 AsmWriteMsr64 (TransferReg,\r
105 (UINTN) mXenInfo.HyperPages +\r
106 (Index << EFI_PAGE_SHIFT) + Index);\r
107 }\r
108\r
12998837
AP
109 //\r
110 // Find out the Xen version\r
111 //\r
112\r
113 AsmCpuid (mXenLeaf + 1, &XenVersion, NULL, NULL, NULL);\r
3b96221f
AP
114 DEBUG ((DEBUG_ERROR, "Detected Xen version %d.%d\n",\r
115 XenVersion >> 16, XenVersion & 0xFFFF));\r
116 mXenInfo.VersionMajor = (UINT16)(XenVersion >> 16);\r
117 mXenInfo.VersionMinor = (UINT16)(XenVersion & 0xFFFF);\r
118\r
8651e1ce
AP
119 //\r
120 // Check if there are information left by hvmloader\r
121 //\r
122\r
123 Info = (EFI_XEN_OVMF_INFO *)(UINTN) OVMF_INFO_PHYSICAL_ADDRESS;\r
124 //\r
125 // Copy the signature, and make it null-terminated.\r
126 //\r
127 AsciiStrnCpyS (Sig, sizeof (Sig), (CHAR8 *) &Info->Signature,\r
128 sizeof (Info->Signature));\r
129 if (AsciiStrCmp (Sig, "XenHVMOVMF") == 0) {\r
130 mXenHvmloaderInfo = Info;\r
131 } else {\r
132 mXenHvmloaderInfo = NULL;\r
133 }\r
3b96221f 134\r
60d26545
AP
135 mXenInfo.RsdpPvh = NULL;\r
136\r
137 //\r
138 // Locate and use information from the start of day structure if we have\r
139 // booted via the PVH entry point.\r
140 //\r
141\r
142 PVHResetVectorData = (VOID *)(UINTN) PcdGet32 (PcdXenPvhStartOfDayStructPtr);\r
143 //\r
144 // That magic value is written in XenResetVector/Ia32/XenPVHMain.asm\r
145 //\r
146 if (PVHResetVectorData[1] == SIGNATURE_32 ('X', 'P', 'V', 'H')) {\r
147 struct hvm_start_info *HVMStartInfo;\r
148\r
149 HVMStartInfo = (VOID *)(UINTN) PVHResetVectorData[0];\r
150 if (HVMStartInfo->magic == XEN_HVM_START_MAGIC_VALUE) {\r
151 ASSERT (HVMStartInfo->rsdp_paddr != 0);\r
152 if (HVMStartInfo->rsdp_paddr != 0) {\r
153 mXenInfo.RsdpPvh = (VOID *)(UINTN)HVMStartInfo->rsdp_paddr;\r
154 }\r
155 }\r
156 }\r
157\r
3b96221f
AP
158 BuildGuidDataHob (\r
159 &gEfiXenInfoGuid,\r
160 &mXenInfo,\r
161 sizeof(mXenInfo)\r
162 );\r
163\r
80b619d5
AP
164 //\r
165 // Initialize the XenHypercall library, now that the XenInfo HOB is\r
166 // available\r
167 //\r
168 Status = XenHypercallLibInit ();\r
169 ASSERT_RETURN_ERROR (Status);\r
170\r
3b96221f
AP
171 return EFI_SUCCESS;\r
172}\r
173\r
174/**\r
175 Figures out if we are running inside Xen HVM.\r
176\r
177 @retval TRUE Xen was detected\r
178 @retval FALSE Xen was not detected\r
179\r
180**/\r
181BOOLEAN\r
182XenDetect (\r
183 VOID\r
184 )\r
185{\r
186 UINT8 Signature[13];\r
187\r
188 if (mXenLeaf != 0) {\r
189 return TRUE;\r
190 }\r
191\r
192 Signature[12] = '\0';\r
193 for (mXenLeaf = 0x40000000; mXenLeaf < 0x40010000; mXenLeaf += 0x100) {\r
194 AsmCpuid (mXenLeaf,\r
195 NULL,\r
196 (UINT32 *) &Signature[0],\r
197 (UINT32 *) &Signature[4],\r
198 (UINT32 *) &Signature[8]);\r
199\r
200 if (!AsciiStrCmp ((CHAR8 *) Signature, "XenVMMXenVMM")) {\r
201 return TRUE;\r
202 }\r
203 }\r
204\r
205 mXenLeaf = 0;\r
206 return FALSE;\r
207}\r
208\r
4022f7fa
AP
209BOOLEAN\r
210XenHvmloaderDetected (\r
211 VOID\r
212 )\r
213{\r
214 return (mXenHvmloaderInfo != NULL);\r
215}\r
3b96221f 216\r
64eac295
AP
217BOOLEAN\r
218XenPvhDetected (\r
219 VOID\r
220 )\r
221{\r
222 //\r
223 // This function should only be used after XenConnect\r
224 //\r
225 ASSERT (mXenInfo.HyperPages != NULL);\r
226\r
227 return mXenHvmloaderInfo == NULL;\r
228}\r
229\r
3b96221f
AP
230VOID\r
231XenPublishRamRegions (\r
232 VOID\r
233 )\r
234{\r
235 EFI_E820_ENTRY64 *E820Map;\r
236 UINT32 E820EntriesCount;\r
237 EFI_STATUS Status;\r
238\r
239 DEBUG ((DEBUG_INFO, "Using memory map provided by Xen\n"));\r
240\r
241 //\r
242 // Parse RAM in E820 map\r
243 //\r
244 E820EntriesCount = 0;\r
245 Status = XenGetE820Map (&E820Map, &E820EntriesCount);\r
246\r
247 ASSERT_EFI_ERROR (Status);\r
248\r
249 if (E820EntriesCount > 0) {\r
250 EFI_E820_ENTRY64 *Entry;\r
251 UINT32 Loop;\r
252\r
253 for (Loop = 0; Loop < E820EntriesCount; Loop++) {\r
254 Entry = E820Map + Loop;\r
255\r
256 //\r
257 // Only care about RAM\r
258 //\r
259 if (Entry->Type != EfiAcpiAddressRangeMemory) {\r
260 continue;\r
261 }\r
262\r
263 AddMemoryBaseSizeHob (Entry->BaseAddr, Entry->Length);\r
264\r
265 MtrrSetMemoryAttribute (Entry->BaseAddr, Entry->Length, CacheWriteBack);\r
266 }\r
267 }\r
268}\r
269\r
270\r
271/**\r
272 Perform Xen PEI initialization.\r
273\r
274 @return EFI_SUCCESS Xen initialized successfully\r
275 @return EFI_NOT_FOUND Not running under Xen\r
276\r
277**/\r
278EFI_STATUS\r
279InitializeXen (\r
280 VOID\r
281 )\r
282{\r
283 RETURN_STATUS PcdStatus;\r
284\r
3b96221f
AP
285 //\r
286 // Reserve away HVMLOADER reserved memory [0xFC000000,0xFD000000).\r
287 // This needs to match HVMLOADER RESERVED_MEMBASE/RESERVED_MEMSIZE.\r
288 //\r
289 AddReservedMemoryBaseSizeHob (0xFC000000, 0x1000000, FALSE);\r
290\r
291 PcdStatus = PcdSetBoolS (PcdPciDisableBusEnumeration, TRUE);\r
292 ASSERT_RETURN_ERROR (PcdStatus);\r
293\r
294 return EFI_SUCCESS;\r
295}\r