public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Laszlo Ersek" <lersek@redhat.com>
To: devel@edk2.groups.io, kraxel@redhat.com
Cc: Oliver Steffen <osteffen@redhat.com>, Ray Ni <ray.ni@intel.com>,
	Rahul Kumar <rahul1.kumar@intel.com>
Subject: Re: [edk2-devel] [PATCH 5/5] UefiCpuPkg/MpInitLib: Add support for multiple HOBs to SaveCpuMpData()
Date: Mon, 19 Feb 2024 13:50:05 +0100	[thread overview]
Message-ID: <6a054f43-913d-93a9-02ac-3be81d443761@redhat.com> (raw)
In-Reply-To: <20240215093149.251319-6-kraxel@redhat.com>

On 2/15/24 10:31, Gerd Hoffmann wrote:
> Add support for splitting Hand-Off data into multiple HOBs.  This is
> required for VMs with thousands of CPUs.  The actual CPU count per HOB
> is much smaller (128) for better test coverage.
>
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
>  UefiCpuPkg/Library/MpInitLib/PeiMpLib.c | 48 ++++++++++++++-----------
>  1 file changed, 27 insertions(+), 21 deletions(-)
>
> diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
> index f80e00edcff3..a5710789c8c3 100644
> --- a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
> +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
> @@ -126,35 +126,41 @@ SaveCpuMpData (
>    IN CPU_MP_DATA  *CpuMpData
>    )
>  {
> -  UINT64           Data64;
> -  UINTN            Index;
> -  CPU_INFO_IN_HOB  *CpuInfoInHob;
> -  MP_HAND_OFF      *MpHandOff;
> -  UINTN            MpHandOffSize;
> +  STATIC CONST UINT32  CpusPerHob = 128;

This should be a fixed-at-build PCD. Easy to modify on the build command
line, for test coverage, but for production builds, it should be as
large as possible.

In fact, the code should determine how many CPU entries fit in a single
HOB [*], and the PCD should be checked against it:

- PCD == 0: use the maximum
- PCD > maximum: assert
- otherwise: use the PCD as chunking factor

[*] See BuildGuidHob() in "MdePkg/Library/PeiHobLib/HobLib.c":

|   //
|   // Make sure that data length is not too long.
|   //
|   ASSERT (DataLength <= (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)));

So the max permitted payload size is 0xFFE0 bytes, if I count right.

  CpusPerHob = (0xFFE0 - sizeof (MP_HAND_OFF)) / sizeof (PROCESSOR_HAND_OFF);


> +  UINT64               Data64;
> +  UINT32               Index, HobBase;
> +  CPU_INFO_IN_HOB      *CpuInfoInHob;
> +  MP_HAND_OFF          *MpHandOff;
> +  UINTN                MpHandOffSize;
>
>    //
>    // 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;
> +  CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
>
> -  MpHandOff->CpuCount = CpuMpData->CpuCount;
> -  if (CpuMpData->ApLoopMode != ApInHltLoop) {
> -    MpHandOff->StartupSignalValue    = MP_HAND_OFF_SIGNAL;
> -    MpHandOff->WaitLoopExecutionMode = sizeof (VOID *);
> -  }
> +  for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
> +    if (Index % CpusPerHob == 0) {
> +      MpHandOffSize = sizeof (MP_HAND_OFF) + sizeof (PROCESSOR_HAND_OFF) * CpusPerHob;

I don't like that the last HOB will only be partially filled in, most of
the time. Especially the max chunking factor -- which strives to create
HOBs that are approximately 64KB in size -- might waste ~32KB on
average, using a flat multiplication like the above.

How about:

  UINT32              FreeInHob;
  PROCESSOR_HAND_OFF  *Info;

  FreeInHob = 0;
  for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
    if (FreeInHob == 0) {
      FreeInHob     = MIN (CpusPerHob, CpuMpData->CpuCount - Index);
      MpHandOffSize = sizeof *MpHandOff + FreeInHob * sizeof *Info;
      MpHandOff     = BuildGuidHob (&mMpHandOffGuid, MpHandOffSize);
      ASSERT (MpHandOff != NULL);
      ZeroMem (MpHandOff, MpHandOffSize);
      MpHandOff->ProcessorIndex = Index;
      MpHandOff->CpuCount       = FreeInHob;
      Info                      = MpHandOff->Info;
    }

    Info->ApicId = CpuInfoInHob[Index].ApicId;
    Info->Health = CpuInfoInHob[Index].Health;
    if (CpuMpData->ApLoopMode != ApInHltLoop) {
      Info->StartupSignalAddress    = (UINT64)(UINTN)CpuMpData->CpuData[Index].StartupApSignal;
      Info->StartupProcedureAddress = (UINT64)(UINTN)&CpuMpData->CpuData[Index].ApFunction;
    }

    Info++;
    FreeInHob--;
  }

