On Wed, Sep 04, 2019 at 06:43:11PM +0800, Abner Chang wrote:
> The driver produces RISC-V EFI_CPU_ARCH_PROTOCOL and use RISC-V platform 
> level timer library
> 
> Due to RISC-V timer CSR is platform implementation specific, RISC-V CPU DXE 
> driver invokes platform level timer library
> to access to timer CSRs.

No comments beyond PatchCheck.py, license/SPDX and contribution agreement.

/
    Leif

> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Abner Chang <abner.ch...@hpe.com>
> ---
>  RiscVPkg/Universal/CpuDxe/CpuDxe.c        | 324 +++++++++++++++
>  RiscVPkg/Universal/CpuDxe/CpuDxe.h        | 212 ++++++++++
>  RiscVPkg/Universal/CpuDxe/CpuDxe.inf      |  66 +++
>  RiscVPkg/Universal/CpuDxe/CpuDxe.uni      | Bin 0 -> 1564 bytes
>  RiscVPkg/Universal/CpuDxe/CpuDxeExtra.uni | Bin 0 -> 1392 bytes
>  RiscVPkg/Universal/CpuDxe/CpuMp.h         | 648 
> ++++++++++++++++++++++++++++++
>  6 files changed, 1250 insertions(+)
>  create mode 100644 RiscVPkg/Universal/CpuDxe/CpuDxe.c
>  create mode 100644 RiscVPkg/Universal/CpuDxe/CpuDxe.h
>  create mode 100644 RiscVPkg/Universal/CpuDxe/CpuDxe.inf
>  create mode 100644 RiscVPkg/Universal/CpuDxe/CpuDxe.uni
>  create mode 100644 RiscVPkg/Universal/CpuDxe/CpuDxeExtra.uni
>  create mode 100644 RiscVPkg/Universal/CpuDxe/CpuMp.h
> 
> diff --git a/RiscVPkg/Universal/CpuDxe/CpuDxe.c 
> b/RiscVPkg/Universal/CpuDxe/CpuDxe.c
> new file mode 100644
> index 0000000..37d9bcf
> --- /dev/null
> +++ b/RiscVPkg/Universal/CpuDxe/CpuDxe.c
> @@ -0,0 +1,324 @@
> +/** @file
> +  RISC-V CPU DXE driver.
> +
> +  Copyright (c) 2016, Hewlett Packard Enterprise Development LP. All rights 
> reserved.<BR>
> +
> +  This program and the accompanying materials are
> +  licensed and made available under the terms and conditions of the BSD 
> License
> +  which accompanies this distribution.  The full text of the license may be 
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
> IMPLIED.
> +
> +**/
> +
> +#include "CpuDxe.h"
> +
> +//
> +// Global Variables
> +//
> +BOOLEAN                   InterruptState = FALSE;
> +EFI_HANDLE                mCpuHandle = NULL;
> +BOOLEAN                   mIsFlushingGCD;
> +
> +EFI_CPU_ARCH_PROTOCOL  gCpu = {
> +  CpuFlushCpuDataCache,
> +  CpuEnableInterrupt,
> +  CpuDisableInterrupt,
> +  CpuGetInterruptState,
> +  CpuInit,
> +  CpuRegisterInterruptHandler,
> +  CpuGetTimerValue,
> +  CpuSetMemoryAttributes,
> +  1,                          // NumberOfTimers
> +  4                           // DmaBufferAlignment
> +};
> +
> +//
> +// CPU Arch Protocol Functions
> +//
> +
> +/**
> +  Flush CPU data cache. If the instruction cache is fully coherent
> +  with all DMA operations then function can just return EFI_SUCCESS.
> +
> +  @param  This              Protocol instance structure
> +  @param  Start             Physical address to start flushing from.
> +  @param  Length            Number of bytes to flush. Round up to chipset
> +                            granularity.
> +  @param  FlushType         Specifies the type of flush operation to perform.
> +
> +  @retval EFI_SUCCESS       If cache was flushed
> +  @retval EFI_UNSUPPORTED   If flush type is not supported.
> +  @retval EFI_DEVICE_ERROR  If requested range could not be flushed.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CpuFlushCpuDataCache (
> +  IN EFI_CPU_ARCH_PROTOCOL     *This,
> +  IN EFI_PHYSICAL_ADDRESS      Start,
> +  IN UINT64                    Length,
> +  IN EFI_CPU_FLUSH_TYPE        FlushType
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Enables CPU interrupts.
> +
> +  @param  This              Protocol instance structure
> +
> +  @retval EFI_SUCCESS       If interrupts were enabled in the CPU
> +  @retval EFI_DEVICE_ERROR  If interrupts could not be enabled on the CPU.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CpuEnableInterrupt (
> +  IN EFI_CPU_ARCH_PROTOCOL          *This
> +  )
> +{
> +  EnableInterrupts ();
> +  InterruptState = TRUE;
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Disables CPU interrupts.
> +
> +  @param  This              Protocol instance structure
> +
> +  @retval EFI_SUCCESS       If interrupts were disabled in the CPU.
> +  @retval EFI_DEVICE_ERROR  If interrupts could not be disabled on the CPU.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CpuDisableInterrupt (
> +  IN EFI_CPU_ARCH_PROTOCOL     *This
> +  )
> +{
> +  DisableInterrupts ();
> +  InterruptState = FALSE;
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Return the state of interrupts.
> +
> +  @param  This                   Protocol instance structure
> +  @param  State                  Pointer to the CPU's current interrupt state
> +
> +  @retval EFI_SUCCESS            If interrupts were disabled in the CPU.
> +  @retval EFI_INVALID_PARAMETER  State is NULL.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CpuGetInterruptState (
> +  IN  EFI_CPU_ARCH_PROTOCOL     *This,
> +  OUT BOOLEAN                   *State
> +  )
> +{
> +  if (State == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *State = InterruptState;
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Generates an INIT to the CPU.
> +
> +  @param  This              Protocol instance structure
> +  @param  InitType          Type of CPU INIT to perform
> +
> +  @retval EFI_SUCCESS       If CPU INIT occurred. This value should never be
> +                            seen.
> +  @retval EFI_DEVICE_ERROR  If CPU INIT failed.
> +  @retval EFI_UNSUPPORTED   Requested type of CPU INIT not supported.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CpuInit (
> +  IN EFI_CPU_ARCH_PROTOCOL      *This,
> +  IN EFI_CPU_INIT_TYPE          InitType
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +
> +/**
> +  Registers a function to be called from the CPU interrupt handler.
> +
> +  @param  This                   Protocol instance structure
> +  @param  InterruptType          Defines which interrupt to hook. IA-32
> +                                 valid range is 0x00 through 0xFF
> +  @param  InterruptHandler       A pointer to a function of type
> +                                 EFI_CPU_INTERRUPT_HANDLER that is called
> +                                 when a processor interrupt occurs.  A null
> +                                 pointer is an error condition.
> +
> +  @retval EFI_SUCCESS            If handler installed or uninstalled.
> +  @retval EFI_ALREADY_STARTED    InterruptHandler is not NULL, and a handler
> +                                 for InterruptType was previously installed.
> +  @retval EFI_INVALID_PARAMETER  InterruptHandler is NULL, and a handler for
> +                                 InterruptType was not previously installed.
> +  @retval EFI_UNSUPPORTED        The interrupt specified by InterruptType
> +                                 is not supported.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CpuRegisterInterruptHandler (
> +  IN EFI_CPU_ARCH_PROTOCOL         *This,
> +  IN EFI_EXCEPTION_TYPE            InterruptType,
> +  IN EFI_CPU_INTERRUPT_HANDLER     InterruptHandler
> +  )
> +{
> +  return RegisterCpuInterruptHandler (InterruptType, InterruptHandler);
> +}
> +
> +
> +/**
> +  Returns a timer value from one of the CPU's internal timers. There is no
> +  inherent time interval between ticks but is a function of the CPU 
> frequency.
> +
> +  @param  This                - Protocol instance structure.
> +  @param  TimerIndex          - Specifies which CPU timer is requested.
> +  @param  TimerValue          - Pointer to the returned timer value.
> +  @param  TimerPeriod         - A pointer to the amount of time that passes
> +                                in femtoseconds (10-15) for each increment
> +                                of TimerValue. If TimerValue does not
> +                                increment at a predictable rate, then 0 is
> +                                returned.  The amount of time that has
> +                                passed between two calls to GetTimerValue()
> +                                can be calculated with the formula
> +                                (TimerValue2 - TimerValue1) * TimerPeriod.
> +                                This parameter is optional and may be NULL.
> +
> +  @retval EFI_SUCCESS           - If the CPU timer count was returned.
> +  @retval EFI_UNSUPPORTED       - If the CPU does not have any readable 
> timers.
> +  @retval EFI_DEVICE_ERROR      - If an error occurred while reading the 
> timer.
> +  @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is 
> NULL.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CpuGetTimerValue (
> +  IN  EFI_CPU_ARCH_PROTOCOL     *This,
> +  IN  UINT32                    TimerIndex,
> +  OUT UINT64                    *TimerValue,
> +  OUT UINT64                    *TimerPeriod OPTIONAL
> +  )
> +{
> +  if (TimerValue == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (TimerIndex != 0) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *TimerValue = (UINT64)RiscVReadMachineTimer ();
> +  if (TimerPeriod != NULL) {
> +    *TimerPeriod  = DivU64x32 (
> +                      1000000000000000u,
> +                      PcdGet64 (PcdRiscVMachineTimerFrequencyInHerz)
> +                      );
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Implementation of SetMemoryAttributes() service of CPU Architecture 
> Protocol.
> +
> +  This function modifies the attributes for the memory region specified by 
> BaseAddress and
> +  Length from their current attributes to the attributes specified by 
> Attributes.
> +
> +  @param  This             The EFI_CPU_ARCH_PROTOCOL instance.
> +  @param  BaseAddress      The physical address that is the start address of 
> a memory region.
> +  @param  Length           The size in bytes of the memory region.
> +  @param  Attributes       The bit mask of attributes to set for the memory 
> region.
> +
> +  @retval EFI_SUCCESS           The attributes were set for the memory 
> region.
> +  @retval EFI_ACCESS_DENIED     The attributes for the memory resource range 
> specified by
> +                                BaseAddress and Length cannot be modified.
> +  @retval EFI_INVALID_PARAMETER Length is zero.
> +                                Attributes specified an illegal combination 
> of attributes that
> +                                cannot be set together.
> +  @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to 
> modify the attributes of
> +                                the memory resource range.
> +  @retval EFI_UNSUPPORTED       The processor does not support one or more 
> bytes of the memory
> +                                resource range specified by BaseAddress and 
> Length.
> +                                The bit mask of attributes is not support 
> for the memory resource
> +                                range specified by BaseAddress and Length.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CpuSetMemoryAttributes (
> +  IN EFI_CPU_ARCH_PROTOCOL     *This,
> +  IN EFI_PHYSICAL_ADDRESS      BaseAddress,
> +  IN UINT64                    Length,
> +  IN UINT64                    Attributes
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "%a:Set memory attributes not supported yet\n", 
> __FUNCTION__));
> +  ASSERT (FALSE);
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Initialize the state information for the CPU Architectural Protocol.
> +
> +  @param ImageHandle     Image handle this driver.
> +  @param SystemTable     Pointer to the System Table.
> +
> +  @retval EFI_SUCCESS           Thread can be successfully created
> +  @retval EFI_OUT_OF_RESOURCES  Cannot allocate protocol data structure
> +  @retval EFI_DEVICE_ERROR      Cannot create the thread
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +InitializeCpu (
> +  IN EFI_HANDLE                            ImageHandle,
> +  IN EFI_SYSTEM_TABLE                      *SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  //
> +  // Machine mode handler is initiated in CpuExceptionHandlerLibConstructor 
> in
> +  // CpuExecptionHandlerLib.
> +  //
> +
> +  //
> +  // Make sure interrupts are disabled
> +  //
> +  DisableInterrupts ();
> +
> +  //
> +  // Install CPU Architectural Protocol
> +  //
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  &mCpuHandle,
> +                  &gEfiCpuArchProtocolGuid, &gCpu,
> +                  NULL
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> diff --git a/RiscVPkg/Universal/CpuDxe/CpuDxe.h 
> b/RiscVPkg/Universal/CpuDxe/CpuDxe.h
> new file mode 100644
> index 0000000..00f40ff
> --- /dev/null
> +++ b/RiscVPkg/Universal/CpuDxe/CpuDxe.h
> @@ -0,0 +1,212 @@
> +/** @file
> +  RISC-V CPU DXE module header file.
> +
> +  Copyright (c) 2016, Hewlett Packard Enterprise Development LP. All rights 
> reserved.<BR>
> +
> +  This program and the accompanying materials are
> +  licensed and made available under the terms and conditions of the BSD 
> License
> +  which accompanies this distribution.  The full text of the license may be 
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
> IMPLIED.
> +
> +**/
> +
> +#ifndef _CPU_DXE_H_
> +#define _CPU_DXE_H_
> +
> +#include <PiDxe.h>
> +
> +#include <Protocol/Cpu.h>
> +
> +#include <Library/UefiDriverEntryPoint.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/DxeServicesTableLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/CpuLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/CpuExceptionHandlerLib.h>
> +#include <Library/TimerLib.h>
> +#include <Library/RiscVCpuLib.h>
> +
> +/**
> +  Flush CPU data cache. If the instruction cache is fully coherent
> +  with all DMA operations then function can just return EFI_SUCCESS.
> +
> +  @param  This              Protocol instance structure
> +  @param  Start             Physical address to start flushing from.
> +  @param  Length            Number of bytes to flush. Round up to chipset
> +                            granularity.
> +  @param  FlushType         Specifies the type of flush operation to perform.
> +
> +  @retval EFI_SUCCESS       If cache was flushed
> +  @retval EFI_UNSUPPORTED   If flush type is not supported.
> +  @retval EFI_DEVICE_ERROR  If requested range could not be flushed.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CpuFlushCpuDataCache (
> +  IN EFI_CPU_ARCH_PROTOCOL     *This,
> +  IN EFI_PHYSICAL_ADDRESS      Start,
> +  IN UINT64                    Length,
> +  IN EFI_CPU_FLUSH_TYPE        FlushType
> +  );
> +
> +/**
> +  Enables CPU interrupts.
> +
> +  @param  This              Protocol instance structure
> +
> +  @retval EFI_SUCCESS       If interrupts were enabled in the CPU
> +  @retval EFI_DEVICE_ERROR  If interrupts could not be enabled on the CPU.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CpuEnableInterrupt (
> +  IN EFI_CPU_ARCH_PROTOCOL     *This
> +  );
> +
> +/**
> +  Disables CPU interrupts.
> +
> +  @param  This              Protocol instance structure
> +
> +  @retval EFI_SUCCESS       If interrupts were disabled in the CPU.
> +  @retval EFI_DEVICE_ERROR  If interrupts could not be disabled on the CPU.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CpuDisableInterrupt (
> +  IN EFI_CPU_ARCH_PROTOCOL     *This
> +  );
> +
> +/**
> +  Return the state of interrupts.
> +
> +  @param  This                   Protocol instance structure
> +  @param  State                  Pointer to the CPU's current interrupt state
> +
> +  @retval EFI_SUCCESS            If interrupts were disabled in the CPU.
> +  @retval EFI_INVALID_PARAMETER  State is NULL.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CpuGetInterruptState (
> +  IN  EFI_CPU_ARCH_PROTOCOL     *This,
> +  OUT BOOLEAN                   *State
> +  );
> +
> +/**
> +  Generates an INIT to the CPU.
> +
> +  @param  This              Protocol instance structure
> +  @param  InitType          Type of CPU INIT to perform
> +
> +  @retval EFI_SUCCESS       If CPU INIT occurred. This value should never be
> +                            seen.
> +  @retval EFI_DEVICE_ERROR  If CPU INIT failed.
> +  @retval EFI_UNSUPPORTED   Requested type of CPU INIT not supported.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CpuInit (
> +  IN EFI_CPU_ARCH_PROTOCOL     *This,
> +  IN EFI_CPU_INIT_TYPE         InitType
> +  );
> +
> +/**
> +  Registers a function to be called from the CPU interrupt handler.
> +
> +  @param  This                   Protocol instance structure
> +  @param  InterruptType          Defines which interrupt to hook. IA-32
> +                                 valid range is 0x00 through 0xFF
> +  @param  InterruptHandler       A pointer to a function of type
> +                                 EFI_CPU_INTERRUPT_HANDLER that is called
> +                                 when a processor interrupt occurs.  A null
> +                                 pointer is an error condition.
> +
> +  @retval EFI_SUCCESS            If handler installed or uninstalled.
> +  @retval EFI_ALREADY_STARTED    InterruptHandler is not NULL, and a handler
> +                                 for InterruptType was previously installed.
> +  @retval EFI_INVALID_PARAMETER  InterruptHandler is NULL, and a handler for
> +                                 InterruptType was not previously installed.
> +  @retval EFI_UNSUPPORTED        The interrupt specified by InterruptType
> +                                 is not supported.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CpuRegisterInterruptHandler (
> +  IN EFI_CPU_ARCH_PROTOCOL         *This,
> +  IN EFI_EXCEPTION_TYPE            InterruptType,
> +  IN EFI_CPU_INTERRUPT_HANDLER     InterruptHandler
> +  );
> +
> +/**
> +  Returns a timer value from one of the CPU's internal timers. There is no
> +  inherent time interval between ticks but is a function of the CPU 
> frequency.
> +
> +  @param  This                - Protocol instance structure.
> +  @param  TimerIndex          - Specifies which CPU timer is requested.
> +  @param  TimerValue          - Pointer to the returned timer value.
> +  @param  TimerPeriod         - A pointer to the amount of time that passes
> +                                in femtoseconds (10-15) for each increment
> +                                of TimerValue. If TimerValue does not
> +                                increment at a predictable rate, then 0 is
> +                                returned.  The amount of time that has
> +                                passed between two calls to GetTimerValue()
> +                                can be calculated with the formula
> +                                (TimerValue2 - TimerValue1) * TimerPeriod.
> +                                This parameter is optional and may be NULL.
> +
> +  @retval EFI_SUCCESS           - If the CPU timer count was returned.
> +  @retval EFI_UNSUPPORTED       - If the CPU does not have any readable 
> timers.
> +  @retval EFI_DEVICE_ERROR      - If an error occurred while reading the 
> timer.
> +  @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is 
> NULL.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CpuGetTimerValue (
> +  IN  EFI_CPU_ARCH_PROTOCOL       *This,
> +  IN  UINT32                      TimerIndex,
> +  OUT UINT64                      *TimerValue,
> +  OUT UINT64                      *TimerPeriod OPTIONAL
> +  );
> +
> +/**
> +  Set memory cacheability attributes for given range of memeory.
> +
> +  @param  This                   Protocol instance structure
> +  @param  BaseAddress            Specifies the start address of the
> +                                 memory range
> +  @param  Length                 Specifies the length of the memory range
> +  @param  Attributes             The memory cacheability for the memory range
> +
> +  @retval EFI_SUCCESS            If the cacheability of that memory range is
> +                                 set successfully
> +  @retval EFI_UNSUPPORTED        If the desired operation cannot be done
> +  @retval EFI_INVALID_PARAMETER  The input parameter is not correct,
> +                                 such as Length = 0
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CpuSetMemoryAttributes (
> +  IN EFI_CPU_ARCH_PROTOCOL      *This,
> +  IN EFI_PHYSICAL_ADDRESS       BaseAddress,
> +  IN UINT64                     Length,
> +  IN UINT64                     Attributes
> +  );
> +
> +#endif
> +
> diff --git a/RiscVPkg/Universal/CpuDxe/CpuDxe.inf 
> b/RiscVPkg/Universal/CpuDxe/CpuDxe.inf
> new file mode 100644
> index 0000000..93638e7
> --- /dev/null
> +++ b/RiscVPkg/Universal/CpuDxe/CpuDxe.inf
> @@ -0,0 +1,66 @@
> +## @file
> +#  RISC-V CPU DXE module.
> +#
> +#  Copyright (c) 2016 - 2019, Hewlett Packard Enterprise Development LP. All 
> rights reserved.<BR>
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of the BSD 
> License
> +#  which accompanies this distribution.  The full text of the license may be 
> found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
> IMPLIED.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = CpuDxe
> +  MODULE_UNI_FILE                = CpuDxe.uni
> +  FILE_GUID                      = 1A1E4886-9517-440e-9FDE-3BE44CEE2136
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +
> +  ENTRY_POINT                    = InitializeCpu
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  RiscVPkg/RiscVPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  BaseMemoryLib
> +  CpuLib
> +  DebugLib
> +  DxeServicesTableLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  UefiLib
> +  CpuExceptionHandlerLib
> +  TimerLib
> +  SynchronizationLib
> +  HobLib
> +  ReportStatusCodeLib
> +  RiscVCpuLib
> +  RiscVPlatformTimerLib
> +
> +[Sources]
> +  CpuDxe.c
> +  CpuDxe.h
> +
> +[Protocols]
> +  gEfiCpuArchProtocolGuid                       ## PRODUCES
> +
> +[Guids]
> +
> +[Ppis]
> +
> +[Pcd]
> +  gUefiRiscVPkgTokenSpaceGuid.PcdRiscVMachineTimerFrequencyInHerz
> +
> +[Depex]
> +  TRUE
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  CpuDxeExtra.uni
> diff --git a/RiscVPkg/Universal/CpuDxe/CpuDxe.uni 
> b/RiscVPkg/Universal/CpuDxe/CpuDxe.uni
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..51e3c0c06df37e5abb4be67ca2bc73d5da4cbdd2
> GIT binary patch
> literal 1564
> zcmb7^TW`}q5QXO%iT_}wFMyf^c;EpcMA90FfX2#&!c&!NYmwBI<F@3_1K*jA<1`cj
> zvb?jG*)wO(&hF12O>0`j|Aa5HH#WD_7B;ho_JG;u)<$+@nO)i1ay-uM!V3H!*~A`W
> zpW9P=W-siJ{(E-cI!56>iH-33Mw{D|_1G?%pE0^}tQGypj%jcB7anCvPhOFIw8R?N
> z7Ap&E6@BHSnQ4FSd#8B5vbOc?^_F*;M`Qyyr+7ymHzS7}PD{okVu@LShq#FE1RhH~
> zwYFy8CH@gJqYd|z-U74=U-@bG0`H0Q7c=3O_}V?)M7W_ZrAIcV)xK+Ip<F5^L8qm&
> zE>Xlxd{daD-d9c;Cs*xjTOUQG-Y%Dl>#b`sq5VDE6gEPX8bL3`S}~UPV|bQvbuK|y
> z@t?C2&Pc4k<F(J~t};Q*HC|)Se@+fT192*LlvS-2oW)D8NL8V#W99z2Yu%uqb3)BM
> z^;gV{@tj(HZ>0gs1%IVU)f-U5F}xBgscY|OTlR@@2US(6vIAy2)Y_0<>{<`)1RFCi
> zO#(u74jt}Kj7Q&*yYy7kYHL{G3blr9`&gsH9d@Uz3$^PJBRj>b=gdx+?|>?du1D`N
> z5_ioh<^W&$C~EL}i?5=8#eQH#%yoC;O_Y#DY+trG6?z9P5-LkEkGXNBZl#U<EeS7&
> z=JX$I>nGf!px+rtT`-2A#dZcG=_O@bs5OAkpS}Z5Q}^MViW$+W{!|lnu*9?mJ5@-*
> zs%mn@oX)EcZrwgJIwFT5wng3O9_TjB=oKJ_dz@f1#u>927&Xu2-?LFID4yabTmA3L
> c=<nIw&wUER)L%Zm8G57cX8iv-Hg>Z71xlCjC;$Ke
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/RiscVPkg/Universal/CpuDxe/CpuDxeExtra.uni 
> b/RiscVPkg/Universal/CpuDxe/CpuDxeExtra.uni
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..e6201a906ae37cfb24a6b501d9789d28f15b96f7
> GIT binary patch
> literal 1392
> zcmZXU+iwz45XR@(#Q))hzNl$I`{08yMqpP<Y=KbF`qXe~=|(7Ip%?t))!#RJYcZQW
> zmpL=veCM0l{rjh34GX+)c!GVlYfEflSN76gVAWaM)^=x+Jz@=ZYAc)C7@x#`W0_$)
> zx2>h@Z*6WH_G4DExADE@?8?Uiv6!>-we381ZZ~)adj<My=3{$n@9e!DvOWRf!C7tH
> zr%#5d{bEc#Pn>5-VJaRQXBsiy^Dbbqwk0cZ(GB`mXKr$`U{*wyUEEXr6rXzR49}0&
> zvVnan6{+|S;jC=I^R7Ti;k0C5D6qvts)_Fu9!orRw#(HDSjMi9SV+}PnMYA#6R;*k
> zi@%sj*#ckDvpmB+Yt?RS6Gp||5uwwRb-_f{NXh!NPGTm{1h2%`I$hBVRa}cIN9<3Z
> zajCR;a4n{c|KBztrx3*<(@VKF>~-r2Jd3=lOEBpw{@0vjH4^Jby!Kf=S0+<)hu0*J
> zU*#Hz)Aot7>a{Jk_~1RR{>apof9hJ-xqnJU8++<+uuR}Sv!lI}Iw&{1g(k(U`<z$|
> zt3G|yv#*RzJ7eEL(}1d)hgdsw+K5%`N{_6|9AmE#sw#B&x?()e9l6I!9j&p(EL@@1
> zm|MQr?y%$*><8!K)$@$nH_0SsUF;oDh0*iu19svrn{p2El8>@xUSIH4<WJ^roQS!;
> z+&IsY-6FP&5~o7%phcg)QqG9)t<bHQga4ZvZkO$#>>T}X^!Jf=m$|xqPzL1<F2U}B
> zIs!k&rwhw7R>9E@sGz>2IaMDss^`=PNBE1MveiJ7c5STRu{FIv)W_<{DWf_@U#=>7
> Q;n)$D#Qz^D@j@xye-~NTv;Y7A
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/RiscVPkg/Universal/CpuDxe/CpuMp.h 
> b/RiscVPkg/Universal/CpuDxe/CpuMp.h
> new file mode 100644
> index 0000000..adb3ef3
> --- /dev/null
> +++ b/RiscVPkg/Universal/CpuDxe/CpuMp.h
> @@ -0,0 +1,648 @@
> +/** @file
> +  RISC-V CPU DXE MP definitions.
> +
> +  Copyright (c) 2016, Hewlett Packard Enterprise Development LP. All rights 
> reserved.<BR>
> +
> +  This program and the accompanying materials are
> +  licensed and made available under the terms and conditions of the BSD 
> License
> +  which accompanies this distribution.  The full text of the license may be 
> found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
> IMPLIED.
> +
> +**/
> +
> +#ifndef _CPU_MP_H_
> +#define _CPU_MP_H_
> +
> +#include <Ppi/SecPlatformInformation.h>
> +#include <Ppi/SecPlatformInformation2.h>
> +#include <Protocol/MpService.h>
> +#include <Library/SynchronizationLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/ReportStatusCodeLib.h>
> +
> +/**
> +  Initialize Multi-processor support.
> +
> +**/
> +VOID
> +InitializeMpSupport (
> +  VOID
> +  );
> +
> +typedef
> +VOID
> +(EFIAPI *STACKLESS_AP_ENTRY_POINT)(
> +  VOID
> +  );
> +
> +/**
> +  Starts the Application Processors and directs them to jump to the
> +  specified routine.
> +
> +  The processor jumps to this code in flat mode, but the processor's
> +  stack is not initialized.
> +
> +  @retval EFI_SUCCESS           The APs were started
> +
> +**/
> +EFI_STATUS
> +StartApsStackless (
> +  VOID
> +  );
> +
> +/**
> +  The AP entry point that the Startup-IPI target code will jump to.
> +
> +  The processor jumps to this code in flat mode, but the processor's
> +  stack is not initialized.
> +
> +**/
> +VOID
> +EFIAPI
> +AsmApEntryPoint (
> +  VOID
> +  );
> +
> +/**
> +  Releases the lock preventing other APs from using the shared AP
> +  stack.
> +
> +  Once the AP has transitioned to using a new stack, it can call this
> +  function to allow another AP to proceed with using the shared stack.
> +
> +**/
> +VOID
> +EFIAPI
> +AsmApDoneWithCommonStack (
> +  VOID
> +  );
> +
> +typedef enum {
> +  CpuStateIdle,
> +  CpuStateBlocked,
> +  CpuStateReady,
> +  CpuStateBusy,
> +  CpuStateFinished,
> +  CpuStateSleeping
> +} CPU_STATE;
> +
> +/**
> +  Define Individual Processor Data block.
> +
> +**/
> +typedef struct {
> +  EFI_PROCESSOR_INFORMATION      Info;
> +  SPIN_LOCK                      CpuDataLock;
> +  INTN                           LockSelf;
> +  volatile CPU_STATE             State;
> +
> +  volatile EFI_AP_PROCEDURE      Procedure;
> +  volatile VOID*                 Parameter;
> +  BOOLEAN                        *Finished;
> +  INTN                           Timeout;
> +  EFI_EVENT                      WaitEvent;
> +  BOOLEAN                        TimeoutActive;
> +  EFI_EVENT                      CheckThisAPEvent;
> +  VOID                           *TopOfStack;
> +} CPU_DATA_BLOCK;
> +
> +/**
> +  Define MP data block which consumes individual processor block.
> +
> +**/
> +typedef struct {
> +  CPU_DATA_BLOCK              *CpuDatas;
> +  UINTN                       NumberOfProcessors;
> +  UINTN                       NumberOfEnabledProcessors;
> +
> +  EFI_AP_PROCEDURE            Procedure;
> +  VOID                        *ProcedureArgument;
> +  UINTN                       StartCount;
> +  UINTN                       FinishCount;
> +  BOOLEAN                     SingleThread;
> +  UINTN                       **FailedList;
> +  UINTN                       FailedListIndex;
> +  INTN                        Timeout;
> +  EFI_EVENT                   WaitEvent;
> +  BOOLEAN                     TimeoutActive;
> +  EFI_EVENT                   CheckAllAPsEvent;
> +} MP_SYSTEM_DATA;
> +
> +/**
> +  This function is called by all processors (both BSP and AP) once and 
> collects MP related data.
> +
> +  @param Bsp             TRUE if the CPU is BSP
> +  @param ProcessorNumber The specific processor number
> +
> +  @retval EFI_SUCCESS    Data for the processor collected and filled in
> +
> +**/
> +EFI_STATUS
> +FillInProcessorInformation (
> +  IN     BOOLEAN              Bsp,
> +  IN     UINTN                ProcessorNumber
> +  );
> +
> +/**
> +  This service retrieves the number of logical processor in the platform
> +  and the number of those logical processors that are enabled on this boot.
> +  This service may only be called from the BSP.
> +
> +  This function is used to retrieve the following information:
> +    - The number of logical processors that are present in the system.
> +    - The number of enabled logical processors in the system at the instant
> +      this call is made.
> +
> +  Because MP Service Protocol provides services to enable and disable 
> processors
> +  dynamically, the number of enabled logical processors may vary during the
> +  course of a boot session.
> +
> +  If this service is called from an AP, then EFI_DEVICE_ERROR is returned.
> +  If NumberOfProcessors or NumberOfEnabledProcessors is NULL, then
> +  EFI_INVALID_PARAMETER is returned. Otherwise, the total number of 
> processors
> +  is returned in NumberOfProcessors, the number of currently enabled 
> processor
> +  is returned in NumberOfEnabledProcessors, and EFI_SUCCESS is returned.
> +
> +  @param[in]  This                        A pointer to the 
> EFI_MP_SERVICES_PROTOCOL
> +                                          instance.
> +  @param[out] NumberOfProcessors          Pointer to the total number of 
> logical
> +                                          processors in the system, 
> including the BSP
> +                                          and disabled APs.
> +  @param[out] NumberOfEnabledProcessors   Pointer to the number of enabled 
> logical
> +                                          processors that exist in system, 
> including
> +                                          the BSP.
> +
> +  @retval EFI_SUCCESS             The number of logical processors and 
> enabled
> +                                  logical processors was retrieved.
> +  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
> +  @retval EFI_INVALID_PARAMETER   NumberOfProcessors is NULL.
> +  @retval EFI_INVALID_PARAMETER   NumberOfEnabledProcessors is NULL.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +GetNumberOfProcessors (
> +  IN  EFI_MP_SERVICES_PROTOCOL  *This,
> +  OUT UINTN                     *NumberOfProcessors,
> +  OUT UINTN                     *NumberOfEnabledProcessors
> +  );
> +
> +/**
> +  Gets detailed MP-related information on the requested processor at the
> +  instant this call is made. This service may only be called from the BSP.
> +
> +  This service retrieves detailed MP-related information about any processor
> +  on the platform. Note the following:
> +    - The processor information may change during the course of a boot 
> session.
> +    - The information presented here is entirely MP related.
> +
> +  Information regarding the number of caches and their sizes, frequency of 
> operation,
> +  slot numbers is all considered platform-related information and is not 
> provided
> +  by this service.
> +
> +  @param[in]  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL
> +                                    instance.
> +  @param[in]  ProcessorNumber       The handle number of processor.
> +  @param[out] ProcessorInfoBuffer   A pointer to the buffer where 
> information for
> +                                    the requested processor is deposited.
> +
> +  @retval EFI_SUCCESS             Processor information was returned.
> +  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
> +  @retval EFI_INVALID_PARAMETER   ProcessorInfoBuffer is NULL.
> +  @retval EFI_NOT_FOUND           The processor with the handle specified by
> +                                  ProcessorNumber does not exist in the 
> platform.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +GetProcessorInfo (
> +  IN  EFI_MP_SERVICES_PROTOCOL   *This,
> +  IN  UINTN                      ProcessorNumber,
> +  OUT EFI_PROCESSOR_INFORMATION  *ProcessorInfoBuffer
> +  );
> +
> +/**
> +  This service executes a caller provided function on all enabled APs. APs 
> can
> +  run either simultaneously or one at a time in sequence. This service 
> supports
> +  both blocking and non-blocking requests. The non-blocking requests use EFI
> +  events so the BSP can detect when the APs have finished. This service may 
> only
> +  be called from the BSP.
> +
> +  This function is used to dispatch all the enabled APs to the function 
> specified
> +  by Procedure.  If any enabled AP is busy, then EFI_NOT_READY is returned
> +  immediately and Procedure is not started on any AP.
> +
> +  If SingleThread is TRUE, all the enabled APs execute the function 
> specified by
> +  Procedure one by one, in ascending order of processor handle number. 
> Otherwise,
> +  all the enabled APs execute the function specified by Procedure 
> simultaneously.
> +
> +  If WaitEvent is NULL, execution is in blocking mode. The BSP waits until 
> all
> +  APs finish or TimeoutInMicroseconds expires. Otherwise, execution is in 
> non-blocking
> +  mode, and the BSP returns from this service without waiting for APs. If a
> +  non-blocking mode is requested after the UEFI Event 
> EFI_EVENT_GROUP_READY_TO_BOOT
> +  is signaled, then EFI_UNSUPPORTED must be returned.
> +
> +  If the timeout specified by TimeoutInMicroseconds expires before all APs 
> return
> +  from Procedure, then Procedure on the failed APs is terminated. All 
> enabled APs
> +  are always available for further calls to 
> EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
> +  and EFI_MP_SERVICES_PROTOCOL.StartupThisAP(). If FailedCpuList is not 
> NULL, its
> +  content points to the list of processor handle numbers in which Procedure 
> was
> +  terminated.
> +
> +  Note: It is the responsibility of the consumer of the 
> EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
> +  to make sure that the nature of the code that is executed on the BSP and 
> the
> +  dispatched APs is well controlled. The MP Services Protocol does not 
> guarantee
> +  that the Procedure function is MP-safe. Hence, the tasks that can be run in
> +  parallel are limited to certain independent tasks and well-controlled 
> exclusive
> +  code. EFI services and protocols may not be called by APs unless otherwise
> +  specified.
> +
> +  In blocking execution mode, BSP waits until all APs finish or
> +  TimeoutInMicroseconds expires.
> +
> +  In non-blocking execution mode, BSP is freed to return to the caller and 
> then
> +  proceed to the next task without having to wait for APs. The following
> +  sequence needs to occur in a non-blocking execution mode:
> +
> +    -# The caller that intends to use this MP Services Protocol in 
> non-blocking
> +       mode creates WaitEvent by calling the EFI CreateEvent() service.  The 
> caller
> +       invokes EFI_MP_SERVICES_PROTOCOL.StartupAllAPs(). If the parameter 
> WaitEvent
> +       is not NULL, then StartupAllAPs() executes in non-blocking mode. It 
> requests
> +       the function specified by Procedure to be started on all the enabled 
> APs,
> +       and releases the BSP to continue with other tasks.
> +    -# The caller can use the CheckEvent() and WaitForEvent() services to 
> check
> +       the state of the WaitEvent created in step 1.
> +    -# When the APs complete their task or TimeoutInMicroSecondss expires, 
> the MP
> +       Service signals WaitEvent by calling the EFI SignalEvent() function. 
> If
> +       FailedCpuList is not NULL, its content is available when WaitEvent is
> +       signaled. If all APs returned from Procedure prior to the timeout, 
> then
> +       FailedCpuList is set to NULL. If not all APs return from Procedure 
> before
> +       the timeout, then FailedCpuList is filled in with the list of the 
> failed
> +       APs. The buffer is allocated by MP Service Protocol using 
> AllocatePool().
> +       It is the caller's responsibility to free the buffer with FreePool() 
> service.
> +    -# This invocation of SignalEvent() function informs the caller that 
> invoked
> +       EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() that either all the APs 
> completed
> +       the specified task or a timeout occurred. The contents of 
> FailedCpuList
> +       can be examined to determine which APs did not complete the specified 
> task
> +       prior to the timeout.
> +
> +  @param[in]  This                    A pointer to the 
> EFI_MP_SERVICES_PROTOCOL
> +                                      instance.
> +  @param[in]  Procedure               A pointer to the function to be run on
> +                                      enabled APs of the system. See type
> +                                      EFI_AP_PROCEDURE.
> +  @param[in]  SingleThread            If TRUE, then all the enabled APs 
> execute
> +                                      the function specified by Procedure 
> one by
> +                                      one, in ascending order of processor 
> handle
> +                                      number.  If FALSE, then all the 
> enabled APs
> +                                      execute the function specified by 
> Procedure
> +                                      simultaneously.
> +  @param[in]  WaitEvent               The event created by the caller with 
> CreateEvent()
> +                                      service.  If it is NULL, then execute 
> in
> +                                      blocking mode. BSP waits until all APs 
> finish
> +                                      or TimeoutInMicroseconds expires.  If 
> it's
> +                                      not NULL, then execute in non-blocking 
> mode.
> +                                      BSP requests the function specified by
> +                                      Procedure to be started on all the 
> enabled
> +                                      APs, and go on executing immediately. 
> If
> +                                      all return from Procedure, or 
> TimeoutInMicroseconds
> +                                      expires, this event is signaled. The 
> BSP
> +                                      can use the CheckEvent() or 
> WaitForEvent()
> +                                      services to check the state of event.  
> Type
> +                                      EFI_EVENT is defined in CreateEvent() 
> in
> +                                      the Unified Extensible Firmware 
> Interface
> +                                      Specification.
> +  @param[in]  TimeoutInMicroseconds   Indicates the time limit in 
> microseconds for
> +                                      APs to return from Procedure, either 
> for
> +                                      blocking or non-blocking mode. Zero 
> means
> +                                      infinity.  If the timeout expires 
> before
> +                                      all APs return from Procedure, then 
> Procedure
> +                                      on the failed APs is terminated. All 
> enabled
> +                                      APs are available for next function 
> assigned
> +                                      by 
> EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
> +                                      or 
> EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
> +                                      If the timeout expires in blocking 
> mode,
> +                                      BSP returns EFI_TIMEOUT.  If the 
> timeout
> +                                      expires in non-blocking mode, WaitEvent
> +                                      is signaled with SignalEvent().
> +  @param[in]  ProcedureArgument       The parameter passed into Procedure for
> +                                      all APs.
> +  @param[out] FailedCpuList           If NULL, this parameter is ignored. 
> Otherwise,
> +                                      if all APs finish successfully, then 
> its
> +                                      content is set to NULL. If not all APs
> +                                      finish before timeout expires, then its
> +                                      content is set to address of the buffer
> +                                      holding handle numbers of the failed 
> APs.
> +                                      The buffer is allocated by MP Service 
> Protocol,
> +                                      and it's the caller's responsibility to
> +                                      free the buffer with FreePool() 
> service.
> +                                      In blocking mode, it is ready for 
> consumption
> +                                      when the call returns. In non-blocking 
> mode,
> +                                      it is ready when WaitEvent is 
> signaled.  The
> +                                      list of failed CPU is terminated by
> +                                      END_OF_CPU_LIST.
> +
> +  @retval EFI_SUCCESS             In blocking mode, all APs have finished 
> before
> +                                  the timeout expired.
> +  @retval EFI_SUCCESS             In non-blocking mode, function has been 
> dispatched
> +                                  to all enabled APs.
> +  @retval EFI_UNSUPPORTED         A non-blocking mode request was made after 
> the
> +                                  UEFI event EFI_EVENT_GROUP_READY_TO_BOOT 
> was
> +                                  signaled.
> +  @retval EFI_DEVICE_ERROR        Caller processor is AP.
> +  @retval EFI_NOT_STARTED         No enabled APs exist in the system.
> +  @retval EFI_NOT_READY           Any enabled APs are busy.
> +  @retval EFI_TIMEOUT             In blocking mode, the timeout expired 
> before
> +                                  all enabled APs have finished.
> +  @retval EFI_INVALID_PARAMETER   Procedure is NULL.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +StartupAllAPs (
> +  IN  EFI_MP_SERVICES_PROTOCOL  *This,
> +  IN  EFI_AP_PROCEDURE          Procedure,
> +  IN  BOOLEAN                   SingleThread,
> +  IN  EFI_EVENT                 WaitEvent               OPTIONAL,
> +  IN  UINTN                     TimeoutInMicroseconds,
> +  IN  VOID                      *ProcedureArgument      OPTIONAL,
> +  OUT UINTN                     **FailedCpuList         OPTIONAL
> +  );
> +
> +/**
> +  This service lets the caller get one enabled AP to execute a 
> caller-provided
> +  function. The caller can request the BSP to either wait for the completion
> +  of the AP or just proceed with the next task by using the EFI event 
> mechanism.
> +  See EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() for more details on 
> non-blocking
> +  execution support.  This service may only be called from the BSP.
> +
> +  This function is used to dispatch one enabled AP to the function specified 
> by
> +  Procedure passing in the argument specified by ProcedureArgument.  If 
> WaitEvent
> +  is NULL, execution is in blocking mode. The BSP waits until the AP 
> finishes or
> +  TimeoutInMicroSecondss expires. Otherwise, execution is in non-blocking 
> mode.
> +  BSP proceeds to the next task without waiting for the AP. If a 
> non-blocking mode
> +  is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is 
> signaled,
> +  then EFI_UNSUPPORTED must be returned.
> +
> +  If the timeout specified by TimeoutInMicroseconds expires before the AP 
> returns
> +  from Procedure, then execution of Procedure by the AP is terminated. The 
> AP is
> +  available for subsequent calls to EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() 
> and
> +  EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
> +
> +  @param[in]  This                    A pointer to the 
> EFI_MP_SERVICES_PROTOCOL
> +                                      instance.
> +  @param[in]  Procedure               A pointer to the function to be run on
> +                                      enabled APs of the system. See type
> +                                      EFI_AP_PROCEDURE.
> +  @param[in]  ProcessorNumber         The handle number of the AP. The range 
> is
> +                                      from 0 to the total number of logical
> +                                      processors minus 1. The total number of
> +                                      logical processors can be retrieved by
> +                                      
> EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
> +  @param[in]  WaitEvent               The event created by the caller with 
> CreateEvent()
> +                                      service.  If it is NULL, then execute 
> in
> +                                      blocking mode. BSP waits until all APs 
> finish
> +                                      or TimeoutInMicroseconds expires.  If 
> it's
> +                                      not NULL, then execute in non-blocking 
> mode.
> +                                      BSP requests the function specified by
> +                                      Procedure to be started on all the 
> enabled
> +                                      APs, and go on executing immediately. 
> If
> +                                      all return from Procedure or 
> TimeoutInMicroseconds
> +                                      expires, this event is signaled. The 
> BSP
> +                                      can use the CheckEvent() or 
> WaitForEvent()
> +                                      services to check the state of event.  
> Type
> +                                      EFI_EVENT is defined in CreateEvent() 
> in
> +                                      the Unified Extensible Firmware 
> Interface
> +                                      Specification.
> +  @param[in]  TimeoutInMicroseconds   Indicates the time limit in 
> microseconds for
> +                                      APs to return from Procedure, either 
> for
> +                                      blocking or non-blocking mode. Zero 
> means
> +                                      infinity.  If the timeout expires 
> before
> +                                      all APs return from Procedure, then 
> Procedure
> +                                      on the failed APs is terminated. All 
> enabled
> +                                      APs are available for next function 
> assigned
> +                                      by 
> EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
> +                                      or 
> EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
> +                                      If the timeout expires in blocking 
> mode,
> +                                      BSP returns EFI_TIMEOUT.  If the 
> timeout
> +                                      expires in non-blocking mode, WaitEvent
> +                                      is signaled with SignalEvent().
> +  @param[in]  ProcedureArgument       The parameter passed into Procedure for
> +                                      all APs.
> +  @param[out] Finished                If NULL, this parameter is ignored.  In
> +                                      blocking mode, this parameter is 
> ignored.
> +                                      In non-blocking mode, if AP returns 
> from
> +                                      Procedure before the timeout expires, 
> its
> +                                      content is set to TRUE. Otherwise, the
> +                                      value is set to FALSE. The caller can
> +                                      determine if the AP returned from 
> Procedure
> +                                      by evaluating this value.
> +
> +  @retval EFI_SUCCESS             In blocking mode, specified AP finished 
> before
> +                                  the timeout expires.
> +  @retval EFI_SUCCESS             In non-blocking mode, the function has been
> +                                  dispatched to specified AP.
> +  @retval EFI_UNSUPPORTED         A non-blocking mode request was made after 
> the
> +                                  UEFI event EFI_EVENT_GROUP_READY_TO_BOOT 
> was
> +                                  signaled.
> +  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
> +  @retval EFI_TIMEOUT             In blocking mode, the timeout expired 
> before
> +                                  the specified AP has finished.
> +  @retval EFI_NOT_READY           The specified AP is busy.
> +  @retval EFI_NOT_FOUND           The processor with the handle specified by
> +                                  ProcessorNumber does not exist.
> +  @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the BSP or 
> disabled AP.
> +  @retval EFI_INVALID_PARAMETER   Procedure is NULL.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +StartupThisAP (
> +  IN  EFI_MP_SERVICES_PROTOCOL  *This,
> +  IN  EFI_AP_PROCEDURE          Procedure,
> +  IN  UINTN                     ProcessorNumber,
> +  IN  EFI_EVENT                 WaitEvent               OPTIONAL,
> +  IN  UINTN                     TimeoutInMicroseconds,
> +  IN  VOID                      *ProcedureArgument      OPTIONAL,
> +  OUT BOOLEAN                   *Finished               OPTIONAL
> +  );
> +
> +/**
> +  This service switches the requested AP to be the BSP from that point 
> onward.
> +  This service changes the BSP for all purposes.   This call can only be 
> performed
> +  by the current BSP.
> +
> +  This service switches the requested AP to be the BSP from that point 
> onward.
> +  This service changes the BSP for all purposes. The new BSP can take over 
> the
> +  execution of the old BSP and continue seamlessly from where the old one 
> left
> +  off. This service may not be supported after the UEFI Event 
> EFI_EVENT_GROUP_READY_TO_BOOT
> +  is signaled.
> +
> +  If the BSP cannot be switched prior to the return from this service, then
> +  EFI_UNSUPPORTED must be returned.
> +
> +  @param[in] This              A pointer to the EFI_MP_SERVICES_PROTOCOL 
> instance.
> +  @param[in] ProcessorNumber   The handle number of AP that is to become the 
> new
> +                               BSP. The range is from 0 to the total number 
> of
> +                               logical processors minus 1. The total number 
> of
> +                               logical processors can be retrieved by
> +                               
> EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
> +  @param[in] EnableOldBSP      If TRUE, then the old BSP will be listed as an
> +                               enabled AP. Otherwise, it will be disabled.
> +
> +  @retval EFI_SUCCESS             BSP successfully switched.
> +  @retval EFI_UNSUPPORTED         Switching the BSP cannot be completed 
> prior to
> +                                  this service returning.
> +  @retval EFI_UNSUPPORTED         Switching the BSP is not supported.
> +  @retval EFI_SUCCESS             The calling processor is an AP.
> +  @retval EFI_NOT_FOUND           The processor with the handle specified by
> +                                  ProcessorNumber does not exist.
> +  @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the current BSP 
> or
> +                                  a disabled AP.
> +  @retval EFI_NOT_READY           The specified AP is busy.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SwitchBSP (
> +  IN EFI_MP_SERVICES_PROTOCOL  *This,
> +  IN  UINTN                    ProcessorNumber,
> +  IN  BOOLEAN                  EnableOldBSP
> +  );
> +
> +/**
> +  This service lets the caller enable or disable an AP from this point 
> onward.
> +  This service may only be called from the BSP.
> +
> +  This service allows the caller enable or disable an AP from this point 
> onward.
> +  The caller can optionally specify the health status of the AP by Health. If
> +  an AP is being disabled, then the state of the disabled AP is 
> implementation
> +  dependent. If an AP is enabled, then the implementation must guarantee 
> that a
> +  complete initialization sequence is performed on the AP, so the AP is in a 
> state
> +  that is compatible with an MP operating system. This service may not be 
> supported
> +  after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled.
> +
> +  If the enable or disable AP operation cannot be completed prior to the 
> return
> +  from this service, then EFI_UNSUPPORTED must be returned.
> +
> +  @param[in] This              A pointer to the EFI_MP_SERVICES_PROTOCOL 
> instance.
> +  @param[in] ProcessorNumber   The handle number of AP that is to become the 
> new
> +                               BSP. The range is from 0 to the total number 
> of
> +                               logical processors minus 1. The total number 
> of
> +                               logical processors can be retrieved by
> +                               
> EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
> +  @param[in] EnableAP          Specifies the new state for the processor for
> +                               enabled, FALSE for disabled.
> +  @param[in] HealthFlag        If not NULL, a pointer to a value that 
> specifies
> +                               the new health status of the AP. This flag
> +                               corresponds to StatusFlag defined in
> +                               EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). 
> Only
> +                               the PROCESSOR_HEALTH_STATUS_BIT is used. All 
> other
> +                               bits are ignored.  If it is NULL, this 
> parameter
> +                               is ignored.
> +
> +  @retval EFI_SUCCESS             The specified AP was enabled or disabled 
> successfully.
> +  @retval EFI_UNSUPPORTED         Enabling or disabling an AP cannot be 
> completed
> +                                  prior to this service returning.
> +  @retval EFI_UNSUPPORTED         Enabling or disabling an AP is not 
> supported.
> +  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
> +  @retval EFI_NOT_FOUND           Processor with the handle specified by 
> ProcessorNumber
> +                                  does not exist.
> +  @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the BSP.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +EnableDisableAP (
> +  IN  EFI_MP_SERVICES_PROTOCOL  *This,
> +  IN  UINTN                     ProcessorNumber,
> +  IN  BOOLEAN                   EnableAP,
> +  IN  UINT32                    *HealthFlag OPTIONAL
> +  );
> +
> +/**
> +  This return the handle number for the calling processor.  This service may 
> be
> +  called from the BSP and APs.
> +
> +  This service returns the processor handle number for the calling processor.
> +  The returned value is in the range from 0 to the total number of logical
> +  processors minus 1. The total number of logical processors can be retrieved
> +  with EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). This service may be
> +  called from the BSP and APs. If ProcessorNumber is NULL, then 
> EFI_INVALID_PARAMETER
> +  is returned. Otherwise, the current processors handle number is returned in
> +  ProcessorNumber, and EFI_SUCCESS is returned.
> +
> +  @param[in]  This             A pointer to the EFI_MP_SERVICES_PROTOCOL 
> instance.
> +  @param[out] ProcessorNumber  The handle number of AP that is to become the 
> new
> +                               BSP. The range is from 0 to the total number 
> of
> +                               logical processors minus 1. The total number 
> of
> +                               logical processors can be retrieved by
> +                               
> EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
> +
> +  @retval EFI_SUCCESS             The current processor handle number was 
> returned
> +                                  in ProcessorNumber.
> +  @retval EFI_INVALID_PARAMETER   ProcessorNumber is NULL.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +WhoAmI (
> +  IN EFI_MP_SERVICES_PROTOCOL  *This,
> +  OUT UINTN                    *ProcessorNumber
> +  );
> +
> +/**
> +  Terminate AP's task and set it to idle state.
> +
> +  This function terminates AP's task due to timeout by sending INIT-SIPI,
> +  and sends it to idle state.
> +
> +  @param CpuData           the pointer to CPU_DATA_BLOCK of specified AP
> +
> +**/
> +VOID
> +ResetProcessorToIdleState (
> +  IN CPU_DATA_BLOCK  *CpuData
> +  );
> +
> +/**
> +  Prepares Startup Code for APs.
> +  This function prepares Startup Code for APs.
> +
> +  @retval EFI_SUCCESS           The APs were started
> +  @retval EFI_OUT_OF_RESOURCES  Cannot allocate memory to start APs
> +
> +**/
> +EFI_STATUS
> +PrepareAPStartupCode (
> +  VOID
> +  );
> +
> +/**
> +  Free the code buffer of startup AP.
> +
> +**/
> +VOID
> +FreeApStartupCode (
> +  VOID
> +  );
> +
> +/**
> +  Resets the Application Processor and directs it to jump to the
> +  specified routine.
> +
> +  The processor jumps to this code in flat mode, but the processor's
> +  stack is not initialized.
> +
> +  @param ProcessorId           the AP of ProcessorId was reset
> +**/
> +VOID
> +ResetApStackless (
> +  IN UINT32 ProcessorId
> +  );
> +
> +#endif // _CPU_MP_H_
> +
> -- 
> 2.7.4
> 
> 
> 
> 

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

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

Reply via email to