]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/PlatformPei: program MSR_IA32_FEATURE_CONTROL from fw_cfg
authorLaszlo Ersek <lersek@redhat.com>
Thu, 7 Jul 2016 13:02:11 +0000 (15:02 +0200)
committerLaszlo Ersek <lersek@redhat.com>
Fri, 15 Jul 2016 05:38:56 +0000 (07:38 +0200)
Under certain circumstances, QEMU exposes the "etc/msr_feature_control"
fw_cfg file, with a 64-bit little endian value. The firmware is supposed
to write this value to MSR_IA32_FEATURE_CONTROL (0x3a), on all processors,
on the normal and the S3 resume boot paths.

Utilize EFI_PEI_MPSERVICES_PPI to implement this feature.

Cc: Jeff Fan <jeff.fan@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Fixes: https://github.com/tianocore/edk2/issues/97
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
OvmfPkg/PlatformPei/FeatureControl.c [new file with mode: 0644]
OvmfPkg/PlatformPei/Platform.c
OvmfPkg/PlatformPei/Platform.h
OvmfPkg/PlatformPei/PlatformPei.inf

diff --git a/OvmfPkg/PlatformPei/FeatureControl.c b/OvmfPkg/PlatformPei/FeatureControl.c
new file mode 100644 (file)
index 0000000..b91d988
--- /dev/null
@@ -0,0 +1,134 @@
+/**@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
index 75f7480ac726e4a8a3f71a26825dba7abc7adacc..ca1e6dc7e320169c1611a9de81c71e85c875fc6b 100644 (file)
@@ -612,6 +612,7 @@ InitializePlatform (
   }\r
 \r
   MiscInitialization ();\r
+  InstallFeatureControlCallback ();\r
 \r
   return EFI_SUCCESS;\r
 }\r
index bb988ea19e7d1bfeeba27c01b6b66602b4b9b18e..eda765be30dee46de7d1d362456d7f5c44e15a89 100644 (file)
@@ -73,6 +73,11 @@ PeiFvInitialization (
   VOID\r
   );\r
 \r
+VOID\r
+InstallFeatureControlCallback (\r
+  VOID\r
+  );\r
+\r
 EFI_STATUS\r
 InitializeXen (\r
   VOID\r
index 5d765baaebe4234e82d8d9076bb9632dc47c07fc..776a4ab11f7900660d5ff032b02e7c054279354e 100644 (file)
@@ -30,6 +30,7 @@
 \r
 [Sources]\r
   Cmos.c\r
+  FeatureControl.c\r
   Fv.c\r
   MemDetect.c\r
   Platform.c\r
 \r
 [Ppis]\r
   gEfiPeiMasterBootModePpiGuid\r
+  gEfiPeiMpServicesPpiGuid\r
 \r
 [Depex]\r
   TRUE\r