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