And then "HobBase" becomes superfluous. (Well, having a HobBase that
carries information between iterations of the loop, versus an Info
pointer, is conceptually the same; it's just that the Info pointer
allows for shorter expressions.)

The UINTN -> UINT32 type change for Index looks fine, however.

> +      MpHandOff     = (MP_HAND_OFF *)BuildGuidHob (&mMpHandOffGuid, MpHandOffSize);
> +      ASSERT (MpHandOff != NULL);
> +      ZeroMem (MpHandOff, MpHandOffSize);
>
> -  for (Index = 0; Index < MpHandOff->CpuCount; Index++) {
> -    MpHandOff->Info[Index].ApicId = CpuInfoInHob[Index].ApicId;
> -    MpHandOff->Info[Index].Health = CpuInfoInHob[Index].Health;
> +      HobBase                   = Index;
> +      MpHandOff->ProcessorIndex = HobBase;
> +      MpHandOff->CpuCount       = MIN (CpuMpData->CpuCount - HobBase, CpusPerHob);

Yes, the MIN() here is my key point, but I think we should also let it
control the allocation!

> +
> +      if (CpuMpData->ApLoopMode != ApInHltLoop) {
> +        MpHandOff->StartupSignalValue    = MP_HAND_OFF_SIGNAL;
> +        MpHandOff->WaitLoopExecutionMode = sizeof (VOID *);
> +      }
> +    }

As noted elsewhere, these fields don't belong in the loop (they don't
belong to MP_HAND_OFF, going forward); the two of them together should
form a new singleton structure.

> +
> +    MpHandOff->Info[Index-HobBase].ApicId = CpuInfoInHob[Index].ApicId;
> +    MpHandOff->Info[Index-HobBase].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->Info[Index-HobBase].StartupSignalAddress    = (UINT64)(UINTN)CpuMpData->CpuData[Index].StartupApSignal;
> +      MpHandOff->Info[Index-HobBase].StartupProcedureAddress = (UINT64)(UINTN)&CpuMpData->CpuData[Index].ApFunction;
>      }
>    }
>

Laszlo



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#115595): https://edk2.groups.io/g/devel/message/115595
Mute This Topic: https://groups.io/mt/104369848/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



  parent reply	other threads:[~2024-02-19 12:50 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-15  9:31 [edk2-devel] [PATCH 0/5] UefiCpuPkg/MpInitLib: Add support for multiple MP_HAND_OFF HOBs Gerd Hoffmann
2024-02-15  9:31 ` [edk2-devel] [PATCH 1/5] UefiCpuPkg/MpInitLib: Add ProcessorIndex argument to GetMpHandOffHob() Gerd Hoffmann
2024-02-19  2:34   ` Ni, Ray
2024-02-19  9:51     ` Gerd Hoffmann
2024-02-20  3:42       ` Ni, Ray
2024-02-19 11:18   ` Laszlo Ersek
2024-02-15  9:31 ` [edk2-devel] [PATCH 2/5] UefiCpuPkg/MpInitLib: Add support for multiple HOBs to GetBspNumber() Gerd Hoffmann
2024-02-19  2:41   ` Ni, Ray
2024-02-19 11:18   ` Laszlo Ersek
2024-02-19 11:37     ` Gerd Hoffmann
2024-02-19 20:02       ` Laszlo Ersek
2024-02-15  9:31 ` [edk2-devel] [PATCH 3/5] UefiCpuPkg/MpInitLib: Add support for multiple HOBs to SwitchApContext() Gerd Hoffmann
2024-02-19  2:43   ` Ni, Ray
2024-02-19 11:25   ` Laszlo Ersek
2024-02-15  9:31 ` [edk2-devel] [PATCH 4/5] UefiCpuPkg/MpInitLib: Add support for multiple HOBs to MpInitLibInitialize Gerd Hoffmann
2024-02-19  2:57   ` Ni, Ray
2024-02-19 11:56   ` Laszlo Ersek
2024-02-15  9:31 ` [edk2-devel] [PATCH 5/5] UefiCpuPkg/MpInitLib: Add support for multiple HOBs to SaveCpuMpData() Gerd Hoffmann
2024-02-19  3:02   ` Ni, Ray
2024-02-19 12:50   ` Laszlo Ersek [this message]
2024-02-20  7:35     ` Ni, Ray

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=6a054f43-913d-93a9-02ac-3be81d443761@redhat.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