From patchwork Wed Jul 13 00:18:06 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laszlo Ersek X-Patchwork-Id: 71898 Delivered-To: patch@linaro.org Received: by 10.140.29.52 with SMTP id a49csp735348qga; Tue, 12 Jul 2016 17:18:45 -0700 (PDT) X-Received: by 10.66.160.199 with SMTP id xm7mr8745199pab.78.1468369125152; Tue, 12 Jul 2016 17:18:45 -0700 (PDT) Return-Path: Received: from ml01.01.org (ml01.01.org. [198.145.21.10]) by mx.google.com with ESMTPS id d5si830947pfa.86.2016.07.12.17.18.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 12 Jul 2016 17:18:45 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) client-ip=198.145.21.10; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id A1EF51A1EFC; Tue, 12 Jul 2016 17:19:29 -0700 (PDT) X-Original-To: edk2-devel@ml01.01.org Delivered-To: edk2-devel@ml01.01.org Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id A293A1A1EFC for ; Tue, 12 Jul 2016 17:19:27 -0700 (PDT) Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 069CCC0467C9; Wed, 13 Jul 2016 00:18:42 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-116-96.phx2.redhat.com [10.3.116.96]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u6D0IAjA025765; Tue, 12 Jul 2016 20:18:40 -0400 From: Laszlo Ersek To: edk2-devel-01 Date: Wed, 13 Jul 2016 02:18:06 +0200 Message-Id: <1468369086-5616-6-git-send-email-lersek@redhat.com> In-Reply-To: <1468369086-5616-1-git-send-email-lersek@redhat.com> References: <1468369086-5616-1-git-send-email-lersek@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Wed, 13 Jul 2016 00:18:42 +0000 (UTC) Subject: [edk2] [PATCH v2 5/5] OvmfPkg/PlatformPei: program MSR_IA32_FEATURE_CONTROL from fw_cfg X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Michael Kinney , Jordan Justen , Jeff Fan MIME-Version: 1.0 Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" 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 Cc: Jordan Justen Cc: Michael Kinney Fixes: https://github.com/tianocore/edk2/issues/97 Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek Reviewed-by: Jeff Fan --- Notes: v2: - consider the EFI_NOT_STARTED status code from EFI_PEI_MP_SERVICES_PPI.StartupAllAPs() success: it is returned in uniprocessor guests [Laszlo] 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 diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf index 229831b10da0..3917446eb0b2 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 @@ -103,6 +104,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..b91d9888a947 --- /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 +#include +#include +#include +#include + +#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 75f7480ac726..ca1e6dc7e320 100644 --- a/OvmfPkg/PlatformPei/Platform.c +++ b/OvmfPkg/PlatformPei/Platform.c @@ -612,6 +612,7 @@ InitializePlatform ( } MiscInitialization (); + InstallFeatureControlCallback (); return EFI_SUCCESS; }