From: "Ni, Ray" <ray.ni@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
"lichao@loongson.cn" <lichao@loongson.cn>
Cc: "Dong, Eric" <eric.dong@intel.com>,
"Kumar, Rahul R" <rahul.r.kumar@intel.com>,
Gerd Hoffmann <kraxel@redhat.com>,
Baoqi Zhang <zhangbaoqi@loongson.cn>
Subject: Re: [edk2-devel] [PATCH v7 12/37] UefiCpuPkg: Add CPU exception library for LoongArch
Date: Fri, 12 Jan 2024 08:49:12 +0000 [thread overview]
Message-ID: <MN6PR11MB824495CC04BEB9496B96E0888C6F2@MN6PR11MB8244.namprd11.prod.outlook.com> (raw)
In-Reply-To: <20240112082356.3288403-1-lichao@loongson.cn>
Chao,
Do you mind putting the lib content under UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch64/?
It also follows the guidelines and avoid creating too much folders under Library folder.
Thanks,
Ray
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Chao Li
> Sent: Friday, January 12, 2024 4:24 PM
> To: devel@edk2.groups.io
> Cc: Dong, Eric <eric.dong@intel.com>; Ni, Ray <ray.ni@intel.com>; Kumar,
> Rahul R <rahul.r.kumar@intel.com>; Gerd Hoffmann <kraxel@redhat.com>;
> Baoqi Zhang <zhangbaoqi@loongson.cn>
> Subject: [edk2-devel] [PATCH v7 12/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.dong@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Rahul Kumar <rahul1.kumar@intel.com>
> Cc: Gerd Hoffmann <kraxel@redhat.com>
> Signed-off-by: Chao Li <lichao@loongson.cn>
> Co-authored-by: Baoqi Zhang <zhangbaoqi@loongson.cn>
> Acked-by: Ray Ni <ray.ni@intel.com>
> ---
> .../DxeCpuExceptionHandlerLib.inf | 45 +++
> .../DxeCpuExceptionHandlerLib.uni | 15 +
> .../DxeExceptionLib.c | 198 +++++++++++
> .../ExceptionCommon.c | 229 +++++++++++++
> .../ExceptionCommon.h | 131 +++++++
> .../LoongArch64/ArchExceptionHandler.c | 213 ++++++++++++
> .../LoongArch64/ExceptionHandlerAsm.S | 320 ++++++++++++++++++
> .../SecPeiCpuExceptionHandlerLib.inf | 45 +++
> .../SecPeiCpuExceptionHandlerLib.uni | 15 +
> .../SecPeiExceptionLib.c | 102 ++++++
> UefiCpuPkg/UefiCpuPkg.dec | 6 +
> UefiCpuPkg/UefiCpuPkg.dsc | 2 +
> 12 files changed, 1321 insertions(+)
> 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/ExceptionCommo
> n.c
> create mode 100644
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/ExceptionCommo
> n.h
> create mode 100644
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/LoongArch64/Arc
> hExceptionHandler.c
> create mode 100644
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/LoongArch64/Exc
> eptionHandlerAsm.S
> create mode 100644
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiCpuExceptio
> nHandlerLib.inf
> create mode 100644
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiCpuExceptio
> nHandlerLib.uni
> create mode 100644
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiExceptionLib
> .c
>
> diff --git
> a/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/DxeCpuExceptio
> nHandlerLib.inf
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/DxeCpuExceptio
> nHandlerLib.inf
> new file mode 100644
> index 0000000000..0ce8abe98d
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/DxeCpuExceptio
> nHandlerLib.inf
> @@ -0,0 +1,45 @@
> +## @file
> +# LoongArch exception library instance for DXE modules.
> +#
> +# Copyright (c) 2024, 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..25b1593666
> --- /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) 2024, 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..2c5d202b33
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/DxeExceptionLib
> .c
> @@ -0,0 +1,198 @@
> +/** @file DxeExceptionLib.c
> +
> + LoongArch exception library implemenation for DXE modules.
> +
> + Copyright (c) 2024, 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 >>= CSR_ESTAT_EXC_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 >>= CSR_ESTAT_EXC_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..4258fe44e2
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/ExceptionComm
> on.c
> @@ -0,0 +1,229 @@
> +/** @file DxeExceptionLib.c
> +
> + CPU Exception Handler Library common functions.
> +
> + Copyright (c) 2024, 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 <Register/LoongArch64/Csr.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
> + );
> + }
> +}
> +
> +/**
> + IPI Interrupt Handler.
> +
> + @param InterruptType The type of interrupt that occurred
> + @param SystemContext A pointer to the system context when the
> interrupt occurred
> +**/
> +VOID
> +EFIAPI
> +IpiInterruptHandler (
> + IN EFI_EXCEPTION_TYPE InterruptType,
> + IN EFI_SYSTEM_CONTEXT SystemContext
> + )
> +{
> + UINTN ResumeVector;
> + UINTN Parameter;
> +
> + //
> + // Clear interrupt.
> + //
> + IoCsrWrite32 (LOONGARCH_IOCSR_IPI_CLEAR, IoCsrRead32
> (LOONGARCH_IOCSR_IPI_STATUS));
> +
> + //
> + // Get the resume vector and parameter if populated.
> + //
> + ResumeVector = IoCsrRead64 (LOONGARCH_IOCSR_MBUF0);
> + Parameter = IoCsrRead64 (LOONGARCH_IOCSR_MBUF3);
> +
> + //
> + // Clean up current processor mailbox 0 and mailbox 3.
> + //
> + IoCsrWrite64 (LOONGARCH_IOCSR_MBUF0, 0x0);
> + IoCsrWrite64 (LOONGARCH_IOCSR_MBUF3, 0x0);
> +
> + //
> + // If mailbox 0 is non-NULL, it means that the BSP or other cores called the
> IPI to wake
> + // up the current core and let it use the resume vector stored in mailbox 0.
> + //
> + if (ResumeVector != 0) {
> + SystemContext.SystemContextLoongArch64->ERA = ResumeVector;
> + //
> + // Only kernel stage BSP calls IPI without parameters. Clean up the PIE and
> make sure
> + // global interrupts are turned off for the current processor when jumping
> to the kernel.
> + //
> + if (Parameter == 0) {
> + SystemContext.SystemContextLoongArch64->PRMD &= ~BIT2;
> + } else {
> + //
> + // If both the resume vector and parameter are non-NULL, it means that
> the IPI was
> + // called in the BIOS. Set $a0 as APIC ID and $a1 as parameter value.
> + //
> + SystemContext.SystemContextLoongArch64->R4 = CsrRead
> (LOONGARCH_CSR_CPUNUM);
> + SystemContext.SystemContextLoongArch64->R5 = Parameter;
> + }
> + }
> +
> + MemoryFence ();
> +}
> +
> +/**
> + 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..e326b73e3f
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/ExceptionComm
> on.h
> @@ -0,0 +1,131 @@
> +/** @file DxeExceptionLib.h
> +
> + Common header file for CPU Exception Handler Library.
> +
> + Copyright (c) 2024, 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
> +
> +//
> +// For coding convenience, define the maximum valid
> +// LoongArch exception.
> +// Since UEFI V2.11, it will be present in DebugSupport.h.
> +//
> +#define MAX_LOONGARCH_EXCEPTION 64
> +
> +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
> + );
> +
> +/**
> + IPI Interrupt Handler.
> +
> + @param InterruptType The type of interrupt that occurred
> + @param SystemContext A pointer to the system context when the
> interrupt occurred
> +**/
> +VOID
> +EFIAPI
> +IpiInterruptHandler (
> + IN EFI_EXCEPTION_TYPE InterruptType,
> + IN EFI_SYSTEM_CONTEXT SystemContext
> + );
> +
> +/**
> + 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/A
> rchExceptionHandler.c
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/LoongArch64/A
> rchExceptionHandler.c
> new file mode 100644
> index 0000000000..04e6d17c45
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/LoongArch64/A
> rchExceptionHandler.c
> @@ -0,0 +1,213 @@
> +/** @file ArchExceptionHandler.c
> +
> + LoongArch64 CPU Exception Handler.
> +
> + Copyright (c) 2024, 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/E
> xceptionHandlerAsm.S
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/LoongArch64/E
> xceptionHandlerAsm.S
> new file mode 100644
> index 0000000000..15d84baa77
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/LoongArch64/E
> xceptionHandlerAsm.S
> @@ -0,0 +1,320 @@
> +#------------------------------------------------------------------------------
> +#
> +# LoongArch64 ASM exception handler
> +#
> +# Copyright (c) 2024, 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..437c92e26d
> --- /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) 2024, 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..591cddc87b
> --- /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) 2024, 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..7588d2050b
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiException
> Lib.c
> @@ -0,0 +1,102 @@
> +/** @file SecPeiExceptionLib.c
> +
> + LoongArch exception library implemenation for PEI and SEC modules.
> +
> + Copyright (c) 2024, 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
> + )
> +{
> + EFI_EXCEPTION_TYPE InterruptType;
> +
> + if (ExceptionType == EXCEPT_LOONGARCH_INT) {
> + //
> + // Interrupt
> + //
> + InterruptType = GetInterruptType (SystemContext);
> + if (InterruptType == EXCEPT_LOONGARCH_INT_IPI) {
> + //
> + // APs may wake up via IPI IRQ during the SEC or PEI phase, clear the IPI
> interrupt and
> + // perform the remaining work.
> + //
> + IpiInterruptHandler (InterruptType, SystemContext);
> + return;
> + } else {
> + ExceptionType = InterruptType;
> + }
> + } else {
> + //
> + // Exception
> + //
> + ExceptionType >>= CSR_ESTAT_EXC_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 cc785a3222..84f61254bb 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) 2024, Loongson Technology Corporation Limited. All rights
> reserved.<BR>
> #
> # SPDX-License-Identifier: BSD-2-Clause-Patent
> #
> @@ -410,6 +411,11 @@
> # 10 - 57bit mode.
>
> gUefiCpuPkgTokenSpaceGuid.PcdCpuRiscVMmuMaxSatpMode|10|UINT32|
> 0x60000021
>
> +[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 a977884c3d..0b8ea858b2 100644
> --- a/UefiCpuPkg/UefiCpuPkg.dsc
> +++ b/UefiCpuPkg/UefiCpuPkg.dsc
> @@ -209,6 +209,8 @@
>
> [Components.LOONGARCH64]
>
> UefiCpuPkg/Library/BaseLoongArch64CpuTimerLib/BaseLoongArch64CpuTim
> erLib.inf
> +
> UefiCpuPkg/Library/LoongArch64CpuExceptionHandlerLib/SecPeiCpuExceptio
> nHandlerLib.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 (#113693): https://edk2.groups.io/g/devel/message/113693
Mute This Topic: https://groups.io/mt/103679446/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/leave/12367111/7686176/1913456212/xyzzy [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
next prev parent reply other threads:[~2024-01-12 8:49 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-12 8:21 [edk2-devel] [PATCH v7 00/37] Enable LoongArch virtual machine in edk2 Chao Li
2024-01-12 8:22 ` [edk2-devel] [PATCH v7 01/37] MdePkg: Add the header file named Csr.h for LoongArch64 Chao Li
2024-01-12 8:22 ` [edk2-devel] [PATCH v7 02/37] MdePkg: Add LoongArch64 FPU function set into BaseCpuLib Chao Li
2024-01-12 8:22 ` [edk2-devel] [PATCH v7 03/37] MdePkg: Add LoongArch64 exception function set into BaseLib Chao Li
2024-01-12 8:23 ` [edk2-devel] [PATCH v7 04/37] MdePkg: Add LoongArch64 local interrupt " Chao Li
2024-01-12 8:23 ` [edk2-devel] [PATCH v7 05/37] MdePkg: Add LoongArch Cpucfg function Chao Li
2024-01-12 8:23 ` [edk2-devel] [PATCH v7 06/37] MdePkg: Add read stable counter operation for LoongArch Chao Li
2024-01-12 8:23 ` [edk2-devel] [PATCH v7 07/37] MdePkg: Add CSR " Chao Li
2024-01-12 8:23 ` [edk2-devel] [PATCH v7 08/37] MdePkg: Add IOCSR " Chao Li
2024-01-12 8:23 ` [edk2-devel] [PATCH v7 09/37] MdePkg: Add a new library named PeiServicesTablePointerLibKs0 Chao Li
2024-01-12 8:23 ` [edk2-devel] [PATCH v7 10/37] MdePkg: Add some comments for LoongArch exceptions Chao Li
2024-01-12 8:23 ` [edk2-devel] [PATCH v7 11/37] UefiCpuPkg: Add LoongArch64 CPU Timer library Chao Li
2024-01-12 8:51 ` Ni, Ray
2024-01-12 9:15 ` Chao Li
2024-01-12 9:26 ` Ni, Ray
2024-01-12 8:23 ` [edk2-devel] [PATCH v7 12/37] UefiCpuPkg: Add CPU exception library for LoongArch Chao Li
2024-01-12 8:49 ` Ni, Ray [this message]
2024-01-12 8:24 ` [edk2-devel] [PATCH v7 13/37] UefiCpuPkg: Add CpuMmuLib.h to UefiCpuPkg Chao Li
2024-01-12 8:24 ` [edk2-devel] [PATCH v7 14/37] UefiCpuPkg: Add LoongArch64CpuMmuLib " Chao Li
2024-01-12 8:24 ` [edk2-devel] [PATCH v7 15/37] UefiCpuPkg: Add multiprocessor library for LoongArch64 Chao Li
2024-01-12 8:50 ` Ni, Ray
2024-01-12 8:24 ` [edk2-devel] [PATCH v7 16/37] UefiCpuPkg: Add CpuDxe driver " Chao Li
2024-01-12 8:50 ` Ni, Ray
2024-01-12 8:24 ` [edk2-devel] [PATCH v7 17/37] EmbeddedPkg: Add PcdPrePiCpuIoSize width for LOONGARCH64 Chao Li
2024-01-12 8:24 ` [edk2-devel] [PATCH v7 18/37] ArmVirtPkg: Move PCD of FDT base address and FDT padding to OvmfPkg Chao Li
2024-01-12 8:24 ` [edk2-devel] [PATCH v7 19/37] UefiCpuPkg: Add a new CPU IO 2 driver named CpuMmio2Dxe Chao Li
2024-01-12 8:24 ` [edk2-devel] [PATCH v7 20/37] ArmVirtPkg: Enable CpuMmio2Dxe Chao Li
2024-01-12 8:25 ` [edk2-devel] [PATCH v7 21/37] OvmfPkg/RiscVVirt: " Chao Li
2024-01-12 8:25 ` [edk2-devel] [PATCH v7 22/37] OvmfPkg/RiscVVirt: Remove PciCpuIo2Dxe from RiscVVirt Chao Li
2024-01-12 8:25 ` [edk2-devel] [PATCH v7 23/37] ArmVirtPkg: Move the FdtSerialPortAddressLib to OvmfPkg Chao Li
2024-01-15 8:32 ` Laszlo Ersek
2024-01-16 12:20 ` Chao Li
2024-01-12 8:25 ` [edk2-devel] [PATCH v7 24/37] ArmVirtPkg: Move two PCD variables into OvmfPkg Chao Li
2024-01-12 8:25 ` [edk2-devel] [PATCH v7 25/37] ArmVirtPkg: Move PlatformBootManagerLib to OvmfPkg Chao Li
2024-01-15 8:46 ` Laszlo Ersek
2024-01-16 11:54 ` Chao Li
2024-01-16 14:41 ` Laszlo Ersek
2024-01-18 8:47 ` Chao Li
2024-01-12 8:25 ` [edk2-devel] [PATCH v7 26/37] OvmfPkg/LoongArchVirt: Add stable timer driver Chao Li
2024-01-12 8:25 ` [edk2-devel] [PATCH v7 27/37] OvmfPkg/LoongArchVirt: Add a NULL library named CollectApResouceLibNull Chao Li
2024-01-12 8:25 ` [edk2-devel] [PATCH v7 28/37] OvmfPkg/LoongArchVirt: Add serial port hook library Chao Li
2024-01-12 8:25 ` [edk2-devel] [PATCH v7 29/37] OvmfPkg/LoongArchVirt: Add the early serial port output library Chao Li
2024-01-12 8:26 ` [edk2-devel] [PATCH v7 30/37] OvmfPkg/LoongArchVirt: Add real time clock library Chao Li
2024-01-12 8:26 ` [edk2-devel] [PATCH v7 31/37] OvmfPkg/LoongArchVirt: Add NorFlashQemuLib Chao Li
2024-01-12 8:26 ` [edk2-devel] [PATCH v7 32/37] OvmfPkg/LoongArchVirt: Add FdtQemuFwCfgLib Chao Li
2024-01-12 8:26 ` [edk2-devel] [PATCH v7 33/37] OvmfPkg/LoongArchVirt: Add reset system library Chao Li
2024-01-12 8:26 ` [edk2-devel] [PATCH v7 34/37] OvmfPkg/LoongArchVirt: Support SEC phase Chao Li
2024-01-12 8:26 ` [edk2-devel] [PATCH v7 35/37] OvmfPkg/LoongArchVirt: Support PEI phase Chao Li
2024-01-12 8:26 ` [edk2-devel] [PATCH v7 36/37] OvmfPkg/LoongArchVirt: Add build file Chao Li
2024-01-12 8:26 ` [edk2-devel] [PATCH v7 37/37] OvmfPkg/LoongArchVirt: Add self introduction file Chao Li
2024-01-15 8:33 ` [edk2-devel] [PATCH v7 00/37] Enable LoongArch virtual machine in edk2 Laszlo Ersek
2024-01-16 11:45 ` Chao Li
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=MN6PR11MB824495CC04BEB9496B96E0888C6F2@MN6PR11MB8244.namprd11.prod.outlook.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox