From: "Ni, Ray" <ray.ni@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
"Dong, Eric" <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Subject: Re: [edk2-devel] [PATCH v3 1/2] UefiCpuPkg/PiSmmCpuDxeSmm: Remove dependence between APs
Date: Tue, 24 Dec 2019 02:44:00 +0000 [thread overview]
Message-ID: <734D49CCEBEEF84792F5B80ED585239D5C3A9DBF@SHSMSX104.ccr.corp.intel.com> (raw)
In-Reply-To: <20191223081037.1565-2-eric.dong@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Dong,
> Eric
> Sent: Monday, December 23, 2019 4:11 PM
> To: devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Laszlo Ersek <lersek@redhat.com>
> Subject: [edk2-devel] [PATCH v3 1/2] UefiCpuPkg/PiSmmCpuDxeSmm:
> Remove dependence between APs
>
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2268
>
> In current implementation, when check whether APs called by StartUpAllAPs
> or StartUpThisAp, it checks the Tokens value used by other APs. Also the AP
> will update the Token value for itself if its task finished. In this
> case, the potential race condition issues happens for the tokens.
> Because of this, system may trig ASSERT during cycling test.
>
> This change enhance the code logic, add new attributes for the token to
> remove the reference for the tokens belongs to other APs.
>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Signed-off-by: Eric Dong <eric.dong@intel.com>
> ---
> UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c | 125 +++++++--------------
> UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h | 5 +-
> 2 files changed, 45 insertions(+), 85 deletions(-)
>
> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
> b/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
> index 757f1056f7..35951cc43e 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
> @@ -402,38 +402,6 @@ IsPresentAp (
> *(mSmmMpSyncData->CpuData[CpuIndex].Present));
>
> }
>
>
>
> -/**
>
> - Check whether execute in single AP or all APs.
>
> -
>
> - Compare two Tokens used by different APs to know whether in StartAllAps
> call.
>
> -
>
> - Whether is an valid AP base on AP's Present flag.
>
> -
>
> - @retval TRUE IN StartAllAps call.
>
> - @retval FALSE Not in StartAllAps call.
>
> -
>
> -**/
>
> -BOOLEAN
>
> -InStartAllApsCall (
>
> - VOID
>
> - )
>
> -{
>
> - UINTN ApIndex;
>
> - UINTN ApIndex2;
>
> -
>
> - for (ApIndex = mMaxNumberOfCpus; ApIndex-- > 0;) {
>
> - if (IsPresentAp (ApIndex) && (mSmmMpSyncData-
> >CpuData[ApIndex].Token != NULL)) {
>
> - for (ApIndex2 = ApIndex; ApIndex2-- > 0;) {
>
> - if (IsPresentAp (ApIndex2) && (mSmmMpSyncData-
> >CpuData[ApIndex2].Token != NULL)) {
>
> - return mSmmMpSyncData->CpuData[ApIndex2].Token ==
> mSmmMpSyncData->CpuData[ApIndex].Token;
>
> - }
>
> - }
>
> - }
>
> - }
>
> -
>
> - return FALSE;
>
> -}
>
> -
>
> /**
>
> Clean up the status flags used during executing the procedure.
>
>
>
> @@ -445,40 +413,15 @@ ReleaseToken (
> IN UINTN CpuIndex
>
> )
>
> {
>
> - UINTN Index;
>
> - BOOLEAN Released;
>
> + PROCEDURE_TOKEN *Token;
>
>
>
> - if (InStartAllApsCall ()) {
>
> - //
>
> - // In Start All APs mode, make sure all APs have finished task.
>
> - //
>
> - if (WaitForAllAPsNotBusy (FALSE)) {
>
> - //
>
> - // Clean the flags update in the function call.
>
> - //
>
> - Released = FALSE;
>
> - for (Index = mMaxNumberOfCpus; Index-- > 0;) {
>
> - //
>
> - // Only In SMM APs need to be clean up.
>
> - //
>
> - if (mSmmMpSyncData->CpuData[Index].Present &&
> mSmmMpSyncData->CpuData[Index].Token != NULL) {
>
> - if (!Released) {
>
> - ReleaseSpinLock (mSmmMpSyncData->CpuData[Index].Token);
>
> - Released = TRUE;
>
> - }
>
> - mSmmMpSyncData->CpuData[Index].Token = NULL;
>
> - }
>
> - }
>
> - }
>
> - } else {
>
> - //
>
> - // In single AP mode.
>
> - //
>
> - if (mSmmMpSyncData->CpuData[CpuIndex].Token != NULL) {
>
> - ReleaseSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Token);
>
> - mSmmMpSyncData->CpuData[CpuIndex].Token = NULL;
>
> - }
>
> + Token = mSmmMpSyncData->CpuData[CpuIndex].Token;
>
> +
>
> + if (InterlockedDecrement (&Token->RunningApCount) == 0) {
>
> + ReleaseSpinLock (Token->SpinLock);
>
> }
>
> +
>
> + mSmmMpSyncData->CpuData[CpuIndex].Token = NULL;
>
> }
>
>
>
> /**
>
> @@ -912,12 +855,14 @@ APHandler (
> *mSmmMpSyncData->CpuData[CpuIndex].Status = ProcedureStatus;
>
> }
>
>
>
> + if (mSmmMpSyncData->CpuData[CpuIndex].Token != NULL) {
>
> + ReleaseToken (CpuIndex);
>
> + }
>
> +
>
> //
>
> // Release BUSY
>
> //
>
> ReleaseSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy);
>
> -
>
> - ReleaseToken (CpuIndex);
>
> }
>
>
>
> if (SmmCpuFeaturesNeedConfigureMtrrs()) {
>
> @@ -1111,7 +1056,7 @@ IsTokenInUse (
> while (!IsNull (&gSmmCpuPrivate->TokenList, Link)) {
>
> ProcToken = PROCEDURE_TOKEN_FROM_LINK (Link);
>
>
>
> - if (ProcToken->ProcedureToken == Token) {
>
> + if (ProcToken->SpinLock == Token) {
>
> return TRUE;
>
> }
>
>
>
> @@ -1124,16 +1069,18 @@ IsTokenInUse (
> /**
>
> create token and save it to the maintain list.
>
>
>
> + @param RunningApCount Input running AP count.
>
> +
>
> @retval return the spin lock used as token.
>
>
>
> **/
>
> -SPIN_LOCK *
>
> +PROCEDURE_TOKEN *
>
> CreateToken (
>
> - VOID
>
> + IN UINT32 RunningApCount
>
> )
>
> {
>
> PROCEDURE_TOKEN *ProcToken;
>
> - SPIN_LOCK *CpuToken;
>
> + SPIN_LOCK *SpinLock;
>
> UINTN SpinLockSize;
>
> TOKEN_BUFFER *TokenBuf;
>
> UINT32 TokenCountPerChunk;
>
> @@ -1160,20 +1107,21 @@ CreateToken (
> gSmmCpuPrivate->UsedTokenNum = 0;
>
> }
>
>
>
> - CpuToken = (SPIN_LOCK *)(gSmmCpuPrivate->CurrentTokenBuf +
> SpinLockSize * gSmmCpuPrivate->UsedTokenNum);
>
> + SpinLock = (SPIN_LOCK *)(gSmmCpuPrivate->CurrentTokenBuf +
> SpinLockSize * gSmmCpuPrivate->UsedTokenNum);
>
> gSmmCpuPrivate->UsedTokenNum++;
>
>
>
> - InitializeSpinLock (CpuToken);
>
> - AcquireSpinLock (CpuToken);
>
> + InitializeSpinLock (SpinLock);
>
> + AcquireSpinLock (SpinLock);
>
>
>
> ProcToken = AllocatePool (sizeof (PROCEDURE_TOKEN));
>
> ASSERT (ProcToken != NULL);
>
> ProcToken->Signature = PROCEDURE_TOKEN_SIGNATURE;
>
> - ProcToken->ProcedureToken = CpuToken;
>
> + ProcToken->SpinLock = SpinLock;
>
> + ProcToken->RunningApCount = RunningApCount;
>
>
>
> InsertTailList (&gSmmCpuPrivate->TokenList, &ProcToken->Link);
>
>
>
> - return CpuToken;
>
> + return ProcToken;
>
> }
>
>
>
> /**
>
> @@ -1246,6 +1194,8 @@ InternalSmmStartupThisAp (
> IN OUT EFI_STATUS *CpuStatus
>
> )
>
> {
>
> + PROCEDURE_TOKEN *ProcToken;
>
> +
>
> if (CpuIndex >= gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus)
> {
>
> DEBUG((DEBUG_ERROR, "CpuIndex(%d) >= gSmmCpuPrivate-
> >SmmCoreEntryContext.NumberOfCpus(%d)\n", CpuIndex,
> gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus));
>
> return EFI_INVALID_PARAMETER;
>
> @@ -1278,14 +1228,12 @@ InternalSmmStartupThisAp (
>
>
> AcquireSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy);
>
>
>
> - if (Token != NULL) {
>
> - *Token = (MM_COMPLETION) CreateToken ();
>
> - }
>
> -
>
> mSmmMpSyncData->CpuData[CpuIndex].Procedure = Procedure;
>
> mSmmMpSyncData->CpuData[CpuIndex].Parameter = ProcArguments;
>
> if (Token != NULL) {
>
> - mSmmMpSyncData->CpuData[CpuIndex].Token = (SPIN_LOCK
> *)(*Token);
>
> + ProcToken= CreateToken (1);
>
> + mSmmMpSyncData->CpuData[CpuIndex].Token = ProcToken;
>
> + *Token = (MM_COMPLETION)ProcToken->SpinLock;
>
> }
>
> mSmmMpSyncData->CpuData[CpuIndex].Status = CpuStatus;
>
> if (mSmmMpSyncData->CpuData[CpuIndex].Status != NULL) {
>
> @@ -1343,6 +1291,7 @@ InternalSmmStartupAllAPs (
> {
>
> UINTN Index;
>
> UINTN CpuCount;
>
> + PROCEDURE_TOKEN *ProcToken;
>
>
>
> if ((TimeoutInMicroseconds != 0) && ((mSmmMp.Attributes &
> EFI_MM_MP_TIMEOUT_SUPPORTED) == 0)) {
>
> return EFI_INVALID_PARAMETER;
>
> @@ -1371,7 +1320,10 @@ InternalSmmStartupAllAPs (
> }
>
>
>
> if (Token != NULL) {
>
> - *Token = (MM_COMPLETION) CreateToken ();
>
> + ProcToken = CreateToken ((UINT32)mMaxNumberOfCpus);
>
> + *Token = (MM_COMPLETION)ProcToken->SpinLock;
>
> + } else {
>
> + ProcToken = NULL;
>
> }
>
>
>
> //
>
> @@ -1391,8 +1343,8 @@ InternalSmmStartupAllAPs (
> if (IsPresentAp (Index)) {
>
> mSmmMpSyncData->CpuData[Index].Procedure =
> (EFI_AP_PROCEDURE2) Procedure;
>
> mSmmMpSyncData->CpuData[Index].Parameter = ProcedureArguments;
>
> - if (Token != NULL) {
>
> - mSmmMpSyncData->CpuData[Index].Token = (SPIN_LOCK *)(*Token);
>
> + if (ProcToken != NULL) {
>
> + mSmmMpSyncData->CpuData[Index].Token = ProcToken;
>
> }
>
> if (CPUStatus != NULL) {
>
> mSmmMpSyncData->CpuData[Index].Status = &CPUStatus[Index];
>
> @@ -1408,6 +1360,13 @@ InternalSmmStartupAllAPs (
> if (CPUStatus != NULL) {
>
> CPUStatus[Index] = EFI_NOT_STARTED;
>
> }
>
> +
>
> + //
>
> + // Decrease the count to mark this processor(AP or BSP) as finished.
>
> + //
>
> + if (ProcToken != NULL) {
>
> + WaitForSemaphore (&ProcToken->RunningApCount);
>
> + }
>
> }
>
> }
>
>
>
> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
> b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
> index 5c1a01e42b..5c98494e2c 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
> @@ -212,7 +212,8 @@ typedef struct {
> UINTN Signature;
>
> LIST_ENTRY Link;
>
>
>
> - SPIN_LOCK *ProcedureToken;
>
> + SPIN_LOCK *SpinLock;
>
> + volatile UINT32 RunningApCount;
>
> } PROCEDURE_TOKEN;
>
>
>
> #define PROCEDURE_TOKEN_FROM_LINK(a) CR (a, PROCEDURE_TOKEN,
> Link, PROCEDURE_TOKEN_SIGNATURE)
>
> @@ -407,7 +408,7 @@ typedef struct {
> volatile VOID *Parameter;
>
> volatile UINT32 *Run;
>
> volatile BOOLEAN *Present;
>
> - SPIN_LOCK *Token;
>
> + PROCEDURE_TOKEN *Token;
>
> EFI_STATUS *Status;
>
> } SMM_CPU_DATA_BLOCK;
>
>
>
> --
> 2.23.0.windows.1
>
>
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
>
> View/Reply Online (#52503): https://edk2.groups.io/g/devel/message/52503
> Mute This Topic: https://groups.io/mt/69227573/1712937
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub [ray.ni@intel.com]
> -=-=-=-=-=-=
next prev parent reply other threads:[~2019-12-24 2:44 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-23 8:10 [PATCH v3 0/2] Fix race condition issue for PiSmmCpuDxeSmm driver Dong, Eric
2019-12-23 8:10 ` [PATCH v3 1/2] UefiCpuPkg/PiSmmCpuDxeSmm: Remove dependence between APs Dong, Eric
2019-12-24 2:44 ` Ni, Ray [this message]
2019-12-23 8:10 ` [PATCH v3 2/2] UefiCpuPkg/PiSmmCpuDxeSmm: Fix buffer overflow issue Dong, Eric
2019-12-24 2:33 ` Ni, Ray
2020-01-03 17:06 ` [edk2-devel] " Laszlo Ersek
2020-01-03 17:20 ` Laszlo Ersek
2020-01-03 18:11 ` Laszlo Ersek
2020-01-06 1:15 ` Dong, Eric
2020-01-06 10:48 ` Laszlo Ersek
2020-01-07 2:47 ` Dong, Eric
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=734D49CCEBEEF84792F5B80ED585239D5C3A9DBF@SHSMSX104.ccr.corp.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