public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Yuanhao Xie" <yuanhao.xie@intel.com>
To: devel@edk2.groups.io
Cc: Gerd Hoffmann <kraxel@redhat.com>,
	Eric Dong <eric.dong@intel.com>, Ray Ni <ray.ni@intel.com>,
	Rahul Kumar <rahul1.kumar@intel.com>,
	Tom Lendacky <thomas.lendacky@amd.com>,
	Yuanhao Xie <yuanhao.xie@intel.com>
Subject: [Patch V2 6/6] UefiCpuPkg: Enhance MpHandOff Handling.
Date: Sun, 25 Jun 2023 22:39:20 +0800	[thread overview]
Message-ID: <20230625143920.57095-7-yuanhao.xie@intel.com> (raw)
In-Reply-To: <20230625143920.57095-1-yuanhao.xie@intel.com>

Enhance MpHandOff Handling for Systems with a Large Number of
Processors.

Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Yuanhao Xie <yuanhao.xie@intel.com>
---
 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


  parent reply	other threads:[~2023-06-25 14:40 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-25 14:39 [Patch V2 0/6] Eliminate the second INIT-SIPI-SIPI sequence Yuanhao Xie
2023-06-25 14:39 ` [Patch V2 1/6] UefiCpuPkg: Refactor the logic for placing APs in HltLoop Yuanhao Xie
2023-06-25 14:39 ` [Patch V2 2/6] UefiCpuPkg: Refactor the logic for placing APs in Mwait/Runloop Yuanhao Xie
2023-06-25 14:39 ` [Patch V2 3/6] UefiCpuPkg: Create MpHandOff Yuanhao Xie
2023-06-26 11:21   ` Gerd Hoffmann
2023-06-26 12:32     ` Yuanhao Xie
2023-06-25 14:39 ` [Patch V2 4/6] UefiCpuPkg: ApWakeupFunction directly use CpuMpData Yuanhao Xie
2023-06-25 14:39 ` [Patch V2 5/6] UefiCpuPkg: Eliminate the second INIT-SIPI-SIPI sequence Yuanhao Xie
2023-06-25 14:39 ` Yuanhao Xie [this message]
2023-06-26  3:14   ` [Patch V2 6/6] UefiCpuPkg: Enhance MpHandOff Handling Ni, Ray
2023-06-26  6:03     ` Yuanhao Xie

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230625143920.57095-7-yuanhao.xie@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox