• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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   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
InitializeXen(VOID)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