Home | History | Annotate | Download | only in PlatformPei
      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 (at) 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
     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
     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
    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
    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
    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