public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Wu, Jiaxin" <jiaxin.wu@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
	"lersek@redhat.com" <lersek@redhat.com>
Cc: "Dong, Eric" <eric.dong@intel.com>, "Ni, Ray" <ray.ni@intel.com>,
	"Zeng, Star" <star.zeng@intel.com>,
	Gerd Hoffmann <kraxel@redhat.com>,
	"Kumar, Rahul R" <rahul.r.kumar@intel.com>
Subject: Re: [edk2-devel] [PATCH v3 3/6] UefiCpuPkg: Implements SmmCpuSyncLib library instance
Date: Thu, 14 Dec 2023 15:34:42 +0000	[thread overview]
Message-ID: <MN0PR11MB6158C4861F3AE86F70596619FE8CA@MN0PR11MB6158.namprd11.prod.outlook.com> (raw)
In-Reply-To: <4a2911fb-aa15-efb0-f2e4-1c5bac8aab8d@redhat.com>

> > The code will be changed to:
> >
> >   if ((INT32)InternalWaitForSemaphore (Context->CpuCount) < 0) {
> >     return RETURN_ABORTED;
> >   }
> 
> I find this quite ugly. In the "semaphore post" operation, we already
> have code that prevents incrementing if the semaphore is "locked". Can
> we perhaps create a "semaphore pend" operation that does the same?
> 
> How about this:
> 
> diff --git a/UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.c
> b/UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.c
> index 3c2835f8def6..5d7fc58ef23f 100644
> --- a/UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.c
> +++ b/UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.c
> @@ -91,35 +91,38 @@ UINT32
>  InternalWaitForSemaphore (
>    IN OUT  volatile UINT32  *Sem
>    )
>  {
>    UINT32  Value;
> 
>    for ( ; ;) {
>      Value = *Sem;
> +    if (Value == MAX_UINT32) {
> +      return Value;
> +    }
>      if ((Value != 0) &&
>          (InterlockedCompareExchange32 (
>             (UINT32 *)Sem,
>             Value,
>             Value - 1
>             ) == Value))
>      {
>        break;
>      }
> 
>      CpuPause ();
>    }
> 
>    return Value - 1;
>  }
> 
> Note, I'm just brainstorming here, I've not thought it through. Just to
> illustrate the direction I'm thinking of.
> 
> This change should be mostly OK. InternalWaitForSemaphore() returns the
> decremented value. So, for InternalWaitForSemaphore() to return
> MAX_UINT32 *without* this update, the function would have to decrement
> the semaphore when the semaphore is zero. But in that case, the function
> *blocks*. Thus, a return value of MAX_UINT32 is not possible without
> this extension; ergo, if MAX_UINT32 is returned (with this extension),

Yes, that's for the semaphore sync usage, we have to block the sem if it's zero, decrease it when return. That's why I said - it's naturally make sure the Run is reset after all ready to exit.  Then it can achieve the below flow:
    BSP: ReleaseOneAp  -->  AP: WaitForBsp
    BSP: WaitForAPs    <--  AP: ReleaseBsp


For locked case, I just copy the existing logic from SMM cpu driver (as I document in the commit message: The instance refers the existing SMM CPU driver (PiSmmCpuDxeSmm) sync implementation and behavior):
existing ReleaseSemaphore() prevents increase the semaphore, but it still return the original semaphore value +1; --> that's why we have to check the return value is  0 or not in SmmCpuSyncCheckInCpu()
existing WaitForSemaphore() allow decrease the semaphore if locked, and it also return the original semaphore value -1;  --> that's why we have to check the return value is  < 0 or not in SmmCpuSyncCheckOutCpu()
 
so, do you want to align the behavior as below?

ReleaseSemaphore() prevents increase the semaphore if locked, and it should return the locked value (MAX_UINT32);  --> then we can check the return value is  MAX_UINT32 or not in SmmCpuSyncCheckInCpu(), and sem itself won't be changed.
WaitForSemaphore() prevents decrease the semaphore if locked, and it should return the locked value (MAX_UINT32); --> then we can check the return value is  MAX_UINT32 or not in SmmCpuSyncCheckOutCpu (), and sem itself won't be changed.

I think:
for ReleaseSemaphore, it must meet below 2 cases usage:
1. for semaphore sync usage (Run), it doesn't care the lock case, and returned value is not cared. Just check the semaphore itself.
2. for Rendezvous case (Counter), it not only needs to check locked or not from return value, but also require "only increase the semaphore if not locked".

for WaitForSemaphore, it must meet below 2 cases usage:
1. for semaphore sync usage (Run), it doesn't care the lock case, and returned value is not cared. But for the semaphore itself, it need block at 0, and decrease when return.
2. for Rendezvous case (Counter), it only needs to check locked or not from return value. semaphore itself is not cared.

