Acked-by: Ray Ni <ray...@intel.com>

Thanks,
Ray
> -----Original Message-----
> From: Chao Li <lic...@loongson.cn>
> Sent: Tuesday, December 12, 2023 9:12 PM
> To: devel@edk2.groups.io
> Cc: Dong, Eric <eric.d...@intel.com>; Ni, Ray <ray...@intel.com>; Kumar,
> Rahul R <rahul.r.ku...@intel.com>; Gerd Hoffmann <kra...@redhat.com>;
> Baoqi Zhang <zhangba...@loongson.cn>
> Subject: [PATCH v4 11/37] UefiCpuPkg: Add CPU exception library for
> LoongArch
> 
> Added a new library named LoongArch64CpuExceptionHandlerLib, and
> modified the way LoongArch exceptions are expressed.
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4584
> 
> Cc: Eric Dong <eric.d...@intel.com>
> Cc: Ray Ni <ray...@intel.com>
> Cc: Rahul Kumar <rahul1.ku...@intel.com>
> Cc: Gerd Hoffmann <kra...@redhat.com>
> Signed-off-by: Chao Li <lic...@loongson.cn>
> Co-authored-by: Baoqi Zhang <zhangba...@loongson.cn>
> ---
>  MdePkg/Include/Protocol/DebugSupport.h        |  76 +++--
>  .../DxeCpuExceptionHandlerLib.inf             |  45 +++
>  .../DxeCpuExceptionHandlerLib.uni             |  15 +
>  .../DxeExceptionLib.c                         | 198 +++++++++++
>  .../ExceptionCommon.c                         | 170 ++++++++++
>  .../ExceptionCommon.h                         | 111 ++++++
>  .../LoongArch64/ArchExceptionHandler.c        | 213 ++++++++++++
>  .../LoongArch64/ExceptionHandlerAsm.S         | 320
> ++++++++++++++++++
>  .../SecPeiCpuExceptionHandlerLib.inf          |  45 +++
>  .../SecPeiCpuExceptionHandlerLib.uni          |  15 +
>  .../SecPeiExceptionLib.c                      |  88 +++++
>  UefiCpuPkg/UefiCpuPkg.dec                     |   6 +
>  UefiCpuPkg/UefiCpuPkg.dsc                     |   2 +
>  13 files changed, 1272 insertions(+), 32 deletions(-)
>  create mode 100644
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/DxeCpuException
> HandlerLib.inf
>  create mode 100644
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/DxeCpuException
> HandlerLib.uni
>  create mode 100644
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/DxeExceptionLib.c
>  create mode 100644
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/ExceptionCommon
> .c
>  create mode 100644
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/ExceptionCommon
> .h
>  create mode 100644
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/LoongArch64/Arch
> ExceptionHandler.c
>  create mode 100644
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/LoongArch64/Exce
> ptionHandlerAsm.S
>  create mode 100644
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiCpuExcepti
> onHandlerLib.inf
>  create mode 100644
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiCpuExcepti
> onHandlerLib.uni
>  create mode 100644
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiExceptionLi
> b.c
> 
> diff --git a/MdePkg/Include/Protocol/DebugSupport.h
> b/MdePkg/Include/Protocol/DebugSupport.h
> index 9742663619..ccdddd4828 100644
> --- a/MdePkg/Include/Protocol/DebugSupport.h
> +++ b/MdePkg/Include/Protocol/DebugSupport.h
> @@ -680,33 +680,45 @@ typedef struct {
>    UINT32    STVAL;
>  } EFI_SYSTEM_CONTEXT_RISCV64;
> 
> -//
> -// LoongArch processor exception types.
> -//
> -#define EXCEPT_LOONGARCH_INT   0
> -#define EXCEPT_LOONGARCH_PIL   1
> -#define EXCEPT_LOONGARCH_PIS   2
> -#define EXCEPT_LOONGARCH_PIF   3
> -#define EXCEPT_LOONGARCH_PME   4
> -#define EXCEPT_LOONGARCH_PNR   5
> -#define EXCEPT_LOONGARCH_PNX   6
> -#define EXCEPT_LOONGARCH_PPI   7
> -#define EXCEPT_LOONGARCH_ADE   8
> -#define EXCEPT_LOONGARCH_ALE   9
> -#define EXCEPT_LOONGARCH_BCE   10
> -#define EXCEPT_LOONGARCH_SYS   11
> -#define EXCEPT_LOONGARCH_BRK   12
> -#define EXCEPT_LOONGARCH_INE   13
> -#define EXCEPT_LOONGARCH_IPE   14
> -#define EXCEPT_LOONGARCH_FPD   15
> -#define EXCEPT_LOONGARCH_SXD   16
> -#define EXCEPT_LOONGARCH_ASXD  17
> -#define EXCEPT_LOONGARCH_FPE   18
> -#define EXCEPT_LOONGARCH_TBR   64 // For code only, there is no such
> type in the ISA spec, the TLB refill is defined for an independent exception.
> -
> -//
> -// LoongArch processor Interrupt types.
> -//
> +///
> +/// LoongArch processor exception types.
> +///
> +#define EXCEPT_LOONGARCH_ECODE_SHIFT  16
> +#define EXCEPT_LOONGARCH_INT          (0 <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_PIL          (1 <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_PIS          (2 <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_PIF          (3 <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_PME          (4 <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_PNR          (5 <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_PNX          (6 <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_PPI          (7 <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_ADE          (8 <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_ALE          (9 <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_BCE          (10  <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_SYS          (11  <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_BRK          (12  <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_INE          (13  <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_IPE          (14  <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_FPD          (15  <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_SXD          (16  <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_ASXD         (17  <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_FPE          (18  <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_WPE          (19  <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_BTD          (20  <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_BTE          (21  <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_GSPR         (22  <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_HVC          (23  <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +#define EXCEPT_LOONGARCH_GCXC         (24  <<
> EXCEPT_LOONGARCH_ECODE_SHIFT)
> +
> +///
> +/// For coding convenience, define the maximum valid
> +/// LoongArch exception.
> +///
> +#define MAX_LOONGARCH_EXCEPTION  64
> +
> +///
> +/// LoongArch processor Interrupt types.
> +///
>  #define EXCEPT_LOONGARCH_INT_SIP0   0
>  #define EXCEPT_LOONGARCH_INT_SIP1   1
>  #define EXCEPT_LOONGARCH_INT_IP0    2
> @@ -721,11 +733,11 @@ typedef struct {
>  #define EXCEPT_LOONGARCH_INT_TIMER  11
>  #define EXCEPT_LOONGARCH_INT_IPI    12
> 
> -//
> -// For coding convenience, define the maximum valid
> -// LoongArch interrupt.
> -//
> -#define MAX_LOONGARCH_INTERRUPT  14
> +///
> +/// For coding convenience, define the maximum valid
> +/// LoongArch interrupt.
> +///
> +#define MAX_LOONGARCH_INTERRUPT  16
> 
>  typedef struct {
>    UINT64    R0;
> diff --git
> a/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/DxeCpuExceptio
> nHandlerLib.inf
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/DxeCpuExceptio
> nHandlerLib.inf
> new file mode 100644
> index 0000000000..ade60fb3c7
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/DxeCpuExceptio
> nHandlerLib.inf
> @@ -0,0 +1,45 @@
> +## @file
> +#  LoongArch exception library instance for DXE modules.
> +#
> +#  Copyright (c) 2023, Loongson Technology Corporation Limited. All rights
> reserved.<BR>
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 1.29
> +  BASE_NAME                      = DxeCpuExceptionHandlerLib
> +  MODULE_UNI_FILE                = DxeCpuExceptionHandlerLib.uni
> +  FILE_GUID                      =
> 23C5D29F-F54B-091B-BD94-027576ED09FA
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  =
> CpuExceptionHandlerLib|DXE_CORE DXE_DRIVER UEFI_APPLICATION
> +
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +#  VALID_ARCHITECTURES           = LOONGARCH64
> +#
> +
> +[Sources.LoongArch64]
> +  LoongArch64/ArchExceptionHandler.c
> +  LoongArch64/ExceptionHandlerAsm.S | GCC
> +
> +[Sources]
> +  DxeExceptionLib.c
> +  ExceptionCommon.h
> +  ExceptionCommon.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  UefiCpuPkg/UefiCpuPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  CpuLib
> +  PeCoffGetEntryPointLib
> +  PrintLib
> +  SerialPortLib
> +  SynchronizationLib
> diff --git
> a/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/DxeCpuExceptio
> nHandlerLib.uni
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/DxeCpuExceptio
> nHandlerLib.uni
> new file mode 100644
> index 0000000000..d884387da3
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/DxeCpuExceptio
> nHandlerLib.uni
> @@ -0,0 +1,15 @@
> +// /** @file
> +// CPU Exception Handler library instance for DXE modules.
> +//
> +// CPU Exception Handler library instance for DXE modules.
> +//
> +// Copyright (c) 2023, Loongson Technology Corporation Limited. All rights
> reserved.<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "CPU
> Exception Handler library instance for DXE modules."
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "CPU
> Exception Handler library instance for DXE modules."
> diff --git
> a/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/DxeExceptionLib
> .c
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/DxeExceptionLib
> .c
> new file mode 100644
> index 0000000000..01d3b303f8
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/DxeExceptionLib
> .c
> @@ -0,0 +1,198 @@
> +/** @file DxeExceptionLib.c
> +
> +  LoongArch exception library implemenation for DXE modules.
> +
> +  Copyright (c) 2023, Loongson Technology Corporation Limited. All rights
> reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/BaseLib.h>
> +#include <Library/CpuExceptionHandlerLib.h>
> +#include <Library/CpuLib.h>
> +#include <Library/CacheMaintenanceLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/SerialPortLib.h>
> +#include <Protocol/DebugSupport.h>
> +#include <Register/LoongArch64/Csr.h>
> +
> +#include "ExceptionCommon.h"
> +
> +EFI_EXCEPTION_CALLBACK
> ExternalInterruptHandler[MAX_LOONGARCH_INTERRUPT + 1] = { 0 };
> +EFI_EXCEPTION_CALLBACK
> ExceptionHandler[MAX_LOONGARCH_EXCEPTION + 1]         = { 0 };
> +
> +/**
> +  Registers a function to be called from the processor interrupt or exception
> handler.
> +
> +  This function registers and enables the handler specified by
> InterruptHandler for a processor
> +  interrupt or exception type specified by InterruptType. If InterruptHandler
> is NULL, then the
> +  handler for the processor interrupt or exception type specified by
> InterruptType is uninstalled.
> +  The installed handler is called once for each processor interrupt or
> exception.
> +
> +  @param  InterruptType    A pointer to the processor's current
> interrupt state. Set to TRUE if interrupts
> +                           are enabled and FALSE if interrupts are
> disabled.
> +  @param  InterruptHandler A pointer to a function of type
> EFI_CPU_INTERRUPT_HANDLER that is called
> +                           when a processor interrupt occurs. If this
> parameter is NULL, then the handler
> +                           will be uninstalled.
> +
> +  @retval EFI_SUCCESS           The handler for the processor
> interrupt was successfully 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
> +RegisterCpuInterruptHandler (
> +  IN EFI_EXCEPTION_TYPE         InterruptType,
> +  IN EFI_CPU_INTERRUPT_HANDLER  InterruptHandler
> +  )
> +{
> +  EFI_EXCEPTION_TYPE  ExceptionType;
> +
> +  ExceptionType = InterruptType & CSR_ESTAT_EXC;
> +
> +  if (ExceptionType != 0) {
> +    //
> +    // Exception
> +    //
> +    if (ExceptionType > EXCEPT_LOONGARCH_FPE) {
> +      return EFI_UNSUPPORTED;
> +    }
> +
> +    ExceptionType >>= EXCEPT_LOONGARCH_ECODE_SHIFT;
> +
> +    if ((InterruptHandler == NULL) && (ExceptionHandler[InterruptType] ==
> NULL)) {
> +      return EFI_INVALID_PARAMETER;
> +    }
> +
> +    if ((InterruptHandler != NULL) && (ExceptionHandler[ExceptionType] !=
> NULL)) {
> +      return EFI_ALREADY_STARTED;
> +    }
> +
> +    ExceptionHandler[ExceptionType] = InterruptHandler;
> +  } else {
> +    //
> +    // Interrupt
> +    //
> +    if (InterruptType > MAX_LOONGARCH_INTERRUPT) {
> +      return EFI_UNSUPPORTED;
> +    }
> +
> +    if ((InterruptHandler == NULL) &&
> (ExternalInterruptHandler[InterruptType] == NULL)) {
> +      return EFI_INVALID_PARAMETER;
> +    }
> +
> +    if ((InterruptHandler != NULL) &&
> (ExternalInterruptHandler[InterruptType] != NULL)) {
> +      return EFI_ALREADY_STARTED;
> +    }
> +
> +    ExternalInterruptHandler[InterruptType] = InterruptHandler;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Common exception handler.
> +
> +  @param ExceptionType  Exception type.
> +  @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.
> +
> +**/
> +VOID
> +EFIAPI
> +CommonExceptionHandler (
> +  IN     EFI_EXCEPTION_TYPE  ExceptionType,
> +  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
> +  )
> +{
> +  EFI_EXCEPTION_TYPE  InterruptType;
> +
> +  if (ExceptionType == EXCEPT_LOONGARCH_INT) {
> +    //
> +    // Interrupt
> +    //
> +    InterruptType = GetInterruptType (SystemContext);
> +    if (InterruptType == 0xFF) {
> +      ExceptionType = InterruptType;
> +    } else {
> +      if ((ExternalInterruptHandler != NULL) &&
> (ExternalInterruptHandler[InterruptType] != NULL)) {
> +        ExternalInterruptHandler[InterruptType](InterruptType,
> SystemContext);
> +        return;
> +      }
> +    }
> +  } else if (ExceptionType == EXCEPT_LOONGARCH_FPD) {
> +    EnableFloatingPointUnits ();
> +    InitializeFloatingPointUnits ();
> +    return;
> +  } else {
> +    //
> +    // Exception
> +    //
> +    ExceptionType >>= EXCEPT_LOONGARCH_ECODE_SHIFT;
> +    if ((ExceptionHandler != NULL) &&
> (ExceptionHandler[ExceptionType] != NULL)) {
> +      ExceptionHandler[ExceptionType](ExceptionType, SystemContext);
> +      return;
> +    }
> +  }
> +
> +  //
> +  // Only the TLB refill exception use the same entry point as normal
> exceptions.
> +  //
> +  if (CsrRead (LOONGARCH_CSR_TLBRERA) & 0x1) {
> +    ExceptionType = mExceptionKnownNameNum - 1; // Use only to dump
> the exception context.
> +  }
> +
> +  DefaultExceptionHandler (ExceptionType, SystemContext);
> +}
> +
> +/**
> +  Initializes all CPU exceptions entries and provides the default exception
> handlers.
> +
> +  Caller should try to get an array of interrupt and/or exception vectors 
> that
> are in use and need to
> +  persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification.
> +  If caller cannot get reserved vector list or it does not exists, set 
> VectorInfo
> to NULL.
> +  If VectorInfo is not NULL, the exception vectors will be initialized per
> vector attribute accordingly.
> +
> +  @param[in]  VectorInfo    Pointer to reserved vector list.
> +
> +  @retval EFI_SUCCESS           CPU Exception Entries have been
> successfully initialized
> +                                with default exception handlers.
> +  @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content
> if VectorInfo is not NULL.
> +  @retval EFI_UNSUPPORTED       This function is not supported.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +InitializeCpuExceptionHandlers (
> +  IN EFI_VECTOR_HANDOFF_INFO  *VectorInfo OPTIONAL
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Setup separate stacks for certain exception handlers.
> +  If the input Buffer and BufferSize are both NULL, use global variable if
> possible.
> +
> +  @param[in]       Buffer        Point to buffer used to separate
> exception stack.
> +  @param[in, out]  BufferSize    On input, it indicates the byte size of
> Buffer.
> +                                 If the size is not enough, the return
> status will
> +                                 be EFI_BUFFER_TOO_SMALL, and
> output BufferSize
> +                                 will be the size it needs.
> +
> +  @retval EFI_SUCCESS             The stacks are assigned
> successfully.
> +  @retval EFI_UNSUPPORTED         This function is not supported.
> +  @retval EFI_BUFFER_TOO_SMALL    This BufferSize is too small.
> +**/
> +EFI_STATUS
> +EFIAPI
> +InitializeSeparateExceptionStacks (
> +  IN     VOID   *Buffer,
> +  IN OUT UINTN  *BufferSize
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> diff --git
> a/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/ExceptionComm
> on.c
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/ExceptionComm
> on.c
> new file mode 100644
> index 0000000000..f244b210df
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/ExceptionComm
> on.c
> @@ -0,0 +1,170 @@
> +/** @file DxeExceptionLib.c
> +
> +  CPU Exception Handler Library common functions.
> +
> +  Copyright (c) 2023, Loongson Technology Corporation Limited. All rights
> reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/BaseLib.h>
> +#include <Library/PeCoffGetEntryPointLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/SerialPortLib.h>
> +#include "ExceptionCommon.h"
> +
> +CONST CHAR8  mExceptionReservedStr[] = "Reserved";
> +CONST CHAR8  *mExceptionNameStr[]    = {
> +  "#INT - Interrupt(CSR.ECFG.VS=0)",
> +  "#PIL - Page invalid exception for Load option",
> +  "#PIS - Page invalid exception for Store operation",
> +  "#PIF - Page invalid exception for Fetch operation",
> +  "#PME - Page modification exception",
> +  "#PNR - Page non-readable exception",
> +  "#PNX - Page non-executable exception",
> +  "#PPI - Page privilege level illegal exception",
> +  "#ADE - Address error exception",
> +  "#ALE - Address alignment fault exception",
> +  "#BCE - Bound check exception",
> +  "#SYS - System call exception",
> +  "#BRK - Beeakpoint exception",
> +  "#INE - Instruction non-defined exception",
> +  "#IPE - Instruction privilege error exception",
> +  "#FPD - Floating-point instruction disable exception",
> +  "#SXD - 128-bit vector (SIMD instructions) expansion instruction disable
> exception",
> +  "#ASXD - 256-bit vector (Advanced SIMD instructions) expansion
> instruction disable exception",
> +  "#FPE - Floating-Point error exception",
> +  "#WPE - WatchPoint Exception for Fetch watchpoint or Memory
> load/store watchpoint",
> +  "#BTD - Binary Translation expansion instruction Disable exception",
> +  "#BTE - Binary Translation related exceptions",
> +  "#GSPR - Guest Sensitive Privileged Resource exception",
> +  "#HVC - HyperVisor Call exception",
> +  "#GCXC - Guest CSR Software/Hardware Change exception",
> +  "#TBR - TLB refill exception" // !!! NOTICE: Because the TLB refill
> exception is not instructed in ECODE, so the TLB refill exception must be the
> last one!
> +};
> +
> +INTN  mExceptionKnownNameNum = (sizeof (mExceptionNameStr) / sizeof
> (CHAR8 *));
> +
> +/**
> +  Get ASCII format string exception name by exception type.
> +
> +  @param ExceptionType  Exception type.
> +
> +  @return  ASCII format string exception name.
> +
> +**/
> +CONST CHAR8 *
> +GetExceptionNameStr (
> +  IN EFI_EXCEPTION_TYPE  ExceptionType
> +  )
> +{
> +  if ((UINTN)ExceptionType < mExceptionKnownNameNum) {
> +    return mExceptionNameStr[ExceptionType];
> +  } else {
> +    return mExceptionReservedStr;
> +  }
> +}
> +
> +/**
> +  Prints a message to the serial port.
> +
> +  @param  Format      Format string for the message to print.
> +  @param  ...         Variable argument list whose contents are
> accessed
> +                      based on the format string specified by Format.
> +
> +**/
> +VOID
> +EFIAPI
> +InternalPrintMessage (
> +  IN  CONST CHAR8  *Format,
> +  ...
> +  )
> +{
> +  CHAR8    Buffer[MAX_DEBUG_MESSAGE_LENGTH];
> +  VA_LIST  Marker;
> +
> +  //
> +  // Convert the message to an ASCII String
> +  //
> +  VA_START (Marker, Format);
> +  AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);
> +  VA_END (Marker);
> +
> +  //
> +  // Send the print string to a Serial Port
> +  //
> +  SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));
> +}
> +
> +/**
> +  Find and display image base address and return image base and its entry
> point.
> +
> +  @param CurrentEra      Current instruction pointer.
> +
> +**/
> +VOID
> +DumpModuleImageInfo (
> +  IN  UINTN  CurrentEra
> +  )
> +{
> +  EFI_STATUS  Status;
> +  UINTN       Pe32Data;
> +  VOID        *PdbPointer;
> +  VOID        *EntryPoint;
> +
> +  Pe32Data = PeCoffSearchImageBase (CurrentEra);
> +  if (Pe32Data == 0) {
> +    InternalPrintMessage ("!!!! Can't find image information. !!!!\n");
> +  } else {
> +    //
> +    // Find Image Base entry point
> +    //
> +    Status = PeCoffLoaderGetEntryPoint ((VOID *)Pe32Data, &EntryPoint);
> +    if (EFI_ERROR (Status)) {
> +      EntryPoint = NULL;
> +    }
> +
> +    InternalPrintMessage ("!!!! Find image based on IP(0x%x) ",
> CurrentEra);
> +    PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)Pe32Data);
> +    if (PdbPointer != NULL) {
> +      InternalPrintMessage ("%a", PdbPointer);
> +    } else {
> +      InternalPrintMessage ("(No PDB) ");
> +    }
> +
> +    InternalPrintMessage (
> +      " (ImageBase=%016lp, EntryPoint=%016p) !!!!\n",
> +      (VOID *)Pe32Data,
> +      EntryPoint
> +      );
> +  }
> +}
> +
> +/**
> +  Default exception handler.
> +
> +  @param ExceptionType  Exception type.
> +  @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.
> +
> +**/
> +VOID
> +EFIAPI
> +DefaultExceptionHandler (
> +  IN     EFI_EXCEPTION_TYPE  ExceptionType,
> +  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
> +  )
> +{
> +  //
> +  // Initialize the serial port before dumping.
> +  //
> +  SerialPortInitialize ();
> +  //
> +  // Display ExceptionType, CPU information and Image information
> +  //
> +  DumpImageAndCpuContent (ExceptionType, SystemContext);
> +
> +  //
> +  // Enter a dead loop.
> +  //
> +  CpuDeadLoop ();
> +}
> diff --git
> a/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/ExceptionComm
> on.h
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/ExceptionComm
> on.h
> new file mode 100644
> index 0000000000..b19144b196
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/ExceptionComm
> on.h
> @@ -0,0 +1,111 @@
> +/** @file DxeExceptionLib.h
> +
> +  Common header file for CPU Exception Handler Library.
> +
> +  Copyright (c) 2023, Loongson Technology Corporation Limited. All rights
> reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef EXCEPTION_COMMON_H_
> +#define EXCEPTION_COMMON_H_
> +
> +#define MAX_DEBUG_MESSAGE_LENGTH  0x100
> +
> +extern INTN  mExceptionKnownNameNum;
> +
> +/**
> +  Get ASCII format string exception name by exception type.
> +
> +  @param[in] ExceptionType  Exception type.
> +
> +  @return    ASCII format string exception name.
> +
> +**/
> +CONST CHAR8 *
> +GetExceptionNameStr (
> +  IN EFI_EXCEPTION_TYPE  ExceptionType
> +  );
> +
> +/**
> +  Prints a message to the serial port.
> +
> +  @param[in]  Format      Format string for the message to print.
> +  @param[in]  ...         Variable argument list whose contents are
> accessed
> +                      based on the format string specified by Format.
> +
> +**/
> +VOID
> +EFIAPI
> +InternalPrintMessage (
> +  IN  CONST CHAR8  *Format,
> +  ...
> +  );
> +
> +/**
> +  Find and display image base address and return image base and its entry
> point.
> +
> +  @param[in] CurrentEip      Current instruction pointer.
> +
> +**/
> +VOID
> +DumpModuleImageInfo (
> +  IN UINTN  CurrentEip
> +  );
> +
> +/**
> +  Default exception handler.
> +
> +  @param[in] ExceptionType  Exception type.
> +  @param[in] SystemContext  Pointer to EFI_SYSTEM_CONTEXT.
> +
> +**/
> +VOID
> +EFIAPI
> +DefaultExceptionHandler (
> +  IN     EFI_EXCEPTION_TYPE  ExceptionType,
> +  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
> +  );
> +
> +/**
> +  Display CPU information.
> +
> +  @param[in] ExceptionType  Exception type.
> +  @param[in] SystemContext  Pointer to EFI_SYSTEM_CONTEXT.
> +
> +**/
> +VOID
> +DumpImageAndCpuContent (
> +  IN EFI_EXCEPTION_TYPE  ExceptionType,
> +  IN EFI_SYSTEM_CONTEXT  SystemContext
> +  );
> +
> +/**
> +  Get exception types
> +
> +  @param[in]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT.
> +
> +  @return     Exception type.
> +
> +**/
> +EFI_EXCEPTION_TYPE
> +EFIAPI
> +GetExceptionType (
> +  IN EFI_SYSTEM_CONTEXT  SystemContext
> +  );
> +
> +/**
> +  Get Common interrupt types
> +
> +  @param[in] SystemContext  Pointer to EFI_SYSTEM_CONTEXT.
> +
> +  @return    Interrupt type.
> +
> +**/
> +EFI_EXCEPTION_TYPE
> +EFIAPI
> +GetInterruptType (
> +  IN EFI_SYSTEM_CONTEXT  SystemContext
> +  );
> +
> +#endif
> diff --git
> a/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/LoongArch64/Ar
> chExceptionHandler.c
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/LoongArch64/Ar
> chExceptionHandler.c
> new file mode 100644
> index 0000000000..757a5f93d1
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/LoongArch64/Ar
> chExceptionHandler.c
> @@ -0,0 +1,213 @@
> +/** @file ArchExceptionHandler.c
> +
> +  LoongArch64 CPU Exception Handler.
> +
> +  Copyright (c) 2023, Loongson Technology Corporation Limited. All rights
> reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/BaseLib.h>
> +#include <Register/LoongArch64/Csr.h>
> +#include "ExceptionCommon.h"
> +
> +/**
> +  Get Exception Type
> +
> +  @param[in] SystemContext  Pointer to EFI_SYSTEM_CONTEXT.
> +
> +  @return    LoongArch64 exception type.
> +
> +**/
> +EFI_EXCEPTION_TYPE
> +EFIAPI
> +GetExceptionType (
> +  IN EFI_SYSTEM_CONTEXT  SystemContext
> +  )
> +{
> +  EFI_EXCEPTION_TYPE  ExceptionType;
> +
> +  ExceptionType = (SystemContext.SystemContextLoongArch64->ESTAT &
> CSR_ESTAT_EXC);
> +  return ExceptionType;
> +}
> +
> +/**
> +  Get Interrupt Type
> +
> +  @param[in] SystemContext  Pointer to EFI_SYSTEM_CONTEXT.
> +
> +  @return    LoongArch64 intrrupt type.
> +
> +**/
> +EFI_EXCEPTION_TYPE
> +EFIAPI
> +GetInterruptType (
> +  IN EFI_SYSTEM_CONTEXT  SystemContext
> +  )
> +{
> +  EFI_EXCEPTION_TYPE  InterruptType;
> +
> +  for (InterruptType = 0; InterruptType <= EXCEPT_LOONGARCH_INT_IPI;
> InterruptType++) {
> +    if (SystemContext.SystemContextLoongArch64->ESTAT & (1 <<
> InterruptType)) {
> +      //
> +      // 0  - EXCEPT_LOONGARCH_INT_SIP0
> +      // 1  - EXCEPT_LOONGARCH_INT_SIP1
> +      // 2  - EXCEPT_LOONGARCH_INT_IP0
> +      // 3  - EXCEPT_LOONGARCH_INT_IP1
> +      // 4  - EXCEPT_LOONGARCH_INT_IP2
> +      // 5  - EXCEPT_LOONGARCH_INT_IP3
> +      // 6  - EXCEPT_LOONGARCH_INT_IP4
> +      // 7  - EXCEPT_LOONGARCH_INT_IP5
> +      // 8  - EXCEPT_LOONGARCH_INT_IP6
> +      // 9  - EXCEPT_LOONGARCH_INT_IP7
> +      // 10 - EXCEPT_LOONGARCH_INT_PMC
> +      // 11 - EXCEPT_LOONGARCH_INT_TIMER
> +      // 12 - EXCEPT_LOONGARCH_INT_IPI
> +      // Greater than EXCEPT_LOONGARCH_INI_IPI is currently invalid.
> +      //
> +      return InterruptType;
> +    }
> +  }
> +
> +  //
> +  // Invalid IRQ
> +  //
> +  return 0xFF;
> +}
> +
> +/**
> +  Display CPU information.
> +
> +  @param ExceptionType  Exception type.
> +  @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.
> +
> +**/
> +VOID
> +EFIAPI
> +DumpCpuContext (
> +  IN EFI_EXCEPTION_TYPE  ExceptionType,
> +  IN EFI_SYSTEM_CONTEXT  SystemContext
> +  )
> +{
> +  InternalPrintMessage (
> +    "\n!!!! LoongArch64 Exception Type - %02x(%a) !!!!\n",
> +    ExceptionType,
> +    GetExceptionNameStr (ExceptionType)
> +    );
> +
> +  //
> +  // Dump TLB refill ERA and BADV
> +  //
> +  if (ExceptionType == (mExceptionKnownNameNum - 1)) {
> +    InternalPrintMessage ("TLB refill ERA  0x%llx\n", (CsrRead
> (LOONGARCH_CSR_TLBRERA) & (~0x3ULL)));
> +    InternalPrintMessage ("TLB refill BADV  0x%llx\n", CsrRead
> (LOONGARCH_CSR_TLBRBADV));
> +  }
> +
> +  //
> +  // Dump the general registers
> +  //
> +  InternalPrintMessage (
> +    "Zero  - 0x%016lx, RA  - 0x%016lx, TP - 0x%016lx, SP - 0x%016lx\n",
> +    SystemContext.SystemContextLoongArch64->R0,
> +    SystemContext.SystemContextLoongArch64->R1,
> +    SystemContext.SystemContextLoongArch64->R2,
> +    SystemContext.SystemContextLoongArch64->R3
> +    );
> +  InternalPrintMessage (
> +    "  A0  - 0x%016lx, A1  - 0x%016lx, A2 - 0x%016lx, A3 - 0x%016lx\n",
> +    SystemContext.SystemContextLoongArch64->R4,
> +    SystemContext.SystemContextLoongArch64->R5,
> +    SystemContext.SystemContextLoongArch64->R6,
> +    SystemContext.SystemContextLoongArch64->R7
> +    );
> +  InternalPrintMessage (
> +    "  A4  - 0x%016lx, A5  - 0x%016lx, A6 - 0x%016lx, A7 - 0x%016lx\n",
> +    SystemContext.SystemContextLoongArch64->R8,
> +    SystemContext.SystemContextLoongArch64->R9,
> +    SystemContext.SystemContextLoongArch64->R10,
> +    SystemContext.SystemContextLoongArch64->R11
> +    );
> +  InternalPrintMessage (
> +    "  T0  - 0x%016lx, T1  - 0x%016lx, T2 - 0x%016lx, T3 - 0x%016lx\n",
> +    SystemContext.SystemContextLoongArch64->R12,
> +    SystemContext.SystemContextLoongArch64->R13,
> +    SystemContext.SystemContextLoongArch64->R14,
> +    SystemContext.SystemContextLoongArch64->R15
> +    );
> +  InternalPrintMessage (
> +    "  T4  - 0x%016lx, T5  - 0x%016lx, T6 - 0x%016lx, T7 - 0x%016lx\n",
> +    SystemContext.SystemContextLoongArch64->R16,
> +    SystemContext.SystemContextLoongArch64->R17,
> +    SystemContext.SystemContextLoongArch64->R18,
> +    SystemContext.SystemContextLoongArch64->R19
> +    );
> +  InternalPrintMessage (
> +    "  T8  - 0x%016lx, R21 - 0x%016lx, FP - 0x%016lx, S0 - 0x%016lx\n",
> +    SystemContext.SystemContextLoongArch64->R20,
> +    SystemContext.SystemContextLoongArch64->R21,
> +    SystemContext.SystemContextLoongArch64->R22,
> +    SystemContext.SystemContextLoongArch64->R23
> +    );
> +  InternalPrintMessage (
> +    "  S1  - 0x%016lx, S2  - 0x%016lx, S3 - 0x%016lx, S4 - 0x%016lx\n",
> +    SystemContext.SystemContextLoongArch64->R24,
> +    SystemContext.SystemContextLoongArch64->R25,
> +    SystemContext.SystemContextLoongArch64->R26,
> +    SystemContext.SystemContextLoongArch64->R27
> +    );
> +  InternalPrintMessage (
> +    "  S5  - 0x%016lx, S6  - 0x%016lx, S7 - 0x%016lx, S8 - 0x%016lx\n",
> +    SystemContext.SystemContextLoongArch64->R28,
> +    SystemContext.SystemContextLoongArch64->R29,
> +    SystemContext.SystemContextLoongArch64->R30,
> +    SystemContext.SystemContextLoongArch64->R31
> +    );
> +  InternalPrintMessage ("\n");
> +
> +  //
> +  // Dump the CSR registers
> +  //
> +  InternalPrintMessage (
> +    "CRMD  - 0x%016lx, PRMD  - 0x%016lx, EUEN - 0x%016lx, MISC -
> 0x%016lx\n",
> +    SystemContext.SystemContextLoongArch64->CRMD,
> +    SystemContext.SystemContextLoongArch64->PRMD,
> +    SystemContext.SystemContextLoongArch64->EUEN,
> +    SystemContext.SystemContextLoongArch64->MISC
> +    );
> +  InternalPrintMessage (
> +    "ECFG  - 0x%016lx, ESTAT - 0x%016lx, ERA  - 0x%016lx, BADV -
> 0x%016lx\n",
> +    SystemContext.SystemContextLoongArch64->ECFG,
> +    SystemContext.SystemContextLoongArch64->ESTAT,
> +    SystemContext.SystemContextLoongArch64->ERA,
> +    SystemContext.SystemContextLoongArch64->BADV
> +    );
> +  InternalPrintMessage (
> +    "BADI  - 0x%016lx\n",
> +    SystemContext.SystemContextLoongArch64->BADI
> +    );
> +}
> +
> +/**
> +  Display CPU information.
> +
> +  @param ExceptionType  Exception type.
> +  @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.
> +
> +**/
> +VOID
> +DumpImageAndCpuContent (
> +  IN EFI_EXCEPTION_TYPE  ExceptionType,
> +  IN EFI_SYSTEM_CONTEXT  SystemContext
> +  )
> +{
> +  DumpCpuContext (ExceptionType, SystemContext);
> +
> +  if (ExceptionType == (mExceptionKnownNameNum - 1)) {
> +    //
> +    // Dump TLB refill image info
> +    //
> +    DumpModuleImageInfo ((CsrRead (LOONGARCH_CSR_TLBRERA) &
> (~0x3ULL)));
> +  } else {
> +    DumpModuleImageInfo
> (SystemContext.SystemContextLoongArch64->ERA);
> +  }
> +}
> diff --git
> a/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/LoongArch64/Ex
> ceptionHandlerAsm.S
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/LoongArch64/Ex
> ceptionHandlerAsm.S
> new file mode 100644
> index 0000000000..9ce2dccd0f
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/LoongArch64/Ex
> ceptionHandlerAsm.S
> @@ -0,0 +1,320 @@
> +#------------------------------------------------------------------------------
> +#
> +# LoongArch64 ASM exception handler
> +#
> +# Copyright (c) 2023, Loongson Technology Corporation Limited. All rights
> reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +#------------------------------------------------------------------------------
> +
> +#include <Library/BaseLib.h>
> +#include <Library/CpuLib.h>
> +#include <Register/LoongArch64/Csr.h>
> +
> +#define RSIZE                 8           // 64 bit mode register
> size
> +#define GP_REG_CONTEXT_SIZE   32 * RSIZE  // General-purpose
> registers size
> +#define FP_REG_CONTEXT_SIZE   34 * RSIZE  // Floating-point registers
> size
> +#define CSR_REG_CONTEXT_SIZE  9  * RSIZE  // CSR registers size
> +
> +ASM_GLOBAL ASM_PFX(ExceptionEntry)
> +ASM_GLOBAL ASM_PFX(ExceptionEntryStart)
> +ASM_GLOBAL ASM_PFX(ExceptionEntryEnd)
> +
> +ASM_PFX(ExceptionEntry):
> +  move    $s0, $a0
> +  bl      GetExceptionType        // Exception type stored in register
> a0
> +  move    $a1, $s0                // SystemContxt
> +  bl      CommonExceptionHandler
> +
> +PopContext:
> +  //
> +  // Not sure if interrupts are turned on during the exception handler,
> anyway disable interrupts here.
> +  // It will be turned on when the instruction 'ertn' is executed.
> +  //
> +  bl      DisableInterrupts
> +
> +  bl      GetExceptionType        // Get current exception type, and
> stored in register a0
> +
> +  // Check whether the FPE is changed during interrupt handler, if ture
> restore it.
> +  ld.d    $t1, $sp, (LOONGARCH_CSR_EUEN * RSIZE +
> GP_REG_CONTEXT_SIZE)
> +  csrrd   $t0, LOONGARCH_CSR_EUEN        // Current EUEN
> +  andi    $t0, $t0, CSR_EUEN_FPEN
> +  andi    $t1, $t1, CSR_EUEN_FPEN
> +  li.d    $t2, EXCEPT_LOONGARCH_INT
> +  bne     $a0, $t2, PopRegs
> +  beq     $t0, $t1, PopRegs
> +  beqz    $t1, CloseFP
> +  bl      EnableFloatingPointUnits
> +  b       PopRegs
> +
> +CloseFP:
> +  bl      DisableFloatingPointUnits
> +
> +PopRegs:
> +  //
> +  // Pop CSR reigsters
> +  //
> +  addi.d  $sp, $sp, GP_REG_CONTEXT_SIZE
> +
> +  ld.d    $t0, $sp, LOONGARCH_CSR_CRMD * RSIZE
> +  csrwr   $t0, LOONGARCH_CSR_CRMD
> +  ld.d    $t0, $sp, LOONGARCH_CSR_PRMD * RSIZE
> +  csrwr   $t0, LOONGARCH_CSR_PRMD
> +  ld.d    $t0, $sp, LOONGARCH_CSR_ECFG * RSIZE
> +  csrwr   $t0, LOONGARCH_CSR_ECFG
> +  ld.d    $t0, $sp, LOONGARCH_CSR_ERA * RSIZE
> +  csrwr   $t0, LOONGARCH_CSR_ERA
> +
> +  addi.d  $sp, $sp, CSR_REG_CONTEXT_SIZE  // Fource change the stack
> pointer befor pop the FP registers.
> +
> +  beqz    $t1, PopGP                      // If the FPE not set, only
> pop the GP registers.
> +
> +  //
> +  // Pop FP registers
> +  //
> +  fld.d  $fa0, $sp, 0 * RSIZE
> +  fld.d  $fa1, $sp, 1 * RSIZE
> +  fld.d  $fa2, $sp, 2 * RSIZE
> +  fld.d  $fa3, $sp, 3 * RSIZE
> +  fld.d  $fa4, $sp, 4 * RSIZE
> +  fld.d  $fa5, $sp, 5 * RSIZE
> +  fld.d  $fa6, $sp, 6 * RSIZE
> +  fld.d  $fa7, $sp, 7 * RSIZE
> +  fld.d  $ft0, $sp, 8 * RSIZE
> +  fld.d  $ft1, $sp, 9 * RSIZE
> +  fld.d  $ft2, $sp, 10 * RSIZE
> +  fld.d  $ft3, $sp, 11 * RSIZE
> +  fld.d  $ft4, $sp, 12 * RSIZE
> +  fld.d  $ft5, $sp, 13 * RSIZE
> +  fld.d  $ft6, $sp, 14 * RSIZE
> +  fld.d  $ft7, $sp, 15 * RSIZE
> +  fld.d  $ft8, $sp, 16 * RSIZE
> +  fld.d  $ft9, $sp, 17 * RSIZE
> +  fld.d  $ft10, $sp, 18 * RSIZE
> +  fld.d  $ft11, $sp, 19 * RSIZE
> +  fld.d  $ft12, $sp, 20 * RSIZE
> +  fld.d  $ft13, $sp, 21 * RSIZE
> +  fld.d  $ft14, $sp, 22 * RSIZE
> +  fld.d  $ft15, $sp, 23 * RSIZE
> +  fld.d  $fs0, $sp, 24 * RSIZE
> +  fld.d  $fs1, $sp, 25 * RSIZE
> +  fld.d  $fs2, $sp, 26 * RSIZE
> +  fld.d  $fs3, $sp, 27 * RSIZE
> +  fld.d  $fs4, $sp, 28 * RSIZE
> +  fld.d  $fs5, $sp, 29 * RSIZE
> +  fld.d  $fs6, $sp, 30 * RSIZE
> +  fld.d  $fs7, $sp, 31 * RSIZE
> +
> +  ld.d        $t0, $sp, 32 * RSIZE
> +  movgr2fcsr  $r0, $t0             // Pop the fcsr0 register.
> +
> +  //
> +  // Pop the fcc0-fcc7 registers.
> +  //
> +  ld.d        $t0, $sp, 33 * RSIZE
> +  bstrpick.d  $t1, $t0, 7, 0
> +  movgr2cf    $fcc0, $t1
> +  bstrpick.d  $t1, $t0, 15, 8
> +  movgr2cf    $fcc1, $t1
> +  bstrpick.d  $t1, $t0, 23, 16
> +  movgr2cf    $fcc2, $t1
> +  bstrpick.d  $t1, $t0, 31, 24
> +  movgr2cf    $fcc3, $t1
> +  bstrpick.d  $t1, $t0, 39, 32
> +  movgr2cf    $fcc4, $t1
> +  bstrpick.d  $t1, $t0, 47, 40
> +  movgr2cf    $fcc5, $t1
> +  bstrpick.d  $t1, $t0, 55, 48
> +  movgr2cf    $fcc6, $t1
> +  bstrpick.d  $t1, $t0, 63, 56
> +  movgr2cf    $fcc7, $t1
> +
> +PopGP:
> +  //
> +  // Pop GP registers
> +  //
> +  addi.d  $sp, $sp, -(GP_REG_CONTEXT_SIZE + CSR_REG_CONTEXT_SIZE)
> +  ld.d    $ra, $sp, 1 * RSIZE
> +  ld.d    $tp, $sp, 2 * RSIZE
> +  ld.d    $a0, $sp, 4 * RSIZE
> +  ld.d    $a1, $sp, 5 * RSIZE
> +  ld.d    $a2, $sp, 6 * RSIZE
> +  ld.d    $a3, $sp, 7 * RSIZE
> +  ld.d    $a4, $sp, 8 * RSIZE
> +  ld.d    $a5, $sp, 9 * RSIZE
> +  ld.d    $a6, $sp, 10 * RSIZE
> +  ld.d    $a7, $sp, 11 * RSIZE
> +  ld.d    $t0, $sp, 12 * RSIZE
> +  ld.d    $t1, $sp, 13 * RSIZE
> +  ld.d    $t2, $sp, 14 * RSIZE
> +  ld.d    $t3, $sp, 15 * RSIZE
> +  ld.d    $t4, $sp, 16 * RSIZE
> +  ld.d    $t5, $sp, 17 * RSIZE
> +  ld.d    $t6, $sp, 18 * RSIZE
> +  ld.d    $t7, $sp, 19 * RSIZE
> +  ld.d    $t8, $sp, 20 * RSIZE
> +  ld.d    $r21, $sp, 21 * RSIZE
> +  ld.d    $fp, $sp, 22 * RSIZE
> +  ld.d    $s0, $sp, 23 * RSIZE
> +  ld.d    $s1, $sp, 24 * RSIZE
> +  ld.d    $s2, $sp, 25 * RSIZE
> +  ld.d    $s3, $sp, 26 * RSIZE
> +  ld.d    $s4, $sp, 27 * RSIZE
> +  ld.d    $s5, $sp, 28 * RSIZE
> +  ld.d    $s6, $sp, 29 * RSIZE
> +  ld.d    $s7, $sp, 30 * RSIZE
> +  ld.d    $s8, $sp, 31 * RSIZE
> +  ld.d    $sp, $sp, 3 * RSIZE
> +
> +  ertn // Returen from exception.
> +//
> +// End of ExceptionEntry
> +//
> +
> +ASM_PFX(ExceptionEntryStart):
> +  //
> +  // Store the old stack pointer in preparation for pushing the exception
> context onto the new stack.
> +  //
> +  csrwr   $sp, LOONGARCH_CSR_KS0
> +
> +  csrrd   $sp, LOONGARCH_CSR_KS0
> +
> +  //
> +  // Push GP registers
> +  //
> +  addi.d  $sp, $sp, -(GP_REG_CONTEXT_SIZE + FP_REG_CONTEXT_SIZE +
> CSR_REG_CONTEXT_SIZE)
> +  st.d    $zero, $sp, 0 * RSIZE
> +  st.d    $ra, $sp, 1 * RSIZE
> +  st.d    $tp, $sp, 2 * RSIZE
> +  st.d    $a0, $sp, 4 * RSIZE
> +  st.d    $a1, $sp, 5 * RSIZE
> +  st.d    $a2, $sp, 6 * RSIZE
> +  st.d    $a3, $sp, 7 * RSIZE
> +  st.d    $a4, $sp, 8 * RSIZE
> +  st.d    $a5, $sp, 9 * RSIZE
> +  st.d    $a6, $sp, 10 * RSIZE
> +  st.d    $a7, $sp, 11 * RSIZE
> +  st.d    $t0, $sp, 12 * RSIZE
> +  st.d    $t1, $sp, 13 * RSIZE
> +  st.d    $t2, $sp, 14 * RSIZE
> +  st.d    $t3, $sp, 15 * RSIZE
> +  st.d    $t4, $sp, 16 * RSIZE
> +  st.d    $t5, $sp, 17 * RSIZE
> +  st.d    $t6, $sp, 18 * RSIZE
> +  st.d    $t7, $sp, 19 * RSIZE
> +  st.d    $t8, $sp, 20 * RSIZE
> +  st.d    $r21, $sp, 21 * RSIZE
> +  st.d    $fp, $sp, 22 * RSIZE
> +  st.d    $s0, $sp, 23 * RSIZE
> +  st.d    $s1, $sp, 24 * RSIZE
> +  st.d    $s2, $sp, 25 * RSIZE
> +  st.d    $s3, $sp, 26 * RSIZE
> +  st.d    $s4, $sp, 27 * RSIZE
> +  st.d    $s5, $sp, 28 * RSIZE
> +  st.d    $s6, $sp, 29 * RSIZE
> +  st.d    $s7, $sp, 30 * RSIZE
> +  st.d    $s8, $sp, 31 * RSIZE
> +  csrrd   $t0, LOONGARCH_CSR_KS0  // Read the old stack pointer.
> +  st.d    $t0, $sp, 3 * RSIZE
> +
> +  //
> +  // Push CSR registers
> +  //
> +  addi.d  $sp, $sp, GP_REG_CONTEXT_SIZE
> +
> +  csrrd   $t0, LOONGARCH_CSR_CRMD
> +  st.d    $t0, $sp, LOONGARCH_CSR_CRMD * RSIZE
> +  csrrd   $t0, LOONGARCH_CSR_PRMD
> +  st.d    $t0, $sp, LOONGARCH_CSR_PRMD * RSIZE
> +  csrrd   $t0, LOONGARCH_CSR_EUEN
> +  st.d    $t0, $sp, LOONGARCH_CSR_EUEN * RSIZE
> +  csrrd   $t0, LOONGARCH_CSR_MISC
> +  st.d    $t0, $sp, LOONGARCH_CSR_MISC * RSIZE
> +  csrrd   $t0, LOONGARCH_CSR_ECFG
> +  st.d    $t0, $sp, LOONGARCH_CSR_ECFG * RSIZE
> +  csrrd   $t0, LOONGARCH_CSR_ESTAT
> +  st.d    $t0, $sp, LOONGARCH_CSR_ESTAT * RSIZE
> +  csrrd   $t0, LOONGARCH_CSR_ERA
> +  st.d    $t0, $sp, LOONGARCH_CSR_ERA * RSIZE
> +  csrrd   $t0, LOONGARCH_CSR_BADV
> +  st.d    $t0, $sp, LOONGARCH_CSR_BADV * RSIZE
> +  csrrd   $t0, LOONGARCH_CSR_BADI
> +  st.d    $t0, $sp, LOONGARCH_CSR_BADI * RSIZE
> +
> +  //
> +  // Push FP registers
> +  //
> +  addi.d  $sp, $sp, CSR_REG_CONTEXT_SIZE
> +
> +  csrrd   $t0, LOONGARCH_CSR_EUEN
> +  andi    $t0, $t0, CSR_EUEN_FPEN
> +  beqz    $t0, PushRegDone
> +
> +  fst.d  $fa0, $sp, 0 * RSIZE
> +  fst.d  $fa1, $sp, 1 * RSIZE
> +  fst.d  $fa2, $sp, 2 * RSIZE
> +  fst.d  $fa3, $sp, 3 * RSIZE
> +  fst.d  $fa4, $sp, 4 * RSIZE
> +  fst.d  $fa5, $sp, 5 * RSIZE
> +  fst.d  $fa6, $sp, 6 * RSIZE
> +  fst.d  $fa7, $sp, 7 * RSIZE
> +  fst.d  $ft0, $sp, 8 * RSIZE
> +  fst.d  $ft1, $sp, 9 * RSIZE
> +  fst.d  $ft2, $sp, 10 * RSIZE
> +  fst.d  $ft3, $sp, 11 * RSIZE
> +  fst.d  $ft4, $sp, 12 * RSIZE
> +  fst.d  $ft5, $sp, 13 * RSIZE
> +  fst.d  $ft6, $sp, 14 * RSIZE
> +  fst.d  $ft7, $sp, 15 * RSIZE
> +  fst.d  $ft8, $sp, 16 * RSIZE
> +  fst.d  $ft9, $sp, 17 * RSIZE
> +  fst.d  $ft10, $sp, 18 * RSIZE
> +  fst.d  $ft11, $sp, 19 * RSIZE
> +  fst.d  $ft12, $sp, 20 * RSIZE
> +  fst.d  $ft13, $sp, 21 * RSIZE
> +  fst.d  $ft14, $sp, 22 * RSIZE
> +  fst.d  $ft15, $sp, 23 * RSIZE
> +  fst.d  $fs0, $sp, 24 * RSIZE
> +  fst.d  $fs1, $sp, 25 * RSIZE
> +  fst.d  $fs2, $sp, 26 * RSIZE
> +  fst.d  $fs3, $sp, 27 * RSIZE
> +  fst.d  $fs4, $sp, 28 * RSIZE
> +  fst.d  $fs5, $sp, 29 * RSIZE
> +  fst.d  $fs6, $sp, 30 * RSIZE
> +  fst.d  $fs7, $sp, 31 * RSIZE
> +
> +  movfcsr2gr  $t3, $r0
> +  st.d        $t3, $sp, 32 * RSIZE  // Push the FCSR0 register.
> +
> +  //
> +  // Push the fcc0-fcc7 registers.
> +  //
> +  movcf2gr    $t3, $fcc0
> +  or          $t2, $t3, $zero
> +  movcf2gr    $t3, $fcc1
> +  bstrins.d   $t2, $t3, 0xf, 0x8
> +  movcf2gr    $t3, $fcc2
> +  bstrins.d   $t2, $t3, 0x17, 0x10
> +  movcf2gr    $t3, $fcc3
> +  bstrins.d   $t2, $t3, 0x1f, 0x18
> +  movcf2gr    $t3, $fcc4
> +  bstrins.d   $t2, $t3, 0x27, 0x20
> +  movcf2gr    $t3, $fcc5
> +  bstrins.d   $t2, $t3, 0x2f, 0x28
> +  movcf2gr    $t3, $fcc6
> +  bstrins.d   $t2, $t3, 0x37, 0x30
> +  movcf2gr    $t3, $fcc7
> +  bstrins.d   $t2, $t3, 0x3f, 0x38
> +  st.d        $t2, $sp, 33 * RSIZE
> +  //
> +  // Push exception context down
> +  //
> +
> +PushRegDone:
> +  addi.d  $sp, $sp, -(GP_REG_CONTEXT_SIZE + CSR_REG_CONTEXT_SIZE)
> +  move    $a0, $sp
> +  la.abs  $ra, ExceptionEntry
> +  jirl    $zero, $ra, 0
> +ASM_PFX(ExceptionEntryEnd):
> +.end
> diff --git
> a/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiCpuExcep
> tionHandlerLib.inf
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiCpuExcep
> tionHandlerLib.inf
> new file mode 100644
> index 0000000000..d99993470c
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiCpuExcep
> tionHandlerLib.inf
> @@ -0,0 +1,45 @@
> +## @file
> +#  LoongArch exception library instance for PEI and SEC modules.
> +#
> +#  Copyright (c) 2023, Loongson Technology Corporation Limited. All rights
> reserved.<BR>
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 1.29
> +  BASE_NAME                      = SecPeiCpuExceptionHandlerLib
> +  MODULE_UNI_FILE                =
> SecPeiCpuExceptionHandlerLib.uni
> +  FILE_GUID                      =
> 0D69E6CD-1423-F118-C4EF-7AA439BC3E3B
> +  MODULE_TYPE                    = PEIM
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = CpuExceptionHandlerLib|SEC
> PEI_CORE PEIM
> +
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +#  VALID_ARCHITECTURES           = LOONGARCH64
> +#
> +
> +[Sources.LoongArch64]
> +  LoongArch64/ArchExceptionHandler.c
> +  LoongArch64/ExceptionHandlerAsm.S | GCC
> +
> +[Sources]
> +  ExceptionCommon.h
> +  ExceptionCommon.c
> +  SecPeiExceptionLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  UefiCpuPkg/UefiCpuPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  CpuLib
> +  PeCoffGetEntryPointLib
> +  PrintLib
> +  SerialPortLib
> +  SynchronizationLib
> diff --git
> a/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiCpuExcep
> tionHandlerLib.uni
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiCpuExcep
> tionHandlerLib.uni
> new file mode 100644
> index 0000000000..81fd606278
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiCpuExcep
> tionHandlerLib.uni
> @@ -0,0 +1,15 @@
> +// /** @file
> +// CPU Exception Handler library instance for SEC/PEI modules.
> +//
> +// CPU Exception Handler library instance for SEC/PEI modules.
> +//
> +// Copyright (c) 2023, Loongson Technology Corporation Limited. All rights
> reserved.<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "CPU
> Exception Handler library instance for SEC/PEI modules."
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "CPU
> Exception Handler library instance for SEC/PEI modules."
> diff --git
> a/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiException
> Lib.c
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiException
> Lib.c
> new file mode 100644
> index 0000000000..fd01e6c411
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiException
> Lib.c
> @@ -0,0 +1,88 @@
> +/** @file SecPeiExceptionLib.c
> +
> +  LoongArch exception library implemenation for PEI and SEC modules.
> +
> +  Copyright (c) 2023, Loongson Technology Corporation Limited. All rights
> reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/BaseLib.h>
> +#include <Library/CpuLib.h>
> +#include <Library/CpuExceptionHandlerLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/SerialPortLib.h>
> +#include <Protocol/DebugSupport.h>
> +#include <Register/LoongArch64/Csr.h>
> +
> +#include "ExceptionCommon.h"
> +
> +/**
> +  Registers a function to be called from the processor interrupt or exception
> handler.
> +
> +  Always return EFI_UNSUPPORTED in the SEC exception initialization
> module.
> +
> +  @param  InterruptType    A pointer to the processor's current
> interrupt state. Set to TRUE if interrupts
> +                           are enabled and FALSE if interrupts are
> disabled.
> +  @param  InterruptHandler A pointer to a function of type
> EFI_CPU_INTERRUPT_HANDLER that is called
> +                           when a processor interrupt occurs. If this
> parameter is NULL, then the handler
> +                           will be uninstalled.
> +
> +  @retval EFI_UNSUPPORTED  The interrupt specified by InterruptType is
> not supported.
> +
> +**/
> +EFI_STATUS
> +RegisterCpuInterruptHandler (
> +  IN EFI_EXCEPTION_TYPE         InterruptType,
> +  IN EFI_CPU_INTERRUPT_HANDLER  InterruptHandler
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Common exception handler.
> +
> +  @param ExceptionType  Exception type.
> +  @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.
> +
> +**/
> +VOID
> +EFIAPI
> +CommonExceptionHandler (
> +  IN     EFI_EXCEPTION_TYPE  ExceptionType,
> +  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
> +  )
> +{
> +  //
> +  // APs may wake up by IPI IRQ during the SEC or PEI phase, clear the IPI
> interrupt and return.
> +  //
> +  if (GetInterruptType (SystemContext) == EXCEPT_LOONGARCH_INT_IPI) {
> +    DisableLocalInterrupts (1 << EXCEPT_LOONGARCH_INT_IPI);
> +    IoCsrWrite32 (LOONGARCH_IOCSR_IPI_CLEAR, IoCsrRead32
> (LOONGARCH_IOCSR_IPI_STATUS));
> +    return;
> +  } else {
> +    ExceptionType >>= EXCEPT_LOONGARCH_ECODE_SHIFT;
> +    DefaultExceptionHandler (ExceptionType, SystemContext);
> +  }
> +}
> +
> +/**
> +  Initializes all CPU exceptions entries and provides the default exception
> handlers.
> +
> +  Always return EFI_SUCCESS in the SEC exception initialization module.
> +
> +  @param[in]  VectorInfo    Pointer to reserved vector list.
> +
> +  @retval EFI_SUCCESS       CPU Exception Entries have been
> successfully initialized
> +                            with default exception handlers.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +InitializeCpuExceptionHandlers (
> +  IN EFI_VECTOR_HANDOFF_INFO  *VectorInfo OPTIONAL
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
> index 0b5431dbf7..154b1d06fe 100644
> --- a/UefiCpuPkg/UefiCpuPkg.dec
> +++ b/UefiCpuPkg/UefiCpuPkg.dec
> @@ -3,6 +3,7 @@
>  #
>  # Copyright (c) 2007 - 2023, Intel Corporation. All rights reserved.<BR>
>  # Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# Copyright (c) 2023, Loongson Technology Corporation Limited. All rights
> reserved.<BR>
>  #
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
> @@ -404,6 +405,11 @@
>    #  10 - 57bit mode.
> 
> gUefiCpuPkgTokenSpaceGuid.PcdCpuRiscVMmuMaxSatpMode|10|UINT32|0
> x60000021
> 
> +[PcdsFixedAtBuild.LoongArch64, PcdsPatchableInModule.LoongArch64,
> PcdsDynamic.LoongArch64, PcdsDynamicEx.LoongArch64]
> +  ## Contains the pointer to a CPU exception vector base address.
> +  # @Prompt The pointer to a CPU exception vector base address.
> +
> gUefiCpuPkgTokenSpaceGuid.PcdCpuExceptionVectorBaseAddress|0x0|UINT
> 64|0x62640000
> +
>  [PcdsDynamic, PcdsDynamicEx]
>    ## Contains the pointer to a CPU S3 data buffer of structure
> ACPI_CPU_DATA.
>    # @Prompt The pointer to a CPU S3 data buffer.
> diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
> index 8e34a9cd6b..872f20fc36 100644
> --- a/UefiCpuPkg/UefiCpuPkg.dsc
> +++ b/UefiCpuPkg/UefiCpuPkg.dsc
> @@ -207,6 +207,8 @@
> 
>  [Components.LOONGARCH64]
> 
> UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuTim
> erLib.inf
> +
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiCpuExcepti
> onHandlerLib.inf
> +
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/DxeCpuException
> HandlerLib.inf
> 
>  [BuildOptions]
>    *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
> --
> 2.27.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#112698): https://edk2.groups.io/g/devel/message/112698
Mute This Topic: https://groups.io/mt/103129093/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: 
https://edk2.groups.io/g/devel/leave/9847357/21656/1706620634/xyzzy 
[arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to