Home | History | Annotate | Download | only in PlatformPei
      1 /**@file
      2   Install a callback when necessary for setting the Feature Control MSR on all
      3   processors.
      4 
      5   Copyright (C) 2016, Red Hat, Inc.
      6 
      7   This program and the accompanying materials are licensed and made available
      8   under the terms and conditions of the BSD License which accompanies this
      9   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, WITHOUT
     13   WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 **/
     15 
     16 #include <Library/DebugLib.h>
     17 #include <Library/PeiServicesLib.h>
     18 #include <Library/QemuFwCfgLib.h>
     19 #include <Ppi/MpServices.h>
     20 #include <Register/Msr/Core2Msr.h>
     21 
     22 #include "Platform.h"
     23 
     24 //
     25 // The value to be written to the Feature Control MSR, retrieved from fw_cfg.
     26 //
     27 STATIC UINT64 mFeatureControlValue;
     28 
     29 /**
     30   Write the Feature Control MSR on an Application Processor or the Boot
     31   Processor.
     32 
     33   All APs execute this function in parallel. The BSP executes the function
     34   separately.
     35 
     36   @param[in,out] WorkSpace  Pointer to the input/output argument workspace
     37                             shared by all processors.
     38 **/
     39 STATIC
     40 VOID
     41 EFIAPI
     42 WriteFeatureControl (
     43   IN OUT VOID *WorkSpace
     44   )
     45 {
     46   AsmWriteMsr64 (MSR_CORE2_FEATURE_CONTROL, mFeatureControlValue);
     47 }
     48 
     49 /**
     50   Notification function called when EFI_PEI_MP_SERVICES_PPI becomes available.
     51 
     52   @param[in] PeiServices      Indirect reference to the PEI Services Table.
     53   @param[in] NotifyDescriptor Address of the notification descriptor data
     54                               structure.
     55   @param[in] Ppi              Address of the PPI that was installed.
     56 
     57   @return  Status of the notification. The status code returned from this
     58            function is ignored.
     59 **/
     60 STATIC
     61 EFI_STATUS
     62 EFIAPI
     63 OnMpServicesAvailable (
     64   IN EFI_PEI_SERVICES           **PeiServices,
     65   IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
     66   IN VOID                       *Ppi
     67   )
     68 {
     69   EFI_PEI_MP_SERVICES_PPI *MpServices;
     70   EFI_STATUS              Status;
     71 
     72   DEBUG ((EFI_D_VERBOSE, "%a: %a\n", gEfiCallerBaseName, __FUNCTION__));
     73 
     74   //
     75   // Write the MSR on all the APs in parallel.
     76   //
     77   MpServices = Ppi;
     78   Status = MpServices->StartupAllAPs (
     79                          (CONST EFI_PEI_SERVICES **)PeiServices,
     80                          MpServices,
     81                          WriteFeatureControl, // Procedure
     82                          FALSE,               // SingleThread
     83                          0,                   // TimeoutInMicroSeconds: inf.
     84                          NULL                 // ProcedureArgument
     85                          );
     86   if (EFI_ERROR (Status) && Status != EFI_NOT_STARTED) {
     87     DEBUG ((EFI_D_ERROR, "%a: StartupAllAps(): %r\n", __FUNCTION__, Status));
     88     return Status;
     89   }
     90 
     91   //
     92   // Now write the MSR on the BSP too.
     93   //
     94   WriteFeatureControl (NULL);
     95   return EFI_SUCCESS;
     96 }
     97 
     98 //
     99 // Notification object for registering the callback, for when
    100 // EFI_PEI_MP_SERVICES_PPI becomes available.
    101 //
    102 STATIC CONST EFI_PEI_NOTIFY_DESCRIPTOR mMpServicesNotify = {
    103   EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | // Flags
    104   EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
    105   &gEfiPeiMpServicesPpiGuid,               // Guid
    106   OnMpServicesAvailable                    // Notify
    107 };
    108 
    109 VOID
    110 InstallFeatureControlCallback (
    111   VOID
    112   )
    113 {
    114   EFI_STATUS           Status;
    115   FIRMWARE_CONFIG_ITEM FwCfgItem;
    116   UINTN                FwCfgSize;
    117 
    118   Status = QemuFwCfgFindFile ("etc/msr_feature_control", &FwCfgItem,
    119              &FwCfgSize);
    120   if (EFI_ERROR (Status) || FwCfgSize != sizeof mFeatureControlValue) {
    121     //
    122     // Nothing to do.
    123     //
    124     return;
    125   }
    126   QemuFwCfgSelectItem (FwCfgItem);
    127   QemuFwCfgReadBytes (sizeof mFeatureControlValue, &mFeatureControlValue);
    128 
    129   Status = PeiServicesNotifyPpi (&mMpServicesNotify);
    130   if (EFI_ERROR (Status)) {
    131     DEBUG ((EFI_D_ERROR, "%a: failed to set up MP Services callback: %r\n",
    132       __FUNCTION__, Status));
    133   }
    134 }
    135