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