From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 DD28381E1F for ; Tue, 22 Nov 2016 12:26:31 -0800 (PST) Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (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 794313F20A; Tue, 22 Nov 2016 20:26:31 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-116-82.phx2.redhat.com [10.3.116.82]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id uAMKQN4w021949; Tue, 22 Nov 2016 15:26:30 -0500 From: Laszlo Ersek To: edk2-devel-01 Cc: Igor Mammedov , Jeff Fan Date: Tue, 22 Nov 2016 21:26:18 +0100 Message-Id: <20161122202619.12594-4-lersek@redhat.com> In-Reply-To: <20161122202619.12594-1-lersek@redhat.com> References: <20161122202619.12594-1-lersek@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Tue, 22 Nov 2016 20:26:31 +0000 (UTC) Subject: [PATCH 3/4] UefiCpuPkg/MpInitLib: allow platforms to provide a known CPU count upfront X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 22 Nov 2016 20:26:32 -0000 On QEMU/KVM, the VCPU topology for a guest is specified dynamically. It can be a low number or a high number. Waiting for PcdCpuApInitTimeOutInMicroSeconds during the initial AP collection is impractical, because in a VM, the time needed for an AP to wake up can vary widely: - if the APs report back quickly, then we could be wasting time, - if the APs report back late (due to scheduling artifacts or VCPU over-subscription on the virtualization host), then the timeout can elapse before all APs increment CpuMpData->CpuCount in ApWakeupFunction(). Trying to set PcdCpuApInitTimeOutInMicroSeconds dynamically is also impractical, as scheduling artifacts on the KVM host may delay AP threads arbitrarily. Instead, allow OVMF (and other platforms) to tell MpInitLib the number of boot-time CPUs in advance. Cc: Igor Mammedov Cc: Jeff Fan Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek --- UefiCpuPkg/UefiCpuPkg.dec | 11 +++++++++++ UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf | 1 + UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf | 4 ++-- UefiCpuPkg/Library/MpInitLib/MpLib.c | 16 ++++++++++++---- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec index ca560398bbef..35903c4386e4 100644 --- a/UefiCpuPkg/UefiCpuPkg.dec +++ b/UefiCpuPkg/UefiCpuPkg.dec @@ -225,5 +225,16 @@ [PcdsDynamic, PcdsDynamicEx] # @ValidList 0x80000001 | 0 gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugDataAddress|0x0|UINT64|0x60000011 + ## On platforms where the number of boot-time CPUs can be dynamically + # retrieved from a platform-specific information source, the BSP does not + # have to wait for PcdCpuApInitTimeOutInMicroSeconds in order to detect all + # APs for the first time. On such platforms, this PCD specifies the number + # of CPUs available at boot. If the platform doesn't support this feature, + # this PCD should be set to 0. The platform is responsible for ensuring that + # this PCD is never set to a value larger than + # PcdCpuMaxLogicalProcessorNumber. + # @Prompt Known number of CPUs available at boot. + gUefiCpuPkgTokenSpaceGuid.PcdCpuKnownLogicalProcessorNumber|0|UINT32|0x60000012 + [UserExtensions.TianoCore."ExtraFiles"] UefiCpuPkgExtra.uni diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf index 11b230174ec8..dc18eaf6152d 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf @@ -61,6 +61,7 @@ [Guids] [Pcd] gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdCpuKnownLogicalProcessorNumber ## SOMETIMES_CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds ## SOMETIMES_CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress ## CONSUMES diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf index 0c6873da79db..2bcfa70ae7e5 100644 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf @@ -61,10 +61,10 @@ [Ppis] [Pcd] gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## CONSUMES - gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds ## CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdCpuKnownLogicalProcessorNumber ## CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds ## SOMETIMES_CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate ## SOMETIMES_CONSUMES - diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c index 15dbfa1e7d6c..f7dfbd5bad13 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -707,6 +707,7 @@ WakeUpAP ( CPU_AP_DATA *CpuData; BOOLEAN ResetVectorRequired; CPU_INFO_IN_HOB *CpuInfoInHob; + UINT32 KnownProcessorCount; CpuMpData->FinishedCount = 0; ResetVectorRequired = FALSE; @@ -745,10 +746,17 @@ WakeUpAP ( SendInitSipiSipiAllExcludingSelf ((UINT32) ExchangeInfo->BufferStart); } if (CpuMpData->InitFlag == ApInitConfig) { - // - // Wait for all potential APs waken up in one specified period - // - MicroSecondDelay (PcdGet32(PcdCpuApInitTimeOutInMicroSeconds)); + KnownProcessorCount = PcdGet32 (PcdCpuKnownLogicalProcessorNumber); + if (KnownProcessorCount > 0) { + while (CpuMpData->FinishedCount < (KnownProcessorCount - 1)) { + CpuPause (); + } + } else { + // + // Wait for all potential APs waken up in one specified period + // + MicroSecondDelay (PcdGet32(PcdCpuApInitTimeOutInMicroSeconds)); + } } else { // // Wait all APs waken up if this is not the 1st broadcast of SIPI -- 2.9.2