diff options
author | Laszlo Ersek <lersek@redhat.com> | 2016-07-07 15:02:11 +0200 |
---|---|---|
committer | Laszlo Ersek <lersek@redhat.com> | 2016-07-15 07:38:56 +0200 |
commit | dbab994991c76dc4b9414a3d80997b64b0fdf9c5 (patch) | |
tree | 589e82c2872919675601e924a673f63e9ad41a4c | |
parent | f0e6a56a9a2fbe6e9a1897e9a10b4bb3aca76cff (diff) | |
download | edk2-dbab994991c76dc4b9414a3d80997b64b0fdf9c5.tar.gz edk2-dbab994991c76dc4b9414a3d80997b64b0fdf9c5.tar.bz2 edk2-dbab994991c76dc4b9414a3d80997b64b0fdf9c5.zip |
OvmfPkg/PlatformPei: program MSR_IA32_FEATURE_CONTROL from fw_cfg
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>
-rw-r--r-- | OvmfPkg/PlatformPei/FeatureControl.c | 134 | ||||
-rw-r--r-- | OvmfPkg/PlatformPei/Platform.c | 1 | ||||
-rw-r--r-- | OvmfPkg/PlatformPei/Platform.h | 5 | ||||
-rw-r--r-- | OvmfPkg/PlatformPei/PlatformPei.inf | 2 |
4 files changed, 142 insertions, 0 deletions
diff --git a/OvmfPkg/PlatformPei/FeatureControl.c b/OvmfPkg/PlatformPei/FeatureControl.c new file mode 100644 index 0000000000..b91d9888a9 --- /dev/null +++ b/OvmfPkg/PlatformPei/FeatureControl.c @@ -0,0 +1,134 @@ +/**@file
+ Install a callback when necessary for setting the Feature Control MSR on all
+ processors.
+
+ Copyright (C) 2016, Red Hat, Inc.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/QemuFwCfgLib.h>
+#include <Ppi/MpServices.h>
+#include <Register/Msr/Core2Msr.h>
+
+#include "Platform.h"
+
+//
+// The value to be written to the Feature Control MSR, retrieved from fw_cfg.
+//
+STATIC UINT64 mFeatureControlValue;
+
+/**
+ Write the Feature Control MSR on an Application Processor or the Boot
+ Processor.
+
+ All APs execute this function in parallel. The BSP executes the function
+ separately.
+
+ @param[in,out] WorkSpace Pointer to the input/output argument workspace
+ shared by all processors.
+**/
+STATIC
+VOID
+EFIAPI
+WriteFeatureControl (
+ IN OUT VOID *WorkSpace
+ )
+{
+ AsmWriteMsr64 (MSR_CORE2_FEATURE_CONTROL, mFeatureControlValue);
+}
+
+/**
+ Notification function called when EFI_PEI_MP_SERVICES_PPI becomes available.
+
+ @param[in] PeiServices Indirect reference to the PEI Services Table.
+ @param[in] NotifyDescriptor Address of the notification descriptor data
+ structure.
+ @param[in] Ppi Address of the PPI that was installed.
+
+ @return Status of the notification. The status code returned from this
+ function is ignored.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+OnMpServicesAvailable (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_PEI_MP_SERVICES_PPI *MpServices;
+ EFI_STATUS Status;
+
+ DEBUG ((EFI_D_VERBOSE, "%a: %a\n", gEfiCallerBaseName, __FUNCTION__));
+
+ //
+ // Write the MSR on all the APs in parallel.
+ //
+ MpServices = Ppi;
+ Status = MpServices->StartupAllAPs (
+ (CONST EFI_PEI_SERVICES **)PeiServices,
+ MpServices,
+ WriteFeatureControl, // Procedure
+ FALSE, // SingleThread
+ 0, // TimeoutInMicroSeconds: inf.
+ NULL // ProcedureArgument
+ );
+ if (EFI_ERROR (Status) && Status != EFI_NOT_STARTED) {
+ DEBUG ((EFI_D_ERROR, "%a: StartupAllAps(): %r\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ //
+ // Now write the MSR on the BSP too.
+ //
+ WriteFeatureControl (NULL);
+ return EFI_SUCCESS;
+}
+
+//
+// Notification object for registering the callback, for when
+// EFI_PEI_MP_SERVICES_PPI becomes available.
+//
+STATIC CONST EFI_PEI_NOTIFY_DESCRIPTOR mMpServicesNotify = {
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | // Flags
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gEfiPeiMpServicesPpiGuid, // Guid
+ OnMpServicesAvailable // Notify
+};
+
+VOID
+InstallFeatureControlCallback (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ FIRMWARE_CONFIG_ITEM FwCfgItem;
+ UINTN FwCfgSize;
+
+ Status = QemuFwCfgFindFile ("etc/msr_feature_control", &FwCfgItem,
+ &FwCfgSize);
+ if (EFI_ERROR (Status) || FwCfgSize != sizeof mFeatureControlValue) {
+ //
+ // Nothing to do.
+ //
+ return;
+ }
+ QemuFwCfgSelectItem (FwCfgItem);
+ QemuFwCfgReadBytes (sizeof mFeatureControlValue, &mFeatureControlValue);
+
+ Status = PeiServicesNotifyPpi (&mMpServicesNotify);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a: failed to set up MP Services callback: %r\n",
+ __FUNCTION__, Status));
+ }
+}
diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c index 75f7480ac7..ca1e6dc7e3 100644 --- a/OvmfPkg/PlatformPei/Platform.c +++ b/OvmfPkg/PlatformPei/Platform.c @@ -612,6 +612,7 @@ InitializePlatform ( }
MiscInitialization ();
+ InstallFeatureControlCallback ();
return EFI_SUCCESS;
}
diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h index bb988ea19e..eda765be30 100644 --- a/OvmfPkg/PlatformPei/Platform.h +++ b/OvmfPkg/PlatformPei/Platform.h @@ -73,6 +73,11 @@ PeiFvInitialization ( VOID
);
+VOID
+InstallFeatureControlCallback (
+ VOID
+ );
+
EFI_STATUS
InitializeXen (
VOID
diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf index 5d765baaeb..776a4ab11f 100644 --- a/OvmfPkg/PlatformPei/PlatformPei.inf +++ b/OvmfPkg/PlatformPei/PlatformPei.inf @@ -30,6 +30,7 @@ [Sources]
Cmos.c
+ FeatureControl.c
Fv.c
MemDetect.c
Platform.c
@@ -104,6 +105,7 @@ [Ppis]
gEfiPeiMasterBootModePpiGuid
+ gEfiPeiMpServicesPpiGuid
[Depex]
TRUE
|