On 07/07/16 21:10, Laszlo Ersek wrote:
> 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 <[email protected]>
> Cc: Jordan Justen <[email protected]>
> Cc: Michael Kinney <[email protected]>
> Fixes: https://github.com/tianocore/edk2/issues/97
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Laszlo Ersek <[email protected]>
> ---
> OvmfPkg/PlatformPei/PlatformPei.inf | 2 +
> OvmfPkg/PlatformPei/Platform.h | 5 +
> OvmfPkg/PlatformPei/FeatureControl.c | 134 ++++++++++++++++++++
> OvmfPkg/PlatformPei/Platform.c | 1 +
> 4 files changed, 142 insertions(+)
>
> diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf
> b/OvmfPkg/PlatformPei/PlatformPei.inf
> index 3556404017fc..8abffde04773 100644
> --- a/OvmfPkg/PlatformPei/PlatformPei.inf
> +++ b/OvmfPkg/PlatformPei/PlatformPei.inf
> @@ -30,6 +30,7 @@ [Defines]
>
> [Sources]
> Cmos.c
> + FeatureControl.c
> Fv.c
> MemDetect.c
> Platform.c
> @@ -104,6 +105,7 @@ [FeaturePcd]
>
> [Ppis]
> gEfiPeiMasterBootModePpiGuid
> + gEfiPeiMpServicesPpiGuid
>
> [Depex]
> TRUE
> diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h
> index bb988ea19e7d..eda765be30de 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/FeatureControl.c
> b/OvmfPkg/PlatformPei/FeatureControl.c
> new file mode 100644
> index 000000000000..508001b2bacf
> --- /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)) {
> + DEBUG ((EFI_D_ERROR, "%a: StartupAllAps(): %r\n", __FUNCTION__, Status));
> + return Status;
> + }
Argh, I always forget that StartupAllAPs() returns EFI_NOT_STARTED in
uniprocessor systems. I'll update this error check to
EFI_ERROR (Status) && Status != EFI_NOT_STARTED
for version 2 (or before pushing the series, if Jordan deems the series
good enough otherwise).
Thanks & sorry
Laszlo
> +
> + //
> + // 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 75f7480ac726..ca1e6dc7e320 100644
> --- a/OvmfPkg/PlatformPei/Platform.c
> +++ b/OvmfPkg/PlatformPei/Platform.c
> @@ -612,6 +612,7 @@ InitializePlatform (
> }
>
> MiscInitialization ();
> + InstallFeatureControlCallback ();
>
> return EFI_SUCCESS;
> }
>
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel