• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
WriteFeatureControl(IN OUT VOID * WorkSpace)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
OnMpServicesAvailable(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_NOTIFY_DESCRIPTOR * NotifyDescriptor,IN VOID * Ppi)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
InstallFeatureControlCallback(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