Message ID | 1467918647-14721-5-git-send-email-lersek@redhat.com |
---|---|
State | Superseded |
Headers | show |
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 <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> > --- > 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 edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
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; + } + + // + // 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; }
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> --- 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(+) -- 1.8.3.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel