> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> Laszlo Ersek
> Sent: Friday, June 21, 2019 12:45 AM
> To: devel@edk2.groups.io; Dong, Eric <eric.d...@intel.com>
> Cc: Ni, Ray <ray...@intel.com>
> Subject: Re: [edk2-devel] [Patch 2/2] UefiCpuPkg/PiSmmCpuDxeSmm:
> Enable MM MP Protocol.
> 
> On 06/19/19 07:51, Dong, Eric wrote:
> > Add MM Mp Protocol in PiSmmCpuDxeSmm driver.
> >
> > Cc: Ray Ni <ray...@intel.com>
> > Cc: Laszlo Ersek <ler...@redhat.com>
> > Signed-off-by: Eric Dong <eric.d...@intel.com>
> > ---
> >  UefiCpuPkg/PiSmmCpuDxeSmm/MpProtocol.c       | 375
> +++++++++++++++
> >  UefiCpuPkg/PiSmmCpuDxeSmm/MpProtocol.h       | 283 +++++++++++
> >  UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c        | 468
> ++++++++++++++++++-
> >  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c   |  11 +
> >  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h   | 172 ++++++-
> >  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf |   3 +
> >  6 files changed, 1296 insertions(+), 16 deletions(-)  create mode
> > 100644 UefiCpuPkg/PiSmmCpuDxeSmm/MpProtocol.c
> >  create mode 100644 UefiCpuPkg/PiSmmCpuDxeSmm/MpProtocol.h
> >
> > diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/MpProtocol.c
> > b/UefiCpuPkg/PiSmmCpuDxeSmm/MpProtocol.c
> > new file mode 100644
> > index 0000000000..8cf69428c2
> > --- /dev/null
> > +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/MpProtocol.c
> > @@ -0,0 +1,375 @@
> > +/** @file
> > +SMM MP protocol implementation
> > +
> > +Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > +
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include "PiSmmCpuDxeSmm.h"
> > +#include "MpProtocol.h"
> > +
> > +///
> > +/// SMM MP Protocol instance
> > +///
> > +EFI_SMM_MP_PROTOCOL  mSmmMp  = {
> > +  EFI_SMM_MP_PROTOCOL_REVISION,
> > +  0,
> > +  SmmMpGetNumberOfProcessors,
> > +  SmmMpDispatchProcedure,
> > +  SmmMpBroadcastProcedure,
> > +  SmmMpSetStartupProcedure,
> > +  SmmMpCheckForProcedure,
> > +  SmmMpWaitForProcedure
> > +};
> > +
> > +/**
> > +  Service to retrieves the number of logical processor in the platform.
> > +
> > +  @param[in]  This                The EFI_MM_MP_PROTOCOL instance.
> > +  @param[out] NumberOfProcessors  Pointer to the total number of
> logical processors in the system,
> > +                                  including the BSP and all APs.
> > +
> > +  @retval EFI_SUCCESS             The number of processors was retrieved
> successfully
> > +  @retval EFI_INVALID_PARAMETER   NumberOfProcessors is NULL
> > +**/
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +SmmMpGetNumberOfProcessors (
> > +  IN CONST EFI_SMM_MP_PROTOCOL  *This,
> > +  OUT      UINTN                *NumberOfProcessors
> > +  )
> > +{
> > +  if (NumberOfProcessors == NULL) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  *NumberOfProcessors =
> > + gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus;
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +
> > +/**
> > +  This service allows the caller to invoke a procedure one of the
> > +application processors (AP). This
> > +  function uses an optional token parameter to support blocking and
> > +non-blocking modes. If the token
> > +  is passed into the call, the function will operate in a
> > +non-blocking fashion and the caller can
> > +  check for completion with CheckOnProcedure or WaitForProcedure.
> > +
> > +  @param[in]     This                   The EFI_MM_MP_PROTOCOL instance.
> > +  @param[in]     Procedure              A pointer to the procedure to be 
> > run on
> the designated target
> > +                                        AP of the system. Type 
> > EFI_AP_PROCEDURE2 is
> defined below in
> > +                                        related definitions.
> > +  @param[in]     CpuNumber              The zero-based index of the 
> > processor
> number of the target
> > +                                        AP, on which the code stream is 
> > supposed to run. If
> the number
> > +                                        points to the calling processor 
> > then it will not run the
> > +                                        supplied code.
> > +  @param[in]     TimeoutInMicroseconds  Indicates the time limit in
> microseconds for this AP to
> > +                                        finish execution of Procedure, 
> > either for blocking or
> > +                                        non-blocking mode. Zero means 
> > infinity. If the
> timeout
> > +                                        expires before this AP returns 
> > from Procedure, then
> Procedure
> > +                                        on the AP is terminated. If the 
> > timeout expires in
> blocking
> > +                                        mode, the call returns 
> > EFI_TIMEOUT. If the timeout
> expires
> > +                                        in non-blocking mode, the timeout 
> > determined can be
> through
> > +                                        CheckOnProcedure or 
> > WaitForProcedure.
> > +                                        Note that timeout support is 
> > optional. Whether an
> > +                                        implementation supports this 
> > feature, can be
> determined via
> > +                                        the Attributes data member.
> > +  @param[in,out] ProcedureArguments     Allows the caller to pass a list of
> parameters to the code
> > +                                        that is run by the AP. It is an 
> > optional common mailbox
> > +                                        between APs and the caller to 
> > share information.
> > +  @param[in,out] Token                  This is parameter is broken into 
> > two
> components:
> > +                                        1.Token->Completion is an optional 
> > parameter that
> allows the
> > +                                        caller to execute the procedure in 
> > a blocking or non-
> blocking
> > +                                        fashion. If it is NULL the call is 
> > blocking, and the call will
> > +                                        not return until the AP has 
> > completed the procedure.
> If the
> > +                                        token is not NULL, the call will 
> > return immediately. The
> caller
> > +                                        can check whether the procedure 
> > has completed with
> > +                                        CheckOnProcedure or 
> > WaitForProcedure.
> > +                                        2.Token->Status The implementation 
> > updates the
> address pointed
> > +                                        at by this variable with the 
> > status code returned by
> Procedure
> > +                                        when it completes execution on the 
> > target AP, or with
> EFI_TIMEOUT
> > +                                        if the Procedure fails to complete 
> > within the optional
> timeout.
> > +                                        The implementation will update 
> > this variable with
> EFI_NOT_READY
> > +                                        prior to starting Procedure on the 
> > target AP
> > +  @param[in,out] CPUStatus              This optional pointer may be used 
> > to
> get the status code returned
> > +                                        by Procedure when it completes 
> > execution on the
> target AP, or with
> > +                                        EFI_TIMEOUT if the Procedure fails 
> > to complete within
> the optional
> > +                                        timeout. The implementation will 
> > update this variable
> with
> > +                                        EFI_NOT_READY prior to starting 
> > Procedure on the
> target AP.
> > +
> > +  @retval EFI_SUCCESS                   In the blocking case, this 
> > indicates that
> Procedure has completed
> > +                                        execution on the target AP.
> > +                                        In the non-blocking case this 
> > indicates that the
> procedure has
> > +                                        been successfully scheduled for 
> > execution on the
> target AP.
> > +  @retval EFI_INVALID_PARAMETER         The input arguments are out of
> range. Either the target AP is the
> > +                                        caller of the function, or the 
> > Procedure or Token is
> NULL
> > +  @retval EFI_NOT_READY                 If the target AP is busy executing
> another procedure
> > +  @retval EFI_ALREADY_STARTED           Token is already in use for another
> procedure
> > +  @retval EFI_TIMEOUT                   In blocking mode, the timeout 
> > expired
> before the specified AP
> > +                                        has finished **/ EFI_STATUS
> > +EFIAPI SmmMpDispatchProcedure (
> > +  IN CONST EFI_SMM_MP_PROTOCOL           *This,
> > +  IN       EFI_AP_PROCEDURE2             Procedure,
> > +  IN       UINTN                         CpuNumber,
> > +  IN       UINTN                         TimeoutInMicroseconds,
> > +  IN OUT   VOID                          *ProcedureArguments OPTIONAL,
> > +  IN OUT   SMM_COMPLETION                *Token,
> > +  IN OUT   EFI_STATUS                    *CPUStatus
> > +  )
> > +{
> > +  if (Token != NULL) {
> > +    *Token = AllocatePool (sizeof (SPIN_LOCK));
> > +    ASSERT (*Token != NULL);
> > +    InitializeSpinLock ((SPIN_LOCK *)(*Token));
> > +
> > +    return InternalSmmStartupThisAp(
> > +      Procedure,
> > +      CpuNumber,
> > +      ProcedureArguments,
> > +      SmmCpuCallInNewType,
> > +      (SPIN_LOCK *)(*Token),
> > +      TimeoutInMicroseconds,
> > +      CPUStatus
> > +      );
> > +  }
> > +
> > +  return InternalSmmStartupThisAp(
> > +    Procedure,
> > +    CpuNumber,
> > +    ProcedureArguments,
> > +    SmmCpuCallInNewType,
> > +    NULL,
> > +    TimeoutInMicroseconds,
> > +    CPUStatus
> > +    );
> > +}
> 
> This function breaks the build for me:
> 
>   passing argument 1 of 'InternalSmmStartupThisAp' from incompatible
>   pointer type [-Werror]
> 
> InternalSmmStartupThisAp() expects an EFI_AP_PROCEDURE as first
> parameter:
> 
>   typedef
>   VOID
>   (EFIAPI *EFI_AP_PROCEDURE)(
>     IN OUT VOID  *Buffer
>     );
> 
> but you pass EFI_AP_PROCEDURE2:
> 
>   typedef
>   EFI_STATUS
>   (EFIAPI *EFI_AP_PROCEDURE2)(
>     IN VOID  *ProcedureArgument
>   );
> 
> Assuming the return status propagation is otherwise correctly implemented
> through "CpuStatus" -- I didn't check --, please use a dedicated wrapper
> function for the callback, so that we can avoid type punning of function
> pointers. (It's possible that you'll have to introduce a separate wrapper
> structure too, for passing in both the function pointer and the procedure
> argument pointer -- and then that structure should be allocated dynamically.)

Hi Laszlo,

Can you help to explain more about how to use dedicated wrapper function for 
the callback? What I can image is using type cast here to fix this issue. Why 
you think type cast is not enough here? 

> 
> 
> --*--
> 
> 
> Independently, I think that catching "out of memory" situations in
> PiSmmCpuDxeSmm with ASSERTs is bad practice. This is a privileged /
> security-relevant driver, and the function in question is exposed as a 
> protocol
> member function (i.e. it's not *only* a part of driver startup). Which I 
> believe
> might make it possible for the OS, indirectly (via EFI runtime calls for
> example), to trigger this function.
> 
> So, even though the PI spec doesn't list EFI_OUT_OF_RESOURCES as a valid
> return code for this member function, we should return that, if
> AllocatePool() fails. (This applies to SmmMpBroadcastProcedure() too.)

Agree, will add error handling here and add the return status code to the 
function header comments.

Thanks,
Eric
> 
> Thanks
> Laszlo
> 
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#42773): https://edk2.groups.io/g/devel/message/42773
Mute This Topic: https://groups.io/mt/32120263/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to