So, based on above, I think, yes, we can do the change to align the lock behavior:  

/**
  Performs an atomic compare exchange operation to get semaphore.
  The compare exchange operation must be performed using MP safe
  mechanisms.

  @param[in,out]  Sem    IN:  32-bit unsigned integer
                         OUT: original integer - 1 if Sem is not locked.
                         OUT: original integer (MAX_UINT32) if Sem is locked.

  @retval     Original integer - 1 if Sem is not locked.
              Original integer (MAX_UINT32) if Sem is locked.

**/
STATIC
UINT32
InternalWaitForSemaphore (
  IN OUT  volatile UINT32  *Sem
  )
{
  UINT32  Value;

  for ( ; ;) {
    Value = *Sem;
    if (Value == MAX_UINT32) {
      return Value;
    }

    if ((Value != 0) &&
        (InterlockedCompareExchange32 (
           (UINT32 *)Sem,
           Value,
           Value - 1
           ) == Value))
    {
      break;
    }

    CpuPause ();
  }

  return Value - 1;
}

/**
  Performs an atomic compare exchange operation to release semaphore.
  The compare exchange operation must be performed using MP safe
  mechanisms.

  @param[in,out]  Sem    IN:  32-bit unsigned integer
                         OUT: original integer + 1 if Sem is not locked.
                         OUT: original integer (MAX_UINT32) if Sem is locked.

  @retval    Original integer + 1 if Sem is not locked.
             Original integer (MAX_UINT32) if Sem is locked.

**/
STATIC
UINT32
InternalReleaseSemaphore (
  IN OUT  volatile UINT32  *Sem
  )
{
  UINT32  Value;

  do {
    Value = *Sem;
  } while (Value + 1 != 0 &&
           InterlockedCompareExchange32 (
             (UINT32 *)Sem,
             Value,
             Value + 1
             ) != Value);

  if (Value == MAX_UINT32) {
    return Value;
  }

  return Value + 1;
}

I haven't see any issue with this change. 

> we know the door was locked earlier (and the semaphore is not changed).
> 
> At the same time, we might want to update InternalReleaseSemaphore() as
> well, so that it cannot validly increment the semaphore value to MAX_UINT32.
> 
> 
> 
> >
> >



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



  reply	other threads:[~2023-12-14 15:34 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-06 10:01 [edk2-devel] [PATCH v3 0/6] Refine SMM CPU Sync flow and abstract SmmCpuSyncLib Wu, Jiaxin
2023-12-06 10:01 ` [edk2-devel] [PATCH v3 1/6] UefiCpuPkg/PiSmmCpuDxeSmm: Optimize Semaphore Sync between BSP and AP Wu, Jiaxin
2023-12-12 19:27   ` Laszlo Ersek
2023-12-06 10:01 ` [edk2-devel] [PATCH v3 2/6] UefiCpuPkg: Adds SmmCpuSyncLib library class Wu, Jiaxin
2023-12-07  9:07   ` Ni, Ray
2023-12-12 20:18   ` Laszlo Ersek
2023-12-13  4:23     ` Wu, Jiaxin
2023-12-13 15:02       ` Laszlo Ersek
2023-12-06 10:01 ` [edk2-devel] [PATCH v3 3/6] UefiCpuPkg: Implements SmmCpuSyncLib library instance Wu, Jiaxin
2023-12-13 14:34   ` Laszlo Ersek
2023-12-14 11:11     ` Wu, Jiaxin
2023-12-14 13:48       ` Laszlo Ersek
2023-12-14 15:34         ` Wu, Jiaxin [this message]
2023-12-14 15:54         ` Wu, Jiaxin
2023-12-15  6:41         ` Wu, Jiaxin
2023-12-15  6:44         ` Wu, Jiaxin
2023-12-06 10:01 ` [edk2-devel] [PATCH v3 4/6] OvmfPkg: Specifies SmmCpuSyncLib instance Wu, Jiaxin
2023-12-13 16:52   ` Laszlo Ersek
2023-12-14 13:43     ` Wu, Jiaxin
2023-12-15  0:21     ` Ni, Ray
2023-12-06 10:01 ` [edk2-devel] [PATCH v3 5/6] UefiPayloadPkg: " Wu, Jiaxin
2023-12-06 10:01 ` [edk2-devel] [PATCH v3 6/6] UefiCpuPkg/PiSmmCpuDxeSmm: Consume SmmCpuSyncLib Wu, Jiaxin

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=MN0PR11MB6158C4861F3AE86F70596619FE8CA@MN0PR11MB6158.namprd11.prod.outlook.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