]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/XenPlatformPei/Xen.c
9962fe9fc796ba819e980b6b2c03fa6760f9b42f
[mirror_edk2.git] / OvmfPkg / XenPlatformPei / Xen.c
1 /**@file
2 Xen Platform PEI support
3
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.
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10 **/
11
12 //
13 // The package level header files this module uses
14 //
15 #include <PiPei.h>
16
17 //
18 // The Library classes this module consumes
19 //
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>
28
29 #include "Platform.h"
30 #include "Xen.h"
31
32 STATIC UINT32 mXenLeaf = 0;
33
34 EFI_XEN_INFO mXenInfo;
35
36 //
37 // Location of the firmware info struct setup by hvmloader.
38 // Only the E820 table is used by OVMF.
39 //
40 EFI_XEN_OVMF_INFO *mXenHvmloaderInfo;
41
42 /**
43 Returns E820 map provided by Xen
44
45 @param Entries Pointer to E820 map
46 @param Count Number of entries
47
48 @return EFI_STATUS
49 **/
50 EFI_STATUS
51 XenGetE820Map (
52 EFI_E820_ENTRY64 **Entries,
53 UINT32 *Count
54 )
55 {
56 EFI_XEN_OVMF_INFO *Info =
57 (EFI_XEN_OVMF_INFO *)(UINTN) OVMF_INFO_PHYSICAL_ADDRESS;
58
59 if (AsciiStrCmp ((CHAR8 *) Info->Signature, "XenHVMOVMF")) {
60 return EFI_NOT_FOUND;
61 }
62
63 ASSERT (Info->E820 < MAX_ADDRESS);
64 *Entries = (EFI_E820_ENTRY64 *)(UINTN) Info->E820;
65 *Count = Info->E820EntriesCount;
66
67 return EFI_SUCCESS;
68 }
69
70 /**
71 Connects to the Hypervisor.
72
73 @param XenLeaf CPUID index used to connect.
74
75 @return EFI_STATUS
76
77 **/
78 EFI_STATUS
79 XenConnect (
80 UINT32 XenLeaf
81 )
82 {
83 UINT32 Index;
84 UINT32 TransferReg;
85 UINT32 TransferPages;
86 UINT32 XenVersion;
87 EFI_XEN_OVMF_INFO *Info;
88 CHAR8 Sig[sizeof (Info->Signature) + 1];
89
90 AsmCpuid (XenLeaf + 2, &TransferPages, &TransferReg, NULL, NULL);
91 mXenInfo.HyperPages = AllocatePages (TransferPages);
92 if (!mXenInfo.HyperPages) {
93 return EFI_OUT_OF_RESOURCES;
94 }
95
96 for (Index = 0; Index < TransferPages; Index++) {
97 AsmWriteMsr64 (TransferReg,
98 (UINTN) mXenInfo.HyperPages +
99 (Index << EFI_PAGE_SHIFT) + Index);
100 }
101
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);
107
108 //
109 // Check if there are information left by hvmloader
110 //
111
112 Info = (EFI_XEN_OVMF_INFO *)(UINTN) OVMF_INFO_PHYSICAL_ADDRESS;
113 //
114 // Copy the signature, and make it null-terminated.
115 //
116 AsciiStrnCpyS (Sig, sizeof (Sig), (CHAR8 *) &Info->Signature,
117 sizeof (Info->Signature));
118 if (AsciiStrCmp (Sig, "XenHVMOVMF") == 0) {
119 mXenHvmloaderInfo = Info;
120 } else {
121 mXenHvmloaderInfo = NULL;
122 }
123
124 BuildGuidDataHob (
125 &gEfiXenInfoGuid,
126 &mXenInfo,
127 sizeof(mXenInfo)
128 );
129
130 return EFI_SUCCESS;
131 }
132
133 /**
134 Figures out if we are running inside Xen HVM.
135
136 @retval TRUE Xen was detected
137 @retval FALSE Xen was not detected
138
139 **/
140 BOOLEAN
141 XenDetect (
142 VOID
143 )
144 {
145 UINT8 Signature[13];
146
147 if (mXenLeaf != 0) {
148 return TRUE;
149 }
150
151 Signature[12] = '\0';
152 for (mXenLeaf = 0x40000000; mXenLeaf < 0x40010000; mXenLeaf += 0x100) {
153 AsmCpuid (mXenLeaf,
154 NULL,
155 (UINT32 *) &Signature[0],
156 (UINT32 *) &Signature[4],
157 (UINT32 *) &Signature[8]);
158
159 if (!AsciiStrCmp ((CHAR8 *) Signature, "XenVMMXenVMM")) {
160 return TRUE;
161 }
162 }
163
164 mXenLeaf = 0;
165 return FALSE;
166 }
167
168
169 VOID
170 XenPublishRamRegions (
171 VOID
172 )
173 {
174 EFI_E820_ENTRY64 *E820Map;
175 UINT32 E820EntriesCount;
176 EFI_STATUS Status;
177
178 DEBUG ((DEBUG_INFO, "Using memory map provided by Xen\n"));
179
180 //
181 // Parse RAM in E820 map
182 //
183 E820EntriesCount = 0;
184 Status = XenGetE820Map (&E820Map, &E820EntriesCount);
185
186 ASSERT_EFI_ERROR (Status);
187
188 if (E820EntriesCount > 0) {
189 EFI_E820_ENTRY64 *Entry;
190 UINT32 Loop;
191
192 for (Loop = 0; Loop < E820EntriesCount; Loop++) {
193 Entry = E820Map + Loop;
194
195 //
196 // Only care about RAM
197 //
198 if (Entry->Type != EfiAcpiAddressRangeMemory) {
199 continue;
200 }
201
202 AddMemoryBaseSizeHob (Entry->BaseAddr, Entry->Length);
203
204 MtrrSetMemoryAttribute (Entry->BaseAddr, Entry->Length, CacheWriteBack);
205 }
206 }
207 }
208
209
210 /**
211 Perform Xen PEI initialization.
212
213 @return EFI_SUCCESS Xen initialized successfully
214 @return EFI_NOT_FOUND Not running under Xen
215
216 **/
217 EFI_STATUS
218 InitializeXen (
219 VOID
220 )
221 {
222 RETURN_STATUS PcdStatus;
223
224 if (mXenLeaf == 0) {
225 return EFI_NOT_FOUND;
226 }
227
228 XenConnect (mXenLeaf);
229
230 //
231 // Reserve away HVMLOADER reserved memory [0xFC000000,0xFD000000).
232 // This needs to match HVMLOADER RESERVED_MEMBASE/RESERVED_MEMSIZE.
233 //
234 AddReservedMemoryBaseSizeHob (0xFC000000, 0x1000000, FALSE);
235
236 PcdStatus = PcdSetBoolS (PcdPciDisableBusEnumeration, TRUE);
237 ASSERT_RETURN_ERROR (PcdStatus);
238
239 return EFI_SUCCESS;
240 }