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