--- /dev/null
+/**@file\r
+ Install a callback when necessary for setting the Feature Control MSR on all\r
+ processors.\r
+\r
+ Copyright (C) 2016, Red Hat, Inc.\r
+\r
+ This program and the accompanying materials are licensed and made available\r
+ under the terms and conditions of the BSD License which accompanies this\r
+ distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Library/QemuFwCfgLib.h>\r
+#include <Ppi/MpServices.h>\r
+#include <Register/Msr/Core2Msr.h>\r
+\r
+#include "Platform.h"\r
+\r
+//\r
+// The value to be written to the Feature Control MSR, retrieved from fw_cfg.\r
+//\r
+STATIC UINT64 mFeatureControlValue;\r
+\r
+/**\r
+ Write the Feature Control MSR on an Application Processor or the Boot\r
+ Processor.\r
+\r
+ All APs execute this function in parallel. The BSP executes the function\r
+ separately.\r
+\r
+ @param[in,out] WorkSpace Pointer to the input/output argument workspace\r
+ shared by all processors.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+WriteFeatureControl (\r
+ IN OUT VOID *WorkSpace\r
+ )\r
+{\r
+ AsmWriteMsr64 (MSR_CORE2_FEATURE_CONTROL, mFeatureControlValue);\r
+}\r
+\r
+/**\r
+ Notification function called when EFI_PEI_MP_SERVICES_PPI becomes available.\r
+\r
+ @param[in] PeiServices Indirect reference to the PEI Services Table.\r
+ @param[in] NotifyDescriptor Address of the notification descriptor data\r
+ structure.\r
+ @param[in] Ppi Address of the PPI that was installed.\r
+\r
+ @return Status of the notification. The status code returned from this\r
+ function is ignored.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+OnMpServicesAvailable (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
+ IN VOID *Ppi\r
+ )\r
+{\r
+ EFI_PEI_MP_SERVICES_PPI *MpServices;\r
+ EFI_STATUS Status;\r
+\r
+ DEBUG ((EFI_D_VERBOSE, "%a: %a\n", gEfiCallerBaseName, __FUNCTION__));\r
+\r
+ //\r
+ // Write the MSR on all the APs in parallel.\r
+ //\r
+ MpServices = Ppi;\r
+ Status = MpServices->StartupAllAPs (\r
+ (CONST EFI_PEI_SERVICES **)PeiServices,\r
+ MpServices,\r
+ WriteFeatureControl, // Procedure\r
+ FALSE, // SingleThread\r
+ 0, // TimeoutInMicroSeconds: inf.\r
+ NULL // ProcedureArgument\r
+ );\r
+ if (EFI_ERROR (Status) && Status != EFI_NOT_STARTED) {\r
+ DEBUG ((EFI_D_ERROR, "%a: StartupAllAps(): %r\n", __FUNCTION__, Status));\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Now write the MSR on the BSP too.\r
+ //\r
+ WriteFeatureControl (NULL);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// Notification object for registering the callback, for when\r
+// EFI_PEI_MP_SERVICES_PPI becomes available.\r
+//\r
+STATIC CONST EFI_PEI_NOTIFY_DESCRIPTOR mMpServicesNotify = {\r
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | // Flags\r
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
+ &gEfiPeiMpServicesPpiGuid, // Guid\r
+ OnMpServicesAvailable // Notify\r
+};\r
+\r
+VOID\r
+InstallFeatureControlCallback (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ FIRMWARE_CONFIG_ITEM FwCfgItem;\r
+ UINTN FwCfgSize;\r
+\r
+ Status = QemuFwCfgFindFile ("etc/msr_feature_control", &FwCfgItem,\r
+ &FwCfgSize);\r
+ if (EFI_ERROR (Status) || FwCfgSize != sizeof mFeatureControlValue) {\r
+ //\r
+ // Nothing to do.\r
+ //\r
+ return;\r
+ }\r
+ QemuFwCfgSelectItem (FwCfgItem);\r
+ QemuFwCfgReadBytes (sizeof mFeatureControlValue, &mFeatureControlValue);\r
+\r
+ Status = PeiServicesNotifyPpi (&mMpServicesNotify);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "%a: failed to set up MP Services callback: %r\n",\r
+ __FUNCTION__, Status));\r
+ }\r
+}\r