From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by mx.groups.io with SMTP id smtpd.web11.12343.1687704019653525203 for ; Sun, 25 Jun 2023 07:40:20 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=dbePB4j+; spf=pass (domain: intel.com, ip: 134.134.136.24, mailfrom: yuanhao.xie@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1687704019; x=1719240019; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=2Z+zy1JTn3tP/0rjQpY1f9T2aiz3JIBQscPkE20pB30=; b=dbePB4j+jpJPOjnSyBK3ZKuabz4X94xzzsgmFUb6hW7UUKQRMdiCW/Ya IXNHMXrWf1l+1wQHEJzsB20KPpB1glFl8GvDOsk7AxfB02Glo9kn0K94b jouUzMS1o8TlvSQKwlYPb0wjRybW5rEjheRROHHCMfOOWJCBNnZiBa38k afyibT44jH+DUKAE+jjnwOKEtwPuOH+ab5z9BiFo5RrnFbwzTJsDxAxDO 9CuHtotYkGIM7yab6z7qquMrXTWaHnC7d7t1oRAVoGIM/9dhLuNdq8egx ERIsVom4/z917KEwwh8Xam5WV/cPQZN2W9t5pMVgfh+OPA5VkeYK3Hq+M A==; X-IronPort-AV: E=McAfee;i="6600,9927,10752"; a="363624393" X-IronPort-AV: E=Sophos;i="6.01,157,1684825200"; d="scan'208";a="363624393" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jun 2023 07:39:51 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10752"; a="785871869" X-IronPort-AV: E=Sophos;i="6.01,157,1684825200"; d="scan'208";a="785871869" Received: from shwdeopenlab705.ccr.corp.intel.com ([10.239.55.55]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Jun 2023 07:39:49 -0700 From: "Yuanhao Xie" To: devel@edk2.groups.io Cc: Gerd Hoffmann , Eric Dong , Ray Ni , Rahul Kumar , Tom Lendacky , Yuanhao Xie Subject: [Patch V2 6/6] UefiCpuPkg: Enhance MpHandOff Handling. Date: Sun, 25 Jun 2023 22:39:20 +0800 Message-Id: <20230625143920.57095-7-yuanhao.xie@intel.com> X-Mailer: git-send-email 2.36.1.windows.1 In-Reply-To: <20230625143920.57095-1-yuanhao.xie@intel.com> References: <20230625143920.57095-1-yuanhao.xie@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Enhance MpHandOff Handling for Systems with a Large Number of Processors. Cc: Gerd Hoffmann Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar Cc: Tom Lendacky Signed-off-by: Yuanhao Xie --- UefiCpuPkg/Library/MpInitLib/MpLib.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------ UefiCpuPkg/Library/MpInitLib/MpLib.h | 22 +++++++++------------- UefiCpuPkg/Library/MpInitLib/PeiMpLib.c | 56 +++++++++++++++++++++++++++++++++++++++----------------- 3 files changed, 116 insertions(+), 90 deletions(-) diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c index 391e6f19ef..087bf3ea92 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -1528,32 +1528,48 @@ SwitchContextPerAp ( This procedure allows the AP to switch to another section of memory and continue its loop there. - @param[in] MpHandOff Pointer to MP hand-off data structure. + @param[in] BspNumber Bsp Number **/ VOID SwitchApContext ( - IN MP_HAND_OFF *MpHandOff + IN UINT32 BspNumber ) { - UINTN Index; - UINT32 BspNumber; - - BspNumber = GetBspNumber (MpHandOff); + UINTN Index; + UINTN LimitationOfMpHandOffHob; + UINTN NumberOfProcessorsInCurrentHob; + UINTN CpuCountInCurrentHob; + MP_HAND_OFF *MpHandOff; + BOOLEAN BspFound; + + BspFound = FALSE; + + MpHandOff = GetMpHandOffHob (); + CpuCountInCurrentHob = 0; + LimitationOfMpHandOffHob = (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE) - sizeof (MP_HAND_OFF)) / sizeof (PROCESSOR_HAND_OFF); + while (CpuCountInCurrentHob < MpHandOff->CpuCount) { + // + // Get the processor number for the BSP + // + NumberOfProcessorsInCurrentHob = MIN (MpHandOff->CpuCount - CpuCountInCurrentHob, LimitationOfMpHandOffHob); - for (Index = 0; Index < MpHandOff->CpuCount; Index++) { - if (Index != BspNumber) { - *(UINTN *)(UINTN)MpHandOff->Info[Index].StartupProcedureAddress = (UINTN)SwitchContextPerAp; - *(UINT32 *)(UINTN)MpHandOff->Info[Index].StartupSignalAddress = MpHandOff->StartupSignalValue; + for (Index = 0; Index < NumberOfProcessorsInCurrentHob; Index++) { + if ((Index == BspNumber) && (BspFound == FALSE)) { + BspFound = TRUE; + } else { + *(UINTN *)(UINTN)MpHandOff->Info[Index].StartupProcedureAddress = (UINTN)SwitchContextPerAp; + *(UINT32 *)(UINTN)MpHandOff->Info[Index].StartupSignalAddress = MpHandOff->StartupSignalValue; + WaitApWakeup ((UINT32 *)(UINTN)(MpHandOff->Info[Index].StartupSignalAddress)); + } } - } - // - // Wait all APs waken up if this is not the 1st broadcast of SIPI - // - for (Index = 0; Index < MpHandOff->CpuCount; Index++) { - if (Index != BspNumber) { - WaitApWakeup ((UINT32 *)(UINTN)(MpHandOff->Info[Index].StartupSignalAddress)); + if (CpuCountInCurrentHob + NumberOfProcessorsInCurrentHob >= MpHandOff->CpuCount) { + break; } + + MpHandOff = (MP_HAND_OFF *)((UINT8 *)MpHandOff + sizeof (MP_HAND_OFF) + sizeof (EFI_HOB_GUID_TYPE) + sizeof (PROCESSOR_HAND_OFF) * NumberOfProcessorsInCurrentHob); + + CpuCountInCurrentHob += NumberOfProcessorsInCurrentHob; } } @@ -1909,37 +1925,6 @@ CheckAllAPs ( return EFI_NOT_READY; } -/** - This function Get BspNumber. - - @param[in] MpHandOff Pointer to MpHandOff - @return BspNumber -**/ -UINT32 -GetBspNumber ( - IN CONST MP_HAND_OFF *MpHandOff - ) -{ - UINT32 ApicId; - UINT32 BspNumber; - UINT32 Index; - - // - // Get the processor number for the BSP - // - BspNumber = MAX_UINT32; - ApicId = GetInitialApicId (); - for (Index = 0; Index < MpHandOff->CpuCount; Index++) { - if (MpHandOff->Info[Index].ApicId == ApicId) { - BspNumber = Index; - } - } - - ASSERT (BspNumber != MAX_UINT32); - - return BspNumber; -} - /** Get pointer to CPU MP Data structure from GUIDed HOB. @@ -1994,8 +1979,13 @@ MpInitLibInitialize ( UINTN ApResetVectorSizeAbove1Mb; UINTN BackupBufferAddr; UINTN ApIdtBase; + UINTN LimitationOfMpHandOffHob; + UINTN NumberOfProcessorsInCurrentHob; + UINTN ProcessedCpuCount; + UINTN CurrentProcessorIndex; MpHandOff = GetMpHandOffHob (); + if (MpHandOff == NULL) { MaxLogicalProcessorNumber = PcdGet32 (PcdCpuMaxLogicalProcessorNumber); } else { @@ -2156,17 +2146,35 @@ MpInitLibInitialize ( // from HOB // AmdSevUpdateCpuMpData (CpuMpData); - CpuMpData->CpuCount = MpHandOff->CpuCount; - CpuMpData->BspNumber = GetBspNumber (MpHandOff); - CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob; - for (Index = 0; Index < CpuMpData->CpuCount; Index++) { - InitializeSpinLock (&CpuMpData->CpuData[Index].ApLock); - CpuMpData->CpuData[Index].CpuHealthy = (MpHandOff->Info[Index].Health == 0) ? TRUE : FALSE; - CpuMpData->CpuData[Index].ApFunction = 0; - CpuInfoInHob[Index].InitialApicId = MpHandOff->Info[Index].ApicId; - CpuInfoInHob[Index].ApTopOfStack = CpuMpData->Buffer + (Index + 1) * CpuMpData->CpuApStackSize; - CpuInfoInHob[Index].ApicId = MpHandOff->Info[Index].ApicId; - CpuInfoInHob[Index].Health = MpHandOff->Info[Index].Health; + CpuMpData->CpuCount = MpHandOff->CpuCount; + CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob; + + LimitationOfMpHandOffHob = (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE) - sizeof (MP_HAND_OFF)) / sizeof (PROCESSOR_HAND_OFF); + ProcessedCpuCount = 0; + while (ProcessedCpuCount < MpHandOff->CpuCount) { + NumberOfProcessorsInCurrentHob = MIN (MpHandOff->CpuCount - ProcessedCpuCount, LimitationOfMpHandOffHob); + + for (Index = 0; Index < NumberOfProcessorsInCurrentHob; Index++) { + CurrentProcessorIndex = Index+MpHandOff->ProcessorIndex; + if (MpHandOff->Info[Index].ApicId == GetInitialApicId ()) { + CpuMpData->BspNumber = (UINT32)Index; + } + + InitializeSpinLock (&CpuMpData->CpuData[CurrentProcessorIndex].ApLock); + CpuMpData->CpuData[CurrentProcessorIndex].CpuHealthy = (MpHandOff->Info[Index].Health == 0) ? TRUE : FALSE; + CpuMpData->CpuData[CurrentProcessorIndex].ApFunction = 0; + CpuInfoInHob[CurrentProcessorIndex].InitialApicId = MpHandOff->Info[Index].ApicId; + CpuInfoInHob[CurrentProcessorIndex].ApTopOfStack = CpuMpData->Buffer + (Index + 1) * CpuMpData->CpuApStackSize; + CpuInfoInHob[CurrentProcessorIndex].ApicId = MpHandOff->Info[Index].ApicId; + CpuInfoInHob[CurrentProcessorIndex].Health = MpHandOff->Info[Index].Health; + } + + if (ProcessedCpuCount+NumberOfProcessorsInCurrentHob >= MpHandOff->CpuCount) { + break; + } + + MpHandOff = (MP_HAND_OFF *)((UINT8 *)MpHandOff + sizeof (MP_HAND_OFF) + sizeof (EFI_HOB_GUID_TYPE) + sizeof (PROCESSOR_HAND_OFF) * NumberOfProcessorsInCurrentHob); + ProcessedCpuCount += NumberOfProcessorsInCurrentHob; } DEBUG ((DEBUG_INFO, "MpHandOff->WaitLoopExecutionMode: %04d, sizeof (VOID *): %04d\n", MpHandOff->WaitLoopExecutionMode, sizeof (VOID *))); @@ -2183,7 +2191,7 @@ MpInitLibInitialize ( CpuMpData->FinishedCount = 0; CpuMpData->InitFlag = ApInitDone; SaveCpuMpData (CpuMpData); - SwitchApContext (MpHandOff); + SwitchApContext (CpuMpData->BspNumber); ASSERT (CpuMpData->FinishedCount == (CpuMpData->CpuCount - 1)); // diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index 468d3a5925..6af635a80c 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -497,17 +497,6 @@ SaveCpuMpData ( IN CPU_MP_DATA *CpuMpData ); -/** - This function Get BspNumber. - - @param[in] MpHandOff Pointer to MpHandOff - @return BspNumber -**/ -UINT32 -GetBspNumber ( - IN CONST MP_HAND_OFF *MpHandOff - ); - /** Get available system memory below 1MB by specified size. @@ -522,12 +511,19 @@ GetWakeupBuffer ( ); /** - Switch Context for each AP. + This function is intended to be invoked by the BSP in order + to wake up the AP. The BSP accomplishes this by triggering a + start-up signal, which in turn causes any APs that are + currently in a loop on the PEI-prepared memory to awaken and + begin running the procedure called SwitchContextPerAp. + This procedure allows the AP to switch to another section of + memory and continue its loop there. + @param[in] BspNumber Bsp Number **/ VOID SwitchApContext ( - IN MP_HAND_OFF *MpHandOff + IN UINT32 BspNumber ); /** diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c index f80e00edcf..18f83d9ed5 100644 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c @@ -131,31 +131,53 @@ SaveCpuMpData ( CPU_INFO_IN_HOB *CpuInfoInHob; MP_HAND_OFF *MpHandOff; UINTN MpHandOffSize; + UINT32 LimitationOfMpHandOffHob; + UINT32 NumberOfProcessorsInCurrentHob; + UINT32 ProcessedCpuCount; + UINTN CurrentProcessorIndex; // // When APs are in a state that can be waken up by a store operation to a memory address, // report the MP_HAND_OFF data for DXE to use. // - CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob; - MpHandOffSize = sizeof (MP_HAND_OFF) + sizeof (PROCESSOR_HAND_OFF) * CpuMpData->CpuCount; - MpHandOff = (MP_HAND_OFF *)BuildGuidHob (&mMpHandOffGuid, MpHandOffSize); - ASSERT (MpHandOff != NULL); - ZeroMem (MpHandOff, MpHandOffSize); - MpHandOff->ProcessorIndex = 0; - - MpHandOff->CpuCount = CpuMpData->CpuCount; - if (CpuMpData->ApLoopMode != ApInHltLoop) { - MpHandOff->StartupSignalValue = MP_HAND_OFF_SIGNAL; - MpHandOff->WaitLoopExecutionMode = sizeof (VOID *); - } + CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob; + // + // Maximum number of processor could be saved in the HOB. + // + LimitationOfMpHandOffHob = (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE) - sizeof (MP_HAND_OFF)) / sizeof (PROCESSOR_HAND_OFF); + ProcessedCpuCount = 0; + while (ProcessedCpuCount < CpuMpData->CpuCount) { + NumberOfProcessorsInCurrentHob = MIN ((UINT32)CpuMpData->CpuCount - ProcessedCpuCount, LimitationOfMpHandOffHob); + MpHandOffSize = sizeof (MP_HAND_OFF) + sizeof (PROCESSOR_HAND_OFF) * NumberOfProcessorsInCurrentHob; + MpHandOff = (MP_HAND_OFF *)BuildGuidHob ( + &mMpHandOffGuid, + MpHandOffSize + ); + ASSERT (MpHandOff != NULL); + ZeroMem (MpHandOff, MpHandOffSize); + // + // Each individual processor can be uniquely identified by + // combining the processorIndex with the mMpHandOffGuid. + // + MpHandOff->ProcessorIndex = ProcessedCpuCount; + MpHandOff->CpuCount = CpuMpData->CpuCount; - for (Index = 0; Index < MpHandOff->CpuCount; Index++) { - MpHandOff->Info[Index].ApicId = CpuInfoInHob[Index].ApicId; - MpHandOff->Info[Index].Health = CpuInfoInHob[Index].Health; if (CpuMpData->ApLoopMode != ApInHltLoop) { - MpHandOff->Info[Index].StartupSignalAddress = (UINT64)(UINTN)CpuMpData->CpuData[Index].StartupApSignal; - MpHandOff->Info[Index].StartupProcedureAddress = (UINT64)(UINTN)&CpuMpData->CpuData[Index].ApFunction; + MpHandOff->StartupSignalValue = MP_HAND_OFF_SIGNAL; + MpHandOff->WaitLoopExecutionMode = sizeof (VOID *); } + + for (Index = MpHandOff->ProcessorIndex; Index < NumberOfProcessorsInCurrentHob + MpHandOff->ProcessorIndex; Index++) { + CurrentProcessorIndex = Index-MpHandOff->ProcessorIndex; + MpHandOff->Info[CurrentProcessorIndex].ApicId = CpuInfoInHob[Index].ApicId; + MpHandOff->Info[CurrentProcessorIndex].Health = CpuInfoInHob[Index].Health; + if (CpuMpData->ApLoopMode != ApInHltLoop) { + MpHandOff->Info[CurrentProcessorIndex].StartupSignalAddress = (UINT64)(UINTN)CpuMpData->CpuData[Index].StartupApSignal; + MpHandOff->Info[CurrentProcessorIndex].StartupProcedureAddress = (UINT64)(UINTN)&CpuMpData->CpuData[Index].ApFunction; + } + } + + ProcessedCpuCount += LimitationOfMpHandOffHob; } // -- 2.36.1.windows.1