From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by mx.groups.io with SMTP id smtpd.web08.15919.1667453877740586469 for ; Wed, 02 Nov 2022 22:38:05 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=KMgM0fnN; spf=pass (domain: intel.com, ip: 192.55.52.93, 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=1667453885; x=1698989885; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=xVDw1l/BWoJWRTf+lVtCYYypHVkGkhElxq41P0Ak3m4=; b=KMgM0fnNfPE/+dACJ82EME9c3HjXQMXuRESIjkZAEVwlSyosB6xva9BB do4++m/3ypFCVzSOzAUdfCbmyCjZES+yzKiBDi1ZUCb0Mq9hNiCjI3nOB G55xGZ9Y65yIQJzOHvPMK/1BMj/T8ooTOQxyS5ANlJWIs8LfTQcYzpV2r 4cr7URaPtzyjAHhDOoU46/3hjq3WLkmgFzm/Nh7V7UdLnEYNen034k/U0 ydKAi3qFuKudgrEx0oU5/aZC0Z4aKUo8IPrbDKstW0OQqlxvit472pefH LEUpNMxHIYJM0eBYKjQ8+7qpG6izo049zBX1WYcOJs6USnZZlEIqTEdec w==; X-IronPort-AV: E=McAfee;i="6500,9779,10519"; a="307207609" X-IronPort-AV: E=Sophos;i="5.95,235,1661842800"; d="scan'208";a="307207609" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Nov 2022 22:38:05 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10519"; a="963805724" X-IronPort-AV: E=Sophos;i="5.95,235,1661842800"; d="scan'208";a="963805724" Received: from shwdeopenlab705.ccr.corp.intel.com ([10.239.56.33]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Nov 2022 22:38:03 -0700 From: "Yuanhao Xie" To: devel@edk2.groups.io Cc: Yuanhao , Eric Dong , Rahul Kumar , Ray Ni Subject: [PATCH 2/3] UefiCpuPkg: Skip Mp initialization in DXE phase Date: Thu, 3 Nov 2022 13:37:46 +0800 Message-Id: <20221103053747.289-3-yuanhao.xie@intel.com> X-Mailer: git-send-email 2.36.1.windows.1 In-Reply-To: <20221103053747.289-1-yuanhao.xie@intel.com> References: <20221103053747.289-1-yuanhao.xie@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Yuanhao If PEI and DXE stages are in the same bit mode, Mp initialization is removed in DXE phase. Signed-off-by: Yuanhao Xie Cc: Eric Dong Cc: Rahul Kumar Cc: Ray Ni --- UefiCpuPkg/Library/MpInitLib/MpLib.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------- UefiCpuPkg/Library/MpInitLib/MpLib.h | 1 + 2 files changed, 90 insertions(+), 39 deletions(-) diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c index 5430688946..c7d1e58909 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -1842,12 +1842,36 @@ MpInitLibInitialize ( UINTN ApResetVectorSizeAbove1Mb; UINTN BackupBufferAddr; UINTN ApIdtBase; + BOOLEAN FirstTimeMpInitializing; - OldCpuMpData = GetCpuMpDataFromGuidedHob (); - if (OldCpuMpData == NULL) { + OldCpuMpData = GetCpuMpDataFromGuidedHob (); + FirstTimeMpInitializing = (BOOLEAN)(OldCpuMpData == NULL); + + if (FirstTimeMpInitializing) { MaxLogicalProcessorNumber = PcdGet32 (PcdCpuMaxLogicalProcessorNumber); + // + // The first time Mp is initialized, or the saved CpuMpData is lost, the + // complete process including preparing the buffer, filling the CpuMpData, + // loading the microcode, and waking up the Aps needs to be performed. + // } else { MaxLogicalProcessorNumber = OldCpuMpData->CpuCount; + // + // If both PEI and DXE phases are 64-bit, CpuMpdata collected in PEI stage + // can be reused in DXE stage, thus no need to redo the initialization. + // For the case where DXE is 64-bit and PEI is 32-bit, a partial + // initialization of Mp is required. + // + if (OldCpuMpData->SizeOfUINTN == sizeof (UINTN)) { + DEBUG ((DEBUG_INFO, "OldCpuMpData->SizeOfUINTN: %04d, sizeof (UINTN): %04d\n", OldCpuMpData->SizeOfUINTN, sizeof (UINTN))); + + OldCpuMpData->NewCpuMpData = OldCpuMpData; + // + // Initialize global data for MP support + // + InitMpGlobalData (OldCpuMpData); + return EFI_SUCCESS; + } } ASSERT (MaxLogicalProcessorNumber != 0); @@ -1991,7 +2015,7 @@ MpInitLibInitialize ( // ProgramVirtualWireMode (); - if (OldCpuMpData == NULL) { + if (FirstTimeMpInitializing) { if (MaxLogicalProcessorNumber > 1) { // // Wakeup all APs and calculate the processor count in system @@ -2015,58 +2039,84 @@ MpInitLibInitialize ( // Detect and apply Microcode on BSP // MicrocodeDetect (CpuMpData, CpuMpData->BspNumber); + + // + // CpuMpData->CpuCount was updated in CollectProcessorCount() + // during the first time Mp Initialization. + // + if (CpuMpData->CpuCount > 1) { + WakeUpAP (CpuMpData, TRUE, 0, ApInitializeSync, CpuMpData, TRUE); + // + // Wait for all APs to complete initialization. + // + while (CpuMpData->FinishedCount < (CpuMpData->CpuCount - 1)) { + CpuPause (); + } + } + // + // After Mp is initialized, sizeof(UINTN) is saved and will be transferred to DXE. + // It is used to decide whether Mp initialization needs to be done again. + // SizeOfUINTN and other fields (CpuInfoInHob, CpuCount, BspNumber) declared at the top of + // the CPU_MP_DATA structure are independent of the bit mode( 32 or 64). + // + CpuMpData->SizeOfUINTN = sizeof (UINTN); } else { // - // APs have been wakeup before, just get the CPU Information - // from HOB + // For the else case where DXE is 64-bit and PEI is 32-bit, a partial + // initialization of Mp is required. // + OldCpuMpData->NewCpuMpData = CpuMpData; - CpuMpData->CpuCount = OldCpuMpData->CpuCount; - CpuMpData->BspNumber = OldCpuMpData->BspNumber; - CpuMpData->CpuInfoInHob = OldCpuMpData->CpuInfoInHob; - CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob; + // + // CpuCount, BspNumber, CpuInfoInHob as well as SizeOfUINTN are collected during PEI, + // and need to be saved in HOB for DXE. The rest fields of _CPU_MP_DATA is more like the temporary field. + // They will be updated during DXE if the DXE mode is different from PEI. + // + CpuMpData->CpuCount = OldCpuMpData->CpuCount; + CpuMpData->BspNumber = OldCpuMpData->BspNumber; + CpuMpData->CpuInfoInHob = OldCpuMpData->CpuInfoInHob; + CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob; for (Index = 0; Index < CpuMpData->CpuCount; Index++) { + // + // In PEI phase, or for first time initialization, initializeSpinLock is + // performed during CollectProcessorCount(). In DXE phase, it is done during traversal here. + // InitializeSpinLock (&CpuMpData->CpuData[Index].ApLock); CpuMpData->CpuData[Index].CpuHealthy = (CpuInfoInHob[Index].Health == 0) ? TRUE : FALSE; CpuMpData->CpuData[Index].ApFunction = 0; } - } - // - // Store BSP's MTRR setting - // - MtrrGetAllMtrrs (&CpuMpData->MtrrTable); - - // - // Wakeup APs to do some AP initialize sync (Microcode & MTRR) - // - if (CpuMpData->CpuCount > 1) { - if (OldCpuMpData != NULL) { - // - // Only needs to use this flag for DXE phase to update the wake up - // buffer. Wakeup buffer allocated in PEI phase is no longer valid - // in DXE. - // - CpuMpData->InitFlag = ApInitReconfig; - WakeUpAP (CpuMpData, TRUE, 0, ApMtrrSync, CpuMpData, TRUE); - } else { - WakeUpAP (CpuMpData, TRUE, 0, ApInitializeSync, CpuMpData, TRUE); - } + // + // Store BSP's MTRR setting + // + MtrrGetAllMtrrs (&CpuMpData->MtrrTable); // - // Wait for all APs finished initialization + // Wakeup APs to do some AP initialize sync (Microcode & MTRR) // - while (CpuMpData->FinishedCount < (CpuMpData->CpuCount - 1)) { - CpuPause (); - } + if (CpuMpData->CpuCount > 1) { + if (OldCpuMpData != NULL) { + // + // Only needs to use this flag for DXE phase to update the wake up + // buffer. Wakeup buffer allocated in PEI phase is no longer valid + // in DXE. + // + CpuMpData->InitFlag = ApInitReconfig; + WakeUpAP (CpuMpData, TRUE, 0, ApMtrrSync, CpuMpData, TRUE); + // + // Wait for all APs to complete initialization. + // + while (CpuMpData->FinishedCount < (CpuMpData->CpuCount - 1)) { + CpuPause (); + } - if (OldCpuMpData != NULL) { - CpuMpData->InitFlag = ApInitDone; + CpuMpData->InitFlag = ApInitDone; + } } + } - for (Index = 0; Index < CpuMpData->CpuCount; Index++) { - SetApState (&CpuMpData->CpuData[Index], CpuStateIdle); - } + for (Index = 0; Index < CpuMpData->CpuCount; Index++) { + SetApState (&CpuMpData->CpuData[Index], CpuStateIdle); } // diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index f5086e497e..d6a416b943 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -235,6 +235,7 @@ struct _CPU_MP_DATA { UINT64 CpuInfoInHob; UINT32 CpuCount; UINT32 BspNumber; + UINT32 SizeOfUINTN; // // The above fields data will be passed from PEI to DXE // Please make sure the fields offset same in the different -- 2.36.1.windows.1