• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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
XenGetE820Map(EFI_E820_ENTRY64 ** Entries,UINT32 * Count)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
XenConnect(UINT32 XenLeaf)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
XenDetect(VOID)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
XenPublishRamRegions(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   E820EntriesCount = 0;
175   Status = XenGetE820Map (&E820Map, &E820EntriesCount);
176 
177   ASSERT_EFI_ERROR (Status);
178 
179   if (E820EntriesCount > 0) {
180     EFI_E820_ENTRY64 *Entry;
181     UINT32 Loop;
182 
183     for (Loop = 0; Loop < E820EntriesCount; Loop++) {
184       Entry = E820Map + Loop;
185 
186       //
187       // Only care about RAM
188       //
189       if (Entry->Type != EfiAcpiAddressRangeMemory) {
190         continue;
191       }
192 
193       AddMemoryBaseSizeHob (Entry->BaseAddr, Entry->Length);
194 
195       MtrrSetMemoryAttribute (Entry->BaseAddr, Entry->Length, CacheWriteBack);
196     }
197   }
198 }
199 
200 
201 /**
202   Perform Xen PEI initialization.
203 
204   @return EFI_SUCCESS     Xen initialized successfully
205   @return EFI_NOT_FOUND   Not running under Xen
206 
207 **/
208 EFI_STATUS
InitializeXen(VOID)209 InitializeXen (
210   VOID
211   )
212 {
213   RETURN_STATUS PcdStatus;
214 
215   if (mXenLeaf == 0) {
216     return EFI_NOT_FOUND;
217   }
218 
219   XenConnect (mXenLeaf);
220 
221   //
222   // Reserve away HVMLOADER reserved memory [0xFC000000,0xFD000000).
223   // This needs to match HVMLOADER RESERVED_MEMBASE/RESERVED_MEMSIZE.
224   //
225   AddReservedMemoryBaseSizeHob (0xFC000000, 0x1000000, FALSE);
226 
227   PcdStatus = PcdSetBoolS (PcdPciDisableBusEnumeration, TRUE);
228   ASSERT_RETURN_ERROR (PcdStatus);
229 
230   return EFI_SUCCESS;
231 }
232