From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) (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 1FAB581CC3 for ; Mon, 28 Nov 2016 16:42:37 -0800 (PST) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga105.fm.intel.com with ESMTP; 28 Nov 2016 16:42:36 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.31,565,1473145200"; d="scan'208";a="1065433488" Received: from fmsmsx105.amr.corp.intel.com ([10.18.124.203]) by orsmga001.jf.intel.com with ESMTP; 28 Nov 2016 16:42:36 -0800 Received: from fmsmsx153.amr.corp.intel.com (10.18.125.6) by FMSMSX105.amr.corp.intel.com (10.18.124.203) with Microsoft SMTP Server (TLS) id 14.3.248.2; Mon, 28 Nov 2016 16:42:36 -0800 Received: from shsmsx103.ccr.corp.intel.com (10.239.4.69) by FMSMSX153.amr.corp.intel.com (10.18.125.6) with Microsoft SMTP Server (TLS) id 14.3.248.2; Mon, 28 Nov 2016 16:42:35 -0800 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.239]) by SHSMSX103.ccr.corp.intel.com ([169.254.4.96]) with mapi id 14.03.0248.002; Tue, 29 Nov 2016 08:42:33 +0800 From: "Fan, Jeff" To: Laszlo Ersek , edk2-devel-01 CC: Igor Mammedov , "Justen, Jordan L" , "Kinney, Michael D" Thread-Topic: [PATCH v3 1/2] UefiCpuPkg/MpInitLib: wait no longer than necessary for initial AP startup Thread-Index: AQHSSXiXRbltNUxV80y8lNE5/jWReqDvH95g Date: Tue, 29 Nov 2016 00:42:33 +0000 Message-ID: <542CF652F8836A4AB8DBFAAD40ED192A4A2EA3FF@shsmsx102.ccr.corp.intel.com> References: <20161128130839.9160-1-lersek@redhat.com> <20161128130839.9160-2-lersek@redhat.com> In-Reply-To: <20161128130839.9160-2-lersek@redhat.com> Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiNjE1NjMwY2QtODFjYy00MDNkLThmZmMtZGE3NTY1NDQ3OTllIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX0lDIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE1LjkuNi42IiwiVHJ1c3RlZExhYmVsSGFzaCI6Imthb21iZW81UE1scHhQTkdGTGRrTXNPR0R0YTQ2dXVCdFZlRFhGR0ZOeGs9In0= x-ctpclassification: CTP_IC x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [PATCH v3 1/2] UefiCpuPkg/MpInitLib: wait no longer than necessary for initial AP startup 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, 29 Nov 2016 00:42:37 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Jeff Fan Thanks! -----Original Message----- From: Laszlo Ersek [mailto:lersek@redhat.com]=20 Sent: Monday, November 28, 2016 9:09 PM To: edk2-devel-01 Cc: Igor Mammedov; Fan, Jeff; Justen, Jordan L; Kinney, Michael D Subject: [PATCH v3 1/2] UefiCpuPkg/MpInitLib: wait no longer than necessary= for initial AP startup Sometimes a platform knows exactly how many CPUs it has at boot. It should = be able to - set PcdCpuMaxLogicalProcessorNumber dynamically to this number, - set PcdCpuApInitTimeOutInMicroSeconds to a very long time (for example MAX_UINT32, approx. 71 minutes), - and expect that MpInitLib wait exactly as long as necessary for all APs to report in. Other platforms should be able to continue setting a reasonably large upper= bound on supported CPUs, and waiting for a reasonable, fixed amount of tim= e for all APs to report in. Add this functionality. The TimedWaitForApFinish() function will return whe= n all APs have reported in, or the timeout has expired -- whichever happens= first. (Accessing these PCDs dynamically is safe. The PEI and DXE phase instances = of this library are restricted to PEIM and DXE_DRIVER client modules, thus = the PCD accesses cannot be linked into runtime code.) Cc: Igor Mammedov Cc: Jeff Fan Cc: Jordan Justen Cc: Michael Kinney Bugzilla: https://bugzilla.tianocore.org/show_bug.cgi?id=3D116 Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek --- Notes: v3: - preserve original behavior for PcdCpuApInitTimeOutInMicroSeconds=3D= =3D0 [Jeff] UefiCpuPkg/Library/MpInitLib/MpLib.c | 73 +++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpIn= itLib/MpLib.c index 15dbfa1e7d6c..ed22ce67782e 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -684,6 +684,21 @@ FillExchangeInfoData ( } =20 /** + Helper function that waits until the finished AP count reaches the=20 + specified limit, or the specified timeout elapses (whichever comes first= ). + + @param[in] CpuMpData Pointer to CPU MP Data. + @param[in] FinishedApLimit The number of finished APs to wait for. + @param[in] TimeLimit The number of microseconds to wait for. +**/ +VOID +TimedWaitForApFinish ( + IN CPU_MP_DATA *CpuMpData, + IN UINT32 FinishedApLimit, + IN UINT32 TimeLimit + ); + +/** This function will be called by BSP to wakeup AP. =20 @param[in] CpuMpData Pointer to CPU MP Data @@ -748,7 +763,11 @@ WakeUpAP ( // // Wait for all potential APs waken up in one specified period // - MicroSecondDelay (PcdGet32(PcdCpuApInitTimeOutInMicroSeconds)); + TimedWaitForApFinish ( + CpuMpData, + PcdGet32 (PcdCpuMaxLogicalProcessorNumber) - 1, + PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds) + ); } else { // // Wait all APs waken up if this is not the 1st broadcast of SIPI @@= -895,6 +914,58 @@ CheckTimeout ( } =20 /** + Helper function that waits until the finished AP count reaches the=20 + specified limit, or the specified timeout elapses (whichever comes first= ). + + @param[in] CpuMpData Pointer to CPU MP Data. + @param[in] FinishedApLimit The number of finished APs to wait for. + @param[in] TimeLimit The number of microseconds to wait for. +**/ +VOID +TimedWaitForApFinish ( + IN CPU_MP_DATA *CpuMpData, + IN UINT32 FinishedApLimit, + IN UINT32 TimeLimit + ) +{ + // + // CalculateTimeout() and CheckTimeout() consider a TimeLimit of 0 + // "infinity", so check for (TimeLimit =3D=3D 0) explicitly. + // + if (TimeLimit =3D=3D 0) { + return; + } + + CpuMpData->TotalTime =3D 0; + CpuMpData->ExpectedTime =3D CalculateTimeout ( + TimeLimit, + &CpuMpData->CurrentTime + ); + while (CpuMpData->FinishedCount < FinishedApLimit && + !CheckTimeout ( + &CpuMpData->CurrentTime, + &CpuMpData->TotalTime, + CpuMpData->ExpectedTime + )) { + CpuPause (); + } + + if (CpuMpData->FinishedCount >=3D FinishedApLimit) { + DEBUG (( + DEBUG_VERBOSE, + "%a: reached FinishedApLimit=3D%u in %Lu microseconds\n", + __FUNCTION__, + FinishedApLimit, + DivU64x64Remainder ( + MultU64x32 (CpuMpData->TotalTime, 1000000), + GetPerformanceCounterProperties (NULL, NULL), + NULL + ) + )); + } +} + +/** Reset an AP to Idle state. =20 Any task being executed by the AP will be aborted and the AP -- 2.9.2