From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by spool.mail.gandi.net (Postfix) with ESMTPS id 416FB7803D0 for ; Wed, 31 Jan 2024 05:29:20 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=oAlmz0kjgBjLIoDF6io2m57cV/47Yy3tTS/EyOZiYuU=; c=relaxed/simple; d=groups.io; h=Message-ID:Date:MIME-Version:User-Agent:Subject:From:To:Cc:Reply-To:References:In-Reply-To:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Type; s=20140610; t=1706678959; v=1; b=Gz7STZtXHnwhZHH+9gq69GcMErMDQ2dcTls/ShDwqeDmopPTL9HmKW+GVmWvXiJ8VM/WRele wjBFPKCATxtXlbOpcz5v+Nw1ZvbWoA2JZEbpFTRIxcAQ+1w25LGVVVv7CIka8CNFidqAMvC6bZQ p+WC85Pn8K8YOpuzjyGGXTZo= X-Received: by 127.0.0.2 with SMTP id fxToYY7687511xJ4zf02sRFv; Tue, 30 Jan 2024 21:29:19 -0800 X-Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web10.8095.1706678957638241103 for ; Tue, 30 Jan 2024 21:29:18 -0800 X-Received: from loongson.cn (unknown [10.40.24.149]) by gateway (Coremail) with SMTP id _____8DxdfGk2rllM8kIAA--.26713S3; Wed, 31 Jan 2024 13:29:08 +0800 (CST) X-Received: from [10.40.24.149] (unknown [10.40.24.149]) by localhost.localdomain (Coremail) with SMTP id AQAAf8AxX8+h2rllapcpAA--.29933S3; Wed, 31 Jan 2024 13:29:05 +0800 (CST) Message-ID: Date: Wed, 31 Jan 2024 13:29:05 +0800 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [edk2-devel] [PATCH v8 12/37] UefiCpuPkg: Add CPU exception library for LoongArch From: "Chao Li" To: devel@edk2.groups.io, Ray Ni , Laszlo Ersek Cc: Eric Dong , Rahul Kumar , Gerd Hoffmann , Baoqi Zhang Reply-To: devel@edk2.groups.io,lichao@loongson.cn References: <20240126062715.3099433-1-lichao@loongson.cn> <17ADD1D7001C37D6.11113@groups.io> <17AF510933F4B8FA.15701@groups.io> In-Reply-To: <17AF510933F4B8FA.15701@groups.io> X-CM-TRANSID: AQAAf8AxX8+h2rllapcpAA--.29933S3 X-CM-SenderInfo: xolfxt3r6o00pqjv00gofq/1tbiAQANCGW4s2EJfwACs- X-Coremail-Antispam: 1Uk129KBj9fXoWDJFy3Ww4rJFyfKFyDAFy7Arc_yoWrZFyDto Z8Aa4rZw4UXw1UAa4DC3ZxG347ZFs7urZ5Xrs0ga10gr1jkw15GayDXw1ftw45XFWrZrZ8 Ga4xX3WkCa93XF1rl-sFpf9Il3svdjkaLaAFLSUrUUUUbb8apTn2vfkv8UJUUUU8wcxFpf 9Il3svdxBIdaVrn8Aqx4xG62kEwI0EY4vaYxAvb48xYxn0WfASr-VFAUDa7-sFnT9fnUUI cSsGvfJTRUUUb3AYFVCjjxCrM7AC8VAFwI0_Jr0_Gr1l1xkIjI8I6I8E6xAIw20EY4v20x vaj40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVWUJVWUCwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV WUJVW8JwA2z4x0Y4vEx4A2jsIE14v26F4j6r4UJwA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_ Gr1j6F4UJwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07AIYIkI8VC2zVCFFI0UMc 02F40En4AKxVAvwIkv4cxYr24lYx0E2Ix0cI8IcVAFwI0_JF0_Jw1lYx0Ex4A2jsIE14v2 6r4j6F4UMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG0xvEwIxGrwCjr7xvwVCIw2I0I7xG6c 02F41lc7CjxVAaw2AFwI0_JF0_Jw1l42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_ Jr0_Gr1lx2IqxVAqx4xG67AKxVWUGVWUWwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1V AY17CE14v26r126r1DMIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Jr0_JF4lIxAI cVC0I7IYx2IY6xkF7I0E14v26r1j6r4UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42 IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26r4j6r4UJbIYCTnIWIev Ja73UjIFyTuYvjxU2mhFDUUUU Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: IOuEqRFMcXm5gDWbM78XsV10x7686176AA= Content-Type: multipart/alternative; boundary="------------LZG4TW9uKD41Nr01bPyau0W6" X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20140610 header.b=Gz7STZtX; dmarc=none; spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce@groups.io --------------LZG4TW9uKD41Nr01bPyau0W6 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable Hi Ray and Laszlo, I would very much like to be merged into stable202302, the soft feature=20 deadline is 2024-02-05, so could you please hlep to review this patch as=20 soon as passable? Please... Thanks, Chao On 2024/1/31 11:31, Chao Li wrote: > > Hi Ray, > > Can you please help to review this patch again? > > On 2024/1/26 14:29, Chao Li wrote: >> Added LoongArch exception handler into CpuExceptionHandlerLib. >> >> Adjust the file order in INF of CpuExceptionHandlerLib with alphabetical >> order. >> >> Adjust files order in CpuExceptionHandlerLib INF in alphabetical order. >> >> BZ:https://bugzilla.tianocore.org/show_bug.cgi?id=3D4584 >> >> Cc: Eric Dong >> Cc: Ray Ni >> Cc: Rahul Kumar >> Cc: Gerd Hoffmann >> Signed-off-by: Chao Li >> Co-authored-by: Baoqi Zhang >> --- >> .../DxeCpuExceptionHandlerLib.inf | 34 +- >> .../LoongArch/DxeExceptionLib.c | 198 ++++++++++ >> .../LoongArch/ExceptionCommon.c | 171 ++++++++ >> .../LoongArch/ExceptionCommon.h | 131 +++++++ >> .../LoongArch64/ArchExceptionHandler.c | 268 +++++++++++++ >> .../LoongArch64/ExceptionHandlerAsm.S | 366 ++++++++++++++++++ >> .../LoongArch/SecPeiExceptionLib.c | 102 +++++ >> .../SecPeiCpuExceptionHandlerLib.inf | 29 +- >> UefiCpuPkg/UefiCpuPkg.dec | 5 + >> 9 files changed, 1283 insertions(+), 21 deletions(-) >> create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch= /DxeExceptionLib.c >> create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch= /ExceptionCommon.c >> create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch= /ExceptionCommon.h >> create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch= /LoongArch64/ArchExceptionHandler.c >> create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch= /LoongArch64/ExceptionHandlerAsm.S >> create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch= /SecPeiExceptionLib.c >> >> diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHa= ndlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHan= dlerLib.inf >> index fdbebadab9..f5bacbe2bc 100644 >> --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLi= b.inf >> +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLi= b.inf >> @@ -18,25 +18,32 @@ >> # >> # The following information is for reference only and not required by = the build tools. >> # >> -# VALID_ARCHITECTURES =3D IA32 X64 >> +# VALID_ARCHITECTURES =3D IA32 X64 LOONGARCH64 >> # >> =20 >> [Sources.Ia32] >> - Ia32/ExceptionHandlerAsm.nasm >> - Ia32/ExceptionTssEntryAsm.nasm >> Ia32/ArchExceptionHandler.c >> Ia32/ArchInterruptDefs.h >> + Ia32/ExceptionHandlerAsm.nasm >> + Ia32/ExceptionTssEntryAsm.nasm >> =20 >> [Sources.X64] >> - X64/ExceptionHandlerAsm.nasm >> X64/ArchExceptionHandler.c >> X64/ArchInterruptDefs.h >> + X64/ExceptionHandlerAsm.nasm >> =20 >> -[Sources.common] >> +[Sources.Ia32, Sources.X64] >> CpuExceptionCommon.h >> CpuExceptionCommon.c >> - PeiDxeSmmCpuException.c >> DxeException.c >> + PeiDxeSmmCpuException.c >> + >> +[Sources.LoongArch64] >> + LoongArch/DxeExceptionLib.c >> + LoongArch/ExceptionCommon.h >> + LoongArch/ExceptionCommon.c >> + LoongArch/LoongArch64/ArchExceptionHandler.c >> + LoongArch/LoongArch64/ExceptionHandlerAsm.S | GCC >> =20 >> [Pcd] >> gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard >> @@ -51,16 +58,19 @@ >> MdeModulePkg/MdeModulePkg.dec >> UefiCpuPkg/UefiCpuPkg.dec >> =20 >> -[LibraryClasses] >> +[LibraryClasses.common] >> BaseLib >> - SerialPortLib >> + CpuLib >> + DebugLib >> + MemoryAllocationLib >> + PeCoffGetEntryPointLib >> PrintLib >> + SerialPortLib >> SynchronizationLib >> - LocalApicLib >> - PeCoffGetEntryPointLib >> - MemoryAllocationLib >> - DebugLib >> + >> +[LibraryClasses.Ia32, LibraryClasses.X64] >> CcExitLib >> + LocalApicLib >> =20 >> [BuildOptions] >> XCODE:*_*_X64_NASM_FLAGS =3D -D NO_ABSOLUTE_RELOCS_IN_TEXT >> diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/DxeExce= ptionLib.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/DxeExcepti= onLib.c >> new file mode 100644 >> index 0000000000..2c5d202b33 >> --- /dev/null >> +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/DxeExceptionLi= b.c >> @@ -0,0 +1,198 @@ >> +/** @file DxeExceptionLib.c >> + >> + LoongArch exception library implemenation for DXE modules. >> + >> + Copyright (c) 2024, Loongson Technology Corporation Limited. All righ= ts reserved.
>> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include "ExceptionCommon.h" >> + >> +EFI_EXCEPTION_CALLBACK ExternalInterruptHandler[MAX_LOONGARCH_INTERRUP= T + 1] =3D { 0 }; >> +EFI_EXCEPTION_CALLBACK ExceptionHandler[MAX_LOONGARCH_EXCEPTION + 1] = =3D { 0 }; >> + >> +/** >> + Registers a function to be called from the processor interrupt or exc= eption handler. >> + >> + This function registers and enables the handler specified by Interrup= tHandler for a processor >> + interrupt or exception type specified by InterruptType. If InterruptH= andler is NULL, then the >> + handler for the processor interrupt or exception type specified by In= terruptType is uninstalled. >> + The installed handler is called once for each processor interrupt or = exception. >> + >> + @param InterruptType A pointer to the processor's current interru= pt state. Set to TRUE if interrupts >> + are enabled and FALSE if interrupts are disa= bled. >> + @param InterruptHandler A pointer to a function of type EFI_CPU_INTE= RRUPT_HANDLER that is called >> + when a processor interrupt occurs. If this p= arameter 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 han= dler 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 InterruptTyp= e is not supported. >> + >> +**/ >> +EFI_STATUS >> +RegisterCpuInterruptHandler ( >> + IN EFI_EXCEPTION_TYPE InterruptType, >> + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler >> + ) >> +{ >> + EFI_EXCEPTION_TYPE ExceptionType; >> + >> + ExceptionType =3D InterruptType & CSR_ESTAT_EXC; >> + >> + if (ExceptionType !=3D 0) { >> + // >> + // Exception >> + // >> + if (ExceptionType > EXCEPT_LOONGARCH_FPE) { >> + return EFI_UNSUPPORTED; >> + } >> + >> + ExceptionType >>=3D CSR_ESTAT_EXC_SHIFT; >> + >> + if ((InterruptHandler =3D=3D NULL) && (ExceptionHandler[InterruptTy= pe] =3D=3D NULL)) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + if ((InterruptHandler !=3D NULL) && (ExceptionHandler[ExceptionType= ] !=3D NULL)) { >> + return EFI_ALREADY_STARTED; >> + } >> + >> + ExceptionHandler[ExceptionType] =3D InterruptHandler; >> + } else { >> + // >> + // Interrupt >> + // >> + if (InterruptType > MAX_LOONGARCH_INTERRUPT) { >> + return EFI_UNSUPPORTED; >> + } >> + >> + if ((InterruptHandler =3D=3D NULL) && (ExternalInterruptHandler[Int= erruptType] =3D=3D NULL)) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + if ((InterruptHandler !=3D NULL) && (ExternalInterruptHandler[Inter= ruptType] !=3D NULL)) { >> + return EFI_ALREADY_STARTED; >> + } >> + >> + ExternalInterruptHandler[InterruptType] =3D 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 =3D=3D EXCEPT_LOONGARCH_INT) { >> + // >> + // Interrupt >> + // >> + InterruptType =3D GetInterruptType (SystemContext); >> + if (InterruptType =3D=3D 0xFF) { >> + ExceptionType =3D InterruptType; >> + } else { >> + if ((ExternalInterruptHandler !=3D NULL) && (ExternalInterruptHan= dler[InterruptType] !=3D NULL)) { >> + ExternalInterruptHandler[InterruptType](InterruptType, SystemCo= ntext); >> + return; >> + } >> + } >> + } else if (ExceptionType =3D=3D EXCEPT_LOONGARCH_FPD) { >> + EnableFloatingPointUnits (); >> + InitializeFloatingPointUnits (); >> + return; >> + } else { >> + // >> + // Exception >> + // >> + ExceptionType >>=3D CSR_ESTAT_EXC_SHIFT; >> + if ((ExceptionHandler !=3D NULL) && (ExceptionHandler[ExceptionType= ] !=3D NULL)) { >> + ExceptionHandler[ExceptionType](ExceptionType, SystemContext); >> + return; >> + } >> + } >> + >> + // >> + // Only the TLB refill exception use the same entry point as normal e= xceptions. >> + // >> + if (CsrRead (LOONGARCH_CSR_TLBRERA) & 0x1) { >> + ExceptionType =3D mExceptionKnownNameNum - 1; // Use only to dump t= he exception context. >> + } >> + >> + DefaultExceptionHandler (ExceptionType, SystemContext); >> +} >> + >> +/** >> + Initializes all CPU exceptions entries and provides the default excep= tion handlers. >> + >> + Caller should try to get an array of interrupt and/or exception vecto= rs 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 success= fully 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 excep= tion stack. >> + @param[in, out] BufferSize On input, it indicates the byte size o= f Buffer. >> + If the size is not enough, the return = status will >> + be EFI_BUFFER_TOO_SMALL, and output Bu= fferSize >> + 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/CpuExceptionHandlerLib/LoongArch/Excepti= onCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/ExceptionC= ommon.c >> new file mode 100644 >> index 0000000000..801c8393e8 >> --- /dev/null >> +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/ExceptionCommo= n.c >> @@ -0,0 +1,171 @@ >> +/** @file DxeExceptionLib.c >> + >> + CPU Exception Handler Library common functions. >> + >> + Copyright (c) 2024, Loongson Technology Corporation Limited. All righ= ts reserved.
>> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include "ExceptionCommon.h" >> + >> +CONST CHAR8 mExceptionReservedStr[] =3D "Reserved"; >> +CONST CHAR8 *mExceptionNameStr[] =3D { >> + "#INT - Interrupt(CSR.ECFG.VS=3D0)", >> + "#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 disa= ble exception", >> + "#ASXD - 256-bit vector (Advanced SIMD instructions) expansion instru= ction disable exception", >> + "#FPE - Floating-Point error exception", >> + "#WPE - WatchPoint Exception for Fetch watchpoint or Memory load/stor= e 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 e= xception is not instructed in ECODE, so the TLB refill exception must be th= e last one! >> +}; >> + >> +INTN mExceptionKnownNameNum =3D (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 accesse= d >> + 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 ent= ry point. >> + >> + @param CurrentEra Current instruction pointer. >> + >> +**/ >> +VOID >> +DumpModuleImageInfo ( >> + IN UINTN CurrentEra >> + ) >> +{ >> + EFI_STATUS Status; >> + UINTN Pe32Data; >> + VOID *PdbPointer; >> + VOID *EntryPoint; >> + >> + Pe32Data =3D PeCoffSearchImageBase (CurrentEra); >> + if (Pe32Data =3D=3D 0) { >> + InternalPrintMessage ("!!!! Can't find image information. !!!!\n"); >> + } else { >> + // >> + // Find Image Base entry point >> + // >> + Status =3D PeCoffLoaderGetEntryPoint ((VOID *)Pe32Data, &EntryPoint= ); >> + if (EFI_ERROR (Status)) { >> + EntryPoint =3D NULL; >> + } >> + >> + InternalPrintMessage ("!!!! Find image based on IP(0x%x) ", Current= Era); >> + PdbPointer =3D PeCoffLoaderGetPdbPointer ((VOID *)Pe32Data); >> + if (PdbPointer !=3D NULL) { >> + InternalPrintMessage ("%a", PdbPointer); >> + } else { >> + InternalPrintMessage ("(No PDB) "); >> + } >> + >> + InternalPrintMessage ( >> + " (ImageBase=3D%016lp, EntryPoint=3D%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/CpuExceptionHandlerLib/LoongArch/Excepti= onCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/ExceptionC= ommon.h >> new file mode 100644 >> index 0000000000..e326b73e3f >> --- /dev/null >> +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/ExceptionCommo= n.h >> @@ -0,0 +1,131 @@ >> +/** @file DxeExceptionLib.h >> + >> + Common header file for CPU Exception Handler Library. >> + >> + Copyright (c) 2024, Loongson Technology Corporation Limited. All righ= ts reserved.
>> + >> + 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 acc= essed >> + 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 ent= ry 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 inte= rrupt 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/CpuExceptionHandlerLib/LoongArch/LoongAr= ch64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Loo= ngArch/LoongArch64/ArchExceptionHandler.c >> new file mode 100644 >> index 0000000000..c0219deba5 >> --- /dev/null >> +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/LoongArch64/Ar= chExceptionHandler.c >> @@ -0,0 +1,268 @@ >> +/** @file ArchExceptionHandler.c >> + >> + LoongArch64 CPU Exception Handler. >> + >> + Copyright (c) 2024, Loongson Technology Corporation Limited. All righ= ts reserved.
>> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include >> +#include >> +#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 =3D (SystemContext.SystemContextLoongArch64->ESTAT & CS= R_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 =3D 0; InterruptType <=3D EXCEPT_LOONGARCH_INT_IPI= ; InterruptType++) { >> + if (SystemContext.SystemContextLoongArch64->ESTAT & (1 << Interrupt= Type)) { >> + // >> + // 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 =3D=3D (mExceptionKnownNameNum - 1)) { >> + InternalPrintMessage ("TLB refill ERA 0x%llx\n", (CsrRead (LOONGAR= CH_CSR_TLBRERA) & (~0x3ULL))); >> + InternalPrintMessage ("TLB refill BADV 0x%llx\n", CsrRead (LOONGAR= CH_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%016= lx\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%016= lx\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 =3D=3D (mExceptionKnownNameNum - 1)) { >> + // >> + // Dump TLB refill image info >> + // >> + DumpModuleImageInfo ((CsrRead (LOONGARCH_CSR_TLBRERA) & (~0x3ULL)))= ; >> + } else { >> + DumpModuleImageInfo (SystemContext.SystemContextLoongArch64->ERA); >> + } >> +} >> + >> +/** >> + IPI Interrupt Handler. >> + >> + @param InterruptType The type of interrupt that occurred >> + @param SystemContext A pointer to the system context when the inte= rrupt 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 =3D IoCsrRead64 (LOONGARCH_IOCSR_MBUF0); >> + Parameter =3D 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 cal= led the IPI to wake >> + // up the current core and let it use the resume vector stored in mai= lbox 0. >> + // >> + // If both the resume vector and parameter are non-NULL, it means tha= t the IPI was >> + // called in the BIOS. >> + // >> + // The situation where the resume vector is non-NULL and the paramete= r is NULL has been >> + // processed after the exception entry is pushed onto the stack. >> + // >> + if ((ResumeVector !=3D 0) && (Parameter !=3D 0)) { >> + SystemContext.SystemContextLoongArch64->ERA =3D ResumeVector; >> + // >> + // Set $a0 as APIC ID and $a1 as parameter value. >> + // >> + SystemContext.SystemContextLoongArch64->R4 =3D CsrRead (LOONGARCH_C= SR_CPUNUM); >> + SystemContext.SystemContextLoongArch64->R5 =3D Parameter; >> + } >> + >> + MemoryFence (); >> +} >> diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/LoongAr= ch64/ExceptionHandlerAsm.S b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Loon= gArch/LoongArch64/ExceptionHandlerAsm.S >> new file mode 100644 >> index 0000000000..7c692e01c1 >> --- /dev/null >> +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/LoongArch64/Ex= ceptionHandlerAsm.S >> @@ -0,0 +1,366 @@ >> +#----------------------------------------------------------------------= -------- >> +# >> +# LoongArch64 ASM exception handler >> +# >> +# Copyright (c) 2024, Loongson Technology Corporation Limited. All righ= ts reserved.
>> +# >> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> +# >> +#----------------------------------------------------------------------= -------- >> + >> +#include >> +#include >> +#include >> + >> +#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 s= ize >> +#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 st= ored 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 po= inter befor pop the FP registers. >> + >> + beqz $t1, PopGP // If the FPE not set, only p= op 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 excepti= on 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_R= EG_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: >> + // >> + // Process IPI only when mailbox3 is NULL and mailbox0 is no-NULL. >> + // >> + li.d $t0, LOONGARCH_IOCSR_MBUF0 >> + iocsrrd.d $a0, $t0 >> + beqz $a0, EntryConmmonHanlder >> + >> + li.d $t0, LOONGARCH_IOCSR_MBUF3 >> + iocsrrd.d $t1, $t0 >> + bnez $t1, EntryConmmonHanlder >> + >> + csrrd $t0, LOONGARCH_CSR_ESTAT >> + srli.d $t0, $t0, 12 >> + andi $t0, $t0, 0x1 >> + beqz $t0, EntryConmmonHanlder >> + >> + // >> + // Clean up current processor mailbox 0 and mailbox 3. >> + // >> + li.d $t0, LOONGARCH_IOCSR_MBUF0 >> + iocsrwr.d $zero, $t0 >> + li.d $t0, LOONGARCH_IOCSR_MBUF3 >> + iocsrwr.d $zero, $t0 >> + >> + // >> + // Clear IPI interrupt. >> + // >> + li.d $t0, LOONGARCH_IOCSR_IPI_STATUS >> + iocsrrd.w $t1, $t0 >> + li.d $t0, LOONGARCH_IOCSR_IPI_CLEAR >> + iocsrwr.w $t1, $t0 >> + >> + // >> + // Only kernel stage BSP calls IPI without parameters. Clean up the P= IE and make sure >> + // global interrupts are turned off for the current processor when ju= mping to the kernel. >> + // >> + csrwr $a0, LOONGARCH_CSR_ERA // Update ERA >> + li.w $t0, BIT2 // IE >> + csrxchg $zero, $t0, LOONGARCH_CSR_PRMD // Clean PIE >> + >> + // >> + // Return this exception and jump to kernel using ERA. >> + // >> + ertn >> + >> +EntryConmmonHanlder: >> + 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/CpuExceptionHandlerLib/LoongArch/SecPeiE= xceptionLib.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/SecPeiE= xceptionLib.c >> new file mode 100644 >> index 0000000000..7588d2050b >> --- /dev/null >> +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/SecPeiExceptio= nLib.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 righ= ts reserved.
>> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include "ExceptionCommon.h" >> + >> +/** >> + Registers a function to be called from the processor interrupt or exc= eption handler. >> + >> + Always return EFI_UNSUPPORTED in the SEC exception initialization mod= ule. >> + >> + @param InterruptType A pointer to the processor's current interru= pt state. Set to TRUE if interrupts >> + are enabled and FALSE if interrupts are disa= bled. >> + @param InterruptHandler A pointer to a function of type EFI_CPU_INTE= RRUPT_HANDLER that is called >> + when a processor interrupt occurs. If this p= arameter 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 =3D=3D EXCEPT_LOONGARCH_INT) { >> + // >> + // Interrupt >> + // >> + InterruptType =3D GetInterruptType (SystemContext); >> + if (InterruptType =3D=3D 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 =3D InterruptType; >> + } >> + } else { >> + // >> + // Exception >> + // >> + ExceptionType >>=3D CSR_ESTAT_EXC_SHIFT; >> + } >> + >> + DefaultExceptionHandler (ExceptionType, SystemContext); >> +} >> + >> +/** >> + Initializes all CPU exceptions entries and provides the default excep= tion 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 successfull= y initialized >> + with default exception handlers. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +InitializeCpuExceptionHandlers ( >> + IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL >> + ) >> +{ >> + return EFI_SUCCESS; >> +} >> diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptio= nHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExcept= ionHandlerLib.inf >> index e7b1144f69..6bb194ea77 100644 >> --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandle= rLib.inf >> +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandle= rLib.inf >> @@ -2,6 +2,7 @@ >> # CPU Exception Handler library instance for SEC/PEI modules. >> # >> # Copyright (c) 2012 - 2022, Intel Corporation. All rights reserved.<= BR> >> +# Copyright (c) 2024, Loongson Technology Corporation Limited. All rig= hts reserved.
>> # SPDX-License-Identifier: BSD-2-Clause-Patent >> # >> ## >> @@ -18,37 +19,47 @@ >> # >> # The following information is for reference only and not required by = the build tools. >> # >> -# VALID_ARCHITECTURES =3D IA32 X64 >> +# VALID_ARCHITECTURES =3D IA32 X64 LOONGARCH64 >> # >> =20 >> [Sources.Ia32] >> - Ia32/ExceptionHandlerAsm.nasm >> - Ia32/ExceptionTssEntryAsm.nasm >> Ia32/ArchExceptionHandler.c >> Ia32/ArchInterruptDefs.h >> + Ia32/ExceptionHandlerAsm.nasm >> + Ia32/ExceptionTssEntryAsm.nasm >> =20 >> [Sources.X64] >> - X64/SecPeiExceptionHandlerAsm.nasm >> X64/ArchExceptionHandler.c >> X64/ArchInterruptDefs.h >> + X64/SecPeiExceptionHandlerAsm.nasm >> =20 >> -[Sources.common] >> +[Sources.Ia32, Sources.X64] >> CpuExceptionCommon.h >> CpuExceptionCommon.c >> SecPeiCpuException.c >> =20 >> +[Sources.LoongArch64] >> + LoongArch/ExceptionCommon.h >> + LoongArch/ExceptionCommon.c >> + LoongArch/SecPeiExceptionLib.c >> + LoongArch/LoongArch64/ArchExceptionHandler.c >> + LoongArch/LoongArch64/ExceptionHandlerAsm.S | GCC >> + >> [Packages] >> MdePkg/MdePkg.dec >> MdeModulePkg/MdeModulePkg.dec >> UefiCpuPkg/UefiCpuPkg.dec >> =20 >> -[LibraryClasses] >> +[LibraryClasses.common] >> BaseLib >> - SerialPortLib >> - PrintLib >> - LocalApicLib >> + CpuLib >> PeCoffGetEntryPointLib >> + PrintLib >> + SerialPortLib >> + >> +[LibraryClasses.Ia32, LibraryClasses.X64] >> CcExitLib >> + LocalApicLib >> =20 >> [Pcd] >> gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard >> diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec >> index 571b59b36f..f5febe46ba 100644 >> --- a/UefiCpuPkg/UefiCpuPkg.dec >> +++ b/UefiCpuPkg/UefiCpuPkg.dec >> @@ -3,6 +3,7 @@ >> # >> # Copyright (c) 2007 - 2023, Intel Corporation. All rights reserved. >> # Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.=
>> +# Copyright (c) 2024, Loongson Technology Corporation Limited. All righ= ts reserved.
>> # >> # SPDX-License-Identifier: BSD-2-Clause-Patent >> # >> @@ -385,6 +386,10 @@ >> # @Prompt Enable performance collecting when processor trace is enab= led. >> gUefiCpuPkgTokenSpaceGuid.PcdCpuProcTracePerformanceCollecting|FALSE= |BOOLEAN|0x60000020 >> =20 >> + ## This PCD Contains the pointer to a CPU exception vector base addre= ss. >> + # @Prompt The pointer to a CPU exception vector base address. >> + gUefiCpuPkgTokenSpaceGuid.PcdCpuExceptionVectorBaseAddress|0x0|UINT64= |0x60000022 >> + >> [PcdsFixedAtBuild.X64, PcdsPatchableInModule.X64, PcdsDynamic.X64, Pcd= sDynamicEx.X64] >> ## Indicate access to non-SMRAM memory is restricted to reserved, ru= ntime and ACPI NVS type after SmmReadyToLock. >> # MMIO access is always allowed regardless of the value of this PCD= . >=20 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114859): https://edk2.groups.io/g/devel/message/114859 Mute This Topic: https://groups.io/mt/104070164/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- --------------LZG4TW9uKD41Nr01bPyau0W6 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable

Hi Ray and Laszlo,

I would very much like to be merged into stable202302, the soft feature deadline is 2024-02-05, so could you please hlep to review this patch as soon as passable? Please...


=
Thanks,
Chao
On 2024/1/31 11:31, Chao Li wrote:

Hi Ray,

Can you please help to review this patch again?

On 2024/1/26 14:29, Chao Li wrote:
Added LoongArch exception ha=
ndler into CpuExceptionHandlerLib.

Adjust the file order in INF of CpuExceptionHandlerLib with alphabetical
order.

Adjust files order in CpuExceptionHandlerLib INF in alphabetical order.

BZ: https://bugzilla.tianocore.org/show_bug.cg=
i?id=3D4584

Cc: Eric Dong <er=
ic.dong@intel.com>
Cc: Ray Ni <ray.n=
i@intel.com>
Cc: Rahul Kumar <=
;rahul1.kumar@intel.com>
Cc: Gerd Hoffmann <krax=
el@redhat.com>
Signed-off-by: Chao Li <lic=
hao@loongson.cn>
Co-authored-by: Baoqi Zhang <=
;zhangbaoqi@loongson.cn>
---
 .../DxeCpuExceptionHandlerLib.inf             |  34 +-
 .../LoongArch/DxeExceptionLib.c               | 198 ++++++++++
 .../LoongArch/ExceptionCommon.c               | 171 ++++++++
 .../LoongArch/ExceptionCommon.h               | 131 +++++++
 .../LoongArch64/ArchExceptionHandler.c        | 268 +++++++++++++
 .../LoongArch64/ExceptionHandlerAsm.S         | 366 ++++++++++++++++++
 .../LoongArch/SecPeiExceptionLib.c            | 102 +++++
 .../SecPeiCpuExceptionHandlerLib.inf          |  29 +-
 UefiCpuPkg/UefiCpuPkg.dec                     |   5 +
 9 files changed, 1283 insertions(+), 21 deletions(-)
 create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/Dxe=
ExceptionLib.c
 create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/Exc=
eptionCommon.c
 create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/Exc=
eptionCommon.h
 create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/Loo=
ngArch64/ArchExceptionHandler.c
 create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/Loo=
ngArch64/ExceptionHandlerAsm.S
 create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/Sec=
PeiExceptionLib.c

diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandl=
erLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandle=
rLib.inf
index fdbebadab9..f5bacbe2bc 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.i=
nf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.i=
nf
@@ -18,25 +18,32 @@
 #
 # The following information is for reference only and not required by the =
build tools.
 #
-#  VALID_ARCHITECTURES           =3D IA32 X64
+#  VALID_ARCHITECTURES           =3D IA32 X64 LOONGARCH64
 #
=20
 [Sources.Ia32]
-  Ia32/ExceptionHandlerAsm.nasm
-  Ia32/ExceptionTssEntryAsm.nasm
   Ia32/ArchExceptionHandler.c
   Ia32/ArchInterruptDefs.h
+  Ia32/ExceptionHandlerAsm.nasm
+  Ia32/ExceptionTssEntryAsm.nasm
=20
 [Sources.X64]
-  X64/ExceptionHandlerAsm.nasm
   X64/ArchExceptionHandler.c
   X64/ArchInterruptDefs.h
+  X64/ExceptionHandlerAsm.nasm
=20
-[Sources.common]
+[Sources.Ia32, Sources.X64]
   CpuExceptionCommon.h
   CpuExceptionCommon.c
-  PeiDxeSmmCpuException.c
   DxeException.c
+  PeiDxeSmmCpuException.c
+
+[Sources.LoongArch64]
+  LoongArch/DxeExceptionLib.c
+  LoongArch/ExceptionCommon.h
+  LoongArch/ExceptionCommon.c
+  LoongArch/LoongArch64/ArchExceptionHandler.c
+  LoongArch/LoongArch64/ExceptionHandlerAsm.S | GCC
=20
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard
@@ -51,16 +58,19 @@
   MdeModulePkg/MdeModulePkg.dec
   UefiCpuPkg/UefiCpuPkg.dec
=20
-[LibraryClasses]
+[LibraryClasses.common]
   BaseLib
-  SerialPortLib
+  CpuLib
+  DebugLib
+  MemoryAllocationLib
+  PeCoffGetEntryPointLib
   PrintLib
+  SerialPortLib
   SynchronizationLib
-  LocalApicLib
-  PeCoffGetEntryPointLib
-  MemoryAllocationLib
-  DebugLib
+
+[LibraryClasses.Ia32, LibraryClasses.X64]
   CcExitLib
+  LocalApicLib
=20
 [BuildOptions]
   XCODE:*_*_X64_NASM_FLAGS =3D -D NO_ABSOLUTE_RELOCS_IN_TEXT
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/DxeExcepti=
onLib.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/DxeExceptionL=
ib.c
new file mode 100644
index 0000000000..2c5d202b33
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/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] =3D { 0 };
+EFI_EXCEPTION_CALLBACK  ExceptionHandler[MAX_LOONGARCH_EXCEPTION + 1]     =
    =3D { 0 };
+
+/**
+  Registers a function to be called from the processor interrupt or except=
ion handler.
+
+  This function registers and enables the handler specified by InterruptHa=
ndler for a processor
+  interrupt or exception type specified by InterruptType. If InterruptHand=
ler is NULL, then the
+  handler for the processor interrupt or exception type specified by Inter=
ruptType is uninstalled.
+  The installed handler is called once for each processor interrupt or exc=
eption.
+
+  @param  InterruptType    A pointer to the processor's current interrupt =
state. Set to TRUE if interrupts
+                           are enabled and FALSE if interrupts are disable=
d.
+  @param  InterruptHandler A pointer to a function of type EFI_CPU_INTERRU=
PT_HANDLER that is called
+                           when a processor interrupt occurs. If this para=
meter is NULL, then the handler
+                           will be uninstalled.
+
+  @retval EFI_SUCCESS           The handler for the processor interrupt wa=
s successfully installed or uninstalled.
+  @retval EFI_ALREADY_STARTED   InterruptHandler is not NULL, and a handle=
r for InterruptType was
+                                previously installed.
+  @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler fo=
r InterruptType was not
+                                previously installed.
+  @retval EFI_UNSUPPORTED       The interrupt specified by InterruptType i=
s not supported.
+
+**/
+EFI_STATUS
+RegisterCpuInterruptHandler (
+  IN EFI_EXCEPTION_TYPE         InterruptType,
+  IN EFI_CPU_INTERRUPT_HANDLER  InterruptHandler
+  )
+{
+  EFI_EXCEPTION_TYPE  ExceptionType;
+
+  ExceptionType =3D InterruptType & CSR_ESTAT_EXC;
+
+  if (ExceptionType !=3D 0) {
+    //
+    // Exception
+    //
+    if (ExceptionType > EXCEPT_LOONGARCH_FPE) {
+      return EFI_UNSUPPORTED;
+    }
+
+    ExceptionType >>=3D CSR_ESTAT_EXC_SHIFT;
+
+    if ((InterruptHandler =3D=3D NULL) && (ExceptionHandler[Interr=
uptType] =3D=3D NULL)) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if ((InterruptHandler !=3D NULL) && (ExceptionHandler[Exceptio=
nType] !=3D NULL)) {
+      return EFI_ALREADY_STARTED;
+    }
+
+    ExceptionHandler[ExceptionType] =3D InterruptHandler;
+  } else {
+    //
+    // Interrupt
+    //
+    if (InterruptType > MAX_LOONGARCH_INTERRUPT) {
+      return EFI_UNSUPPORTED;
+    }
+
+    if ((InterruptHandler =3D=3D NULL) && (ExternalInterruptHandle=
r[InterruptType] =3D=3D NULL)) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if ((InterruptHandler !=3D NULL) && (ExternalInterruptHandler[=
InterruptType] !=3D NULL)) {
+      return EFI_ALREADY_STARTED;
+    }
+
+    ExternalInterruptHandler[InterruptType] =3D 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 =3D=3D EXCEPT_LOONGARCH_INT) {
+    //
+    // Interrupt
+    //
+    InterruptType =3D GetInterruptType (SystemContext);
+    if (InterruptType =3D=3D 0xFF) {
+      ExceptionType =3D InterruptType;
+    } else {
+      if ((ExternalInterruptHandler !=3D NULL) && (ExternalInterru=
ptHandler[InterruptType] !=3D NULL)) {
+        ExternalInterruptHandler[InterruptType](InterruptType, SystemConte=
xt);
+        return;
+      }
+    }
+  } else if (ExceptionType =3D=3D EXCEPT_LOONGARCH_FPD) {
+    EnableFloatingPointUnits ();
+    InitializeFloatingPointUnits ();
+    return;
+  } else {
+    //
+    // Exception
+    //
+    ExceptionType >>=3D CSR_ESTAT_EXC_SHIFT;
+    if ((ExceptionHandler !=3D NULL) && (ExceptionHandler[Exceptio=
nType] !=3D NULL)) {
+      ExceptionHandler[ExceptionType](ExceptionType, SystemContext);
+      return;
+    }
+  }
+
+  //
+  // Only the TLB refill exception use the same entry point as normal exce=
ptions.
+  //
+  if (CsrRead (LOONGARCH_CSR_TLBRERA) & 0x1) {
+    ExceptionType =3D mExceptionKnownNameNum - 1; // Use only to dump the =
exception context.
+  }
+
+  DefaultExceptionHandler (ExceptionType, SystemContext);
+}
+
+/**
+  Initializes all CPU exceptions entries and provides the default exceptio=
n 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 Vec=
torInfo 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 successful=
ly 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 exceptio=
n stack.
+  @param[in, out]  BufferSize    On input, it indicates the byte size of B=
uffer.
+                                 If the size is not enough, the return sta=
tus will
+                                 be EFI_BUFFER_TOO_SMALL, and output Buffe=
rSize
+                                 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/CpuExceptionHandlerLib/LoongArch/ExceptionC=
ommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/ExceptionComm=
on.c
new file mode 100644
index 0000000000..801c8393e8
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/ExceptionCommon.c
@@ -0,0 +1,171 @@
+/** @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[] =3D "Reserved";
+CONST CHAR8  *mExceptionNameStr[]    =3D {
+  "#INT - Interrupt(CSR.ECFG.VS=3D0)",
+  "#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 instructi=
on disable exception",
+  "#FPE - Floating-Point error exception",
+  "#WPE - WatchPoint Exception for Fetch watchpoint or Memory load/store w=
atchpoint",
+  "#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 exce=
ption is not instructed in ECODE, so the TLB refill exception must be the l=
ast one!
+};
+
+INTN  mExceptionKnownNameNum =3D (sizeof (mExceptionNameStr) / sizeof (CHA=
R8 *));
+
+/**
+  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 =3D PeCoffSearchImageBase (CurrentEra);
+  if (Pe32Data =3D=3D 0) {
+    InternalPrintMessage ("!!!! Can't find image information. !!!!\n");
+  } else {
+    //
+    // Find Image Base entry point
+    //
+    Status =3D PeCoffLoaderGetEntryPoint ((VOID *)Pe32Data, &EntryPoin=
t);
+    if (EFI_ERROR (Status)) {
+      EntryPoint =3D NULL;
+    }
+
+    InternalPrintMessage ("!!!! Find image based on IP(0x%x) ", CurrentEra=
);
+    PdbPointer =3D PeCoffLoaderGetPdbPointer ((VOID *)Pe32Data);
+    if (PdbPointer !=3D NULL) {
+      InternalPrintMessage ("%a", PdbPointer);
+    } else {
+      InternalPrintMessage ("(No PDB) ");
+    }
+
+    InternalPrintMessage (
+      " (ImageBase=3D%016lp, EntryPoint=3D%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/CpuExceptionHandlerLib/LoongArch/ExceptionC=
ommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/ExceptionComm=
on.h
new file mode 100644
index 0000000000..e326b73e3f
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/ExceptionCommon.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 access=
ed
+                      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 interru=
pt 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/CpuExceptionHandlerLib/LoongArch/LoongArch6=
4/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongA=
rch/LoongArch64/ArchExceptionHandler.c
new file mode 100644
index 0000000000..c0219deba5
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/LoongArch64/ArchE=
xceptionHandler.c
@@ -0,0 +1,268 @@
+/** @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 =3D (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 =3D 0; InterruptType <=3D 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 =3D=3D (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 =3D=3D (mExceptionKnownNameNum - 1)) {
+    //
+    // Dump TLB refill image info
+    //
+    DumpModuleImageInfo ((CsrRead (LOONGARCH_CSR_TLBRERA) & (~0x3ULL))=
);
+  } else {
+    DumpModuleImageInfo (SystemContext.SystemContextLoongArch64->ERA);
+  }
+}
+
+/**
+  IPI Interrupt Handler.
+
+  @param InterruptType    The type of interrupt that occurred
+  @param SystemContext    A pointer to the system context when the interru=
pt 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_IP=
I_STATUS));
+
+  //
+  // Get the resume vector and parameter if populated.
+  //
+  ResumeVector =3D IoCsrRead64 (LOONGARCH_IOCSR_MBUF0);
+  Parameter    =3D 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 mailbo=
x 0.
+  //
+  // If both the resume vector and parameter are non-NULL, it means that t=
he IPI was
+  // called in the BIOS.
+  //
+  // The situation where the resume vector is non-NULL and the parameter i=
s NULL has been
+  // processed after the exception entry is pushed onto the stack.
+  //
+  if ((ResumeVector !=3D 0) && (Parameter !=3D 0)) {
+    SystemContext.SystemContextLoongArch64->ERA =3D ResumeVector;
+    //
+    // Set $a0 as APIC ID and $a1 as parameter value.
+    //
+    SystemContext.SystemContextLoongArch64->R4 =3D CsrRead (LOONGARCH_C=
SR_CPUNUM);
+    SystemContext.SystemContextLoongArch64->R5 =3D Parameter;
+  }
+
+  MemoryFence ();
+}
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/LoongArch6=
4/ExceptionHandlerAsm.S b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongAr=
ch/LoongArch64/ExceptionHandlerAsm.S
new file mode 100644
index 0000000000..7c692e01c1
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/LoongArch64/Excep=
tionHandlerAsm.S
@@ -0,0 +1,366 @@
+#-------------------------------------------------------------------------=
-----
+#
+# 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 siz=
e
+#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, an=
yway disable interrupts here.
+  // It will be turned on when the instruction 'ertn' is executed.
+  //
+  bl      DisableInterrupts
+
+  bl      GetExceptionType        // Get current exception type, and store=
d in register a0
+
+  // Check whether the FPE is changed during interrupt handler, if ture re=
store 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 point=
er 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:
+  //
+  // Process IPI only when mailbox3 is NULL and mailbox0 is no-NULL.
+  //
+  li.d      $t0, LOONGARCH_IOCSR_MBUF0
+  iocsrrd.d $a0, $t0
+  beqz      $a0, EntryConmmonHanlder
+
+  li.d      $t0, LOONGARCH_IOCSR_MBUF3
+  iocsrrd.d $t1, $t0
+  bnez      $t1, EntryConmmonHanlder
+
+  csrrd     $t0, LOONGARCH_CSR_ESTAT
+  srli.d    $t0, $t0, 12
+  andi      $t0, $t0, 0x1
+  beqz      $t0, EntryConmmonHanlder
+
+  //
+  // Clean up current processor mailbox 0 and mailbox 3.
+  //
+  li.d      $t0, LOONGARCH_IOCSR_MBUF0
+  iocsrwr.d $zero, $t0
+  li.d      $t0, LOONGARCH_IOCSR_MBUF3
+  iocsrwr.d $zero, $t0
+
+  //
+  // Clear IPI interrupt.
+  //
+  li.d      $t0, LOONGARCH_IOCSR_IPI_STATUS
+  iocsrrd.w $t1, $t0
+  li.d      $t0, LOONGARCH_IOCSR_IPI_CLEAR
+  iocsrwr.w $t1, $t0
+
+  //
+  // 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 jumpi=
ng to the kernel.
+  //
+  csrwr     $a0, LOONGARCH_CSR_ERA         // Update ERA
+  li.w      $t0, BIT2                      // IE
+  csrxchg   $zero, $t0, LOONGARCH_CSR_PRMD // Clean PIE
+
+  //
+  // Return this exception and jump to kernel using ERA.
+  //
+  ertn
+
+EntryConmmonHanlder:
+  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/CpuExceptionHandlerLib/LoongArch/SecPeiExce=
ptionLib.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/SecPeiExce=
ptionLib.c
new file mode 100644
index 0000000000..7588d2050b
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/LoongArch/SecPeiExceptionLi=
b.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 except=
ion 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 disable=
d.
+  @param  InterruptHandler A pointer to a function of type EFI_CPU_INTERRU=
PT_HANDLER that is called
+                           when a processor interrupt occurs. If this para=
meter 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 =3D=3D EXCEPT_LOONGARCH_INT) {
+    //
+    // Interrupt
+    //
+    InterruptType =3D GetInterruptType (SystemContext);
+    if (InterruptType =3D=3D EXCEPT_LOONGARCH_INT_IPI) {
+      //
+      // APs may wake up via IPI IRQ during the SEC or PEI phase, clear th=
e IPI interrupt and
+      // perform the remaining work.
+      //
+      IpiInterruptHandler (InterruptType, SystemContext);
+      return;
+    } else {
+      ExceptionType =3D InterruptType;
+    }
+  } else {
+    //
+    // Exception
+    //
+    ExceptionType >>=3D CSR_ESTAT_EXC_SHIFT;
+  }
+
+  DefaultExceptionHandler (ExceptionType, SystemContext);
+}
+
+/**
+  Initializes all CPU exceptions entries and provides the default exceptio=
n 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 i=
nitialized
+                            with default exception handlers.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpuExceptionHandlers (
+  IN EFI_VECTOR_HANDOFF_INFO  *VectorInfo OPTIONAL
+  )
+{
+  return EFI_SUCCESS;
+}
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHa=
ndlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException=
HandlerLib.inf
index e7b1144f69..6bb194ea77 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLi=
b.inf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLi=
b.inf
@@ -2,6 +2,7 @@
 #  CPU Exception Handler library instance for SEC/PEI modules.
 #
 #  Copyright (c) 2012 - 2022, Intel Corporation. All rights reserved.<B=
R>
+#  Copyright (c) 2024, Loongson Technology Corporation Limited. All rights=
 reserved.<BR>
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
@@ -18,37 +19,47 @@
 #
 # The following information is for reference only and not required by the =
build tools.
 #
-#  VALID_ARCHITECTURES           =3D IA32 X64
+#  VALID_ARCHITECTURES           =3D IA32 X64 LOONGARCH64
 #
=20
 [Sources.Ia32]
-  Ia32/ExceptionHandlerAsm.nasm
-  Ia32/ExceptionTssEntryAsm.nasm
   Ia32/ArchExceptionHandler.c
   Ia32/ArchInterruptDefs.h
+  Ia32/ExceptionHandlerAsm.nasm
+  Ia32/ExceptionTssEntryAsm.nasm
=20
 [Sources.X64]
-  X64/SecPeiExceptionHandlerAsm.nasm
   X64/ArchExceptionHandler.c
   X64/ArchInterruptDefs.h
+  X64/SecPeiExceptionHandlerAsm.nasm
=20
-[Sources.common]
+[Sources.Ia32, Sources.X64]
   CpuExceptionCommon.h
   CpuExceptionCommon.c
   SecPeiCpuException.c
=20
+[Sources.LoongArch64]
+  LoongArch/ExceptionCommon.h
+  LoongArch/ExceptionCommon.c
+  LoongArch/SecPeiExceptionLib.c
+  LoongArch/LoongArch64/ArchExceptionHandler.c
+  LoongArch/LoongArch64/ExceptionHandlerAsm.S | GCC
+
 [Packages]
   MdePkg/MdePkg.dec
   MdeModulePkg/MdeModulePkg.dec
   UefiCpuPkg/UefiCpuPkg.dec
=20
-[LibraryClasses]
+[LibraryClasses.common]
   BaseLib
-  SerialPortLib
-  PrintLib
-  LocalApicLib
+  CpuLib
   PeCoffGetEntryPointLib
+  PrintLib
+  SerialPortLib
+
+[LibraryClasses.Ia32, LibraryClasses.X64]
   CcExitLib
+  LocalApicLib
=20
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 571b59b36f..f5febe46ba 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
 #
@@ -385,6 +386,10 @@
   # @Prompt Enable performance collecting when processor trace is enabled.
   gUefiCpuPkgTokenSpaceGuid.PcdCpuProcTracePerformanceCollecting|FALSE|BOO=
LEAN|0x60000020
=20
+  ## This PCD Contains the pointer to a CPU exception vector base address.
+  # @Prompt The pointer to a CPU exception vector base address.
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuExceptionVectorBaseAddress|0x0|UINT64|0x=
60000022
+
 [PcdsFixedAtBuild.X64, PcdsPatchableInModule.X64, PcdsDynamic.X64, PcdsDyn=
amicEx.X64]
   ## Indicate access to non-SMRAM memory is restricted to reserved, runtim=
e and ACPI NVS type after SmmReadyToLock.
   #  MMIO access is always allowed regardless of the value of this PCD.
=20
_._,_._,_

Groups.io Links:

=20 You receive all messages sent to this group. =20 =20

View/Reply Online (#114859) | =20 | Mute= This Topic | New Topic
Your Subscriptio= n | Contact Group Owner | Unsubscribe [rebecca@openfw.io]

_._,_._,_
--------------LZG4TW9uKD41Nr01bPyau0W6--