From nobody Mon Feb 9 19:05:52 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+66827+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+66827+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=arm.com ARC-Seal: i=1; a=rsa-sha256; t=1604070055; cv=none; d=zohomail.com; s=zohoarc; b=Ni0orLSEK6qRZ1v/7CZ3Dpj/gwoMTpLsZbSnkN9s1Gwoed8bDasp9FZ6ygRzCrC0x8k/iVHaXFlXrbv2RcunyQlCnkjyymKlIjAdHqLpJDHpGXCbgvDXRy09jQiM/4bXQSZ4xdKKnR77HWRPwqHtlRs6/N3SQrizdwrUrtfr9zU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1604070055; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=ZLttwr7AUTDYT6/PK5tlYVbp2S37I2qJTL/ZrZfZ3Bc=; b=c7ywbk4KFs4CQWyEbG9rjA28PeWEhdXmAo6BlvYfs+Rq989e4xAG1TzPUuVL/VsEjvGBeFrDXAWbTWgymMSfH4ZcGv7MCboRqNeLw01/1cHXJvPaD0+qh1mLmUK7gmkFHp0xObaqb6yurVHRUv4ONWMalYvkn0TRFc5EXi7RQeg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+66827+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1604070055546314.0156097663895; Fri, 30 Oct 2020 08:00:55 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id PHrhYY1788612xvuE29TsVm0; Fri, 30 Oct 2020 08:00:53 -0700 X-Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web11.10636.1604047326714500214 for ; Fri, 30 Oct 2020 01:42:06 -0700 X-Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 56A69143D; Fri, 30 Oct 2020 01:42:06 -0700 (PDT) X-Received: from usa.arm.com (a076764.blr.arm.com [10.162.16.42]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 3C37F3F719; Fri, 30 Oct 2020 01:42:04 -0700 (PDT) From: "Omkar Anand Kulkarni" To: devel@edk2.groups.io Cc: Ard Biesheuvel , Leif Lindholm , Sami Mujawar , Jiewen Yao Subject: [edk2-devel] [edk2-platforms][PATCH 1/6] Platform/ARM: Add DMC-620 RAS error handling driver Date: Fri, 30 Oct 2020 14:11:51 +0530 Message-Id: <20201030084156.8291-2-omkar.kulkarni@arm.com> In-Reply-To: <20201030084156.8291-1-omkar.kulkarni@arm.com> References: <20201030084156.8291-1-omkar.kulkarni@arm.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: 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,omkar.kulkarni@arm.com X-Gm-Message-State: TchlMCLTUqxBgmCYhywISj8ox1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1604070053; bh=k3x11nhlUZXFlKkZykg6uxnwgxFC0WRCRat8q3SdfLM=; h=Cc:Date:From:Reply-To:Subject:To; b=kOCk7bQQQa3TzXW+Jxp00p3qwFFIdE5NYgi3eezDr52FZSklForgM3A84XkGb2onugA Iv5VFZi1qxkAd28KlQ3znYAe19c3oPDqF4jovbEDnLvXHwEELQa8//XU9isik8i4ae8Ub 6/IGmtXxZ422OcneyGrzi+BYQ1jMBS8qvJE= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" DMC-620 memory controller improves system reliability by generating interrupts on detecting ECC errors on the data. Add a initial DMC-620 MM driver that implements a MMI handler for handling single-bit ECC error events originating from the DRAM. The driver implements the HEST error source descriptor protocol in order to publish the GHES error source descriptor for single-bit DRAM errors. The GHES error source descriptor that is published is of type 'memory error'. A GHES error source descriptor is pub;lished for each instances if the DMC-620 controller in the system. The driver registers a MMI handler for handling 1-bit DRAM ECC error events. The MMI handler, when invoked, reads the DMC-620 error record registers and populates the EFI_PLATFORM_MEMORY_ERROR_DATA type error section information structure with the corresponding information read from the error record registers. Co-authored-by: Thomas Abraham Signed-off-by: Omkar Anand Kulkarni --- Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.dec | 28 ++ Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.inf | 59 +++ Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.h | 209 +++++++++++ Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.c | 379 ++++++++++++= ++++++++ Platform/ARM/Drivers/Dmc620Mm/Dmc620MmErrorSourceInfo.c | 191 ++++++++++ 5 files changed, 866 insertions(+) diff --git a/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.dec b/Platform/ARM/Driv= ers/Dmc620Mm/Dmc620Mm.dec new file mode 100644 index 000000000000..2caa28879c35 --- /dev/null +++ b/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.dec @@ -0,0 +1,28 @@ +#/** @file +# +# Copyright (c) 2020, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#**/ + +[Defines] + DEC_SPECIFICATION =3D 0x0001001A + PACKAGE_NAME =3D Dmc620Mm + PACKAGE_GUID =3D 94110B10-8E72-42A0-8963-D2B57FCF0F38 + PACKAGE_VERSION =3D 0.1 + +[Guids] + gDmc620MmTokenSpaceGuid =3D {0xc305f72a, 0xd10d, 0x45e8, { 0x81, 0x78, 0= x51, 0x8b, 0x78, 0x62, 0x77, 0x79 } } + gArmDmcEventHandlerGuid =3D { 0x5ef0afd5, 0xe01a, 0x4c30, { 0x86, 0x19, = 0x45, 0x46, 0x26, 0x91, 0x80, 0x98 }} + +[PcdsFixedAtBuild.common] + gDmc620MmTokenSpaceGuid.PcdDmc620NumCtrl|2|UINT32|0x00000001 + gDmc620MmTokenSpaceGuid.PcdDmc620RegisterBase|0x4E000000|UINT64|0x000000= 02 + gDmc620MmTokenSpaceGuid.PcdDmc620CtrlSize|0x100000|UINT32|0x00000003 + gDmc620MmTokenSpaceGuid.PcdDmc620CorrectableErrorThreshold|10|UINT32|0x0= 0000004 + gDmc620MmTokenSpaceGuid.PcdDmc620ErrSourceCount|1|UINT32|0x00000005 + gDmc620MmTokenSpaceGuid.PcdDmc620DramErrorSdeiEventBase|0|UINT32|0x00000= 006 + gDmc620MmTokenSpaceGuid.PcdDmc620DramOneBitErrorDataBase|0|UINT64|0x0000= 0007 + gDmc620MmTokenSpaceGuid.PcdDmc620DramOneBitErrorDataSize|0|UINT64|0x0000= 0008 + gDmc620MmTokenSpaceGuid.PcdDmc620DramOneBitErrorSourceId|0|UINT16|0x0000= 0009 diff --git a/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.inf b/Platform/ARM/Driv= ers/Dmc620Mm/Dmc620Mm.inf new file mode 100644 index 000000000000..02c8107467aa --- /dev/null +++ b/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.inf @@ -0,0 +1,59 @@ +## @file +# StandaloneMM driver for the DMC620 Memory Controller. +# +# Copyright (c) 2020, ARM Limited. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x0001001A + BASE_NAME =3D StandaloneMmDmc620Driver + FILE_GUID =3D CB53ACD9-A1A1-43B3-A638-AC74DA5D9DA2 + MODULE_TYPE =3D MM_STANDALONE + VERSION_STRING =3D 1.0 + PI_SPECIFICATION_VERSION =3D 0x00010032 + ENTRY_POINT =3D Dmc620MmDriverInitialize + +[Sources] + Dmc620Mm.c + Dmc620MmErrorSourceInfo.c + +[Packages] + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + edk2-platforms/Platform/ARM/ARM.dec + Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + StandaloneMmPkg/StandaloneMmPkg.dec + +[LibraryClasses] + StandaloneMmDriverEntryPoint + DebugLib + ArmSvcLib + ArmLib + BaseMemoryLib + +[Protocols] + gMmHestErrorSourceDescProtocolGuid ##PRODUCES + +[FixedPcd] + gArmPlatformTokenSpaceGuid.PcdGhesGenericErrorDataMmBufferBase + gArmPlatformTokenSpaceGuid.PcdGhesGenericErrorDataMmBufferSize + + gDmc620MmTokenSpaceGuid.PcdDmc620NumCtrl + gDmc620MmTokenSpaceGuid.PcdDmc620RegisterBase + gDmc620MmTokenSpaceGuid.PcdDmc620CtrlSize + gDmc620MmTokenSpaceGuid.PcdDmc620CorrectableErrorThreshold + gDmc620MmTokenSpaceGuid.PcdDmc620ErrSourceCount + gDmc620MmTokenSpaceGuid.PcdDmc620DramErrorSdeiEventBase + gDmc620MmTokenSpaceGuid.PcdDmc620DramOneBitErrorDataBase + gDmc620MmTokenSpaceGuid.PcdDmc620DramOneBitErrorDataSize + gDmc620MmTokenSpaceGuid.PcdDmc620DramOneBitErrorSourceId + +[Guids] + gArmDmcEventHandlerGuid + +[Depex] + TRUE diff --git a/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.h b/Platform/ARM/Driver= s/Dmc620Mm/Dmc620Mm.h new file mode 100644 index 000000000000..36d4b5c6be0b --- /dev/null +++ b/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.h @@ -0,0 +1,209 @@ +/** @file + DMC-620 memory controller register defines, macros and structres used by + the DMC-620 StandaloneMM driver. + + Copyright (c) 2020, ARM Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef DMC620_MM_DRIVER_H_ +#define DMC620_MM_DRIVER_H_ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +// DMC-620 memory controller status register field values and masks +#define DMC620_MEMC_STATUS_MEMC_STATUS_MASK (0x00000007) +#define DMC620_MEMC_STATUS_MEMC_STATUS_READY (0x3) + +// DMC-620 memory controller command register +#define DMC620_MEMC_CMD_MEMC_CMD_EXECUTE_DRAIN (0x5) + +// DMC-620 memory controller Err Record 1/2 Status register bit masks +#define DMC620_ERR_STATUS_MV (0x04000000) +#define DMC620_ERR_STATUS_AV (0x80000000) + +// DMC-620 memory controller DRAM error record (Err1/2) Misc 0 register fi= elds +#define DMC620_ERR_MISC0_COLUMN_MASK (0x000003FF) +#define DMC620_ERR_MISC0_ROW_MASK (0x0FFFFC00) +#define DMC620_ERR_MISC0_ROW_SHIFT (10) +#define DMC620_ERR_MISC0_RANK_MASK (0x70000000) +#define DMC620_ERR_MISC0_RANK_SHIFT (28) +#define DMC620_ERR_MISC0_VAILD (0x80000000) + +// DMC-620 memory controller DRAM error record (Err1/2) Misc 1 register fi= elds +#define DMC620_ERR_MISC1_VAILD (0x80000000) +#define DMC620_ERR_MISC1_BANK_MASK (0x0000000F) + +// DMC-620 memory controller ErrGsr register bit masks +#define DMC620_DRAM_ECC_CORRECTED_FH (BIT0 << 1) + +// +// Macro to initialize the HEST GHESv2 Notification structure. +// +#define ARM_PLATFORM_ACPI_6_3_GHES_NOTIFICATION_STRUCT_INIT(Type, \ + PollInterval, EventId) { \ + Type, \ + sizeof (EFI_ACPI_6_3_HARDWARE_ERROR_NOTIFICATION_STRUCTURE), \ + {0, 0, 0, 0, 0, 0, 0}, /* ConfigurationWriteEnable */ \ + PollInterval, \ + EventId, \ + 0, /* Poll Interval Threshold Value */ \ + 0, /* Poll Interval Threshold Window */ \ + 0, /* Error Threshold Value */ \ + 0 /* Error Threshold Window */ \ +} + +// +// Macro to initialize the HEST GHESv2 Error Status and Read Ack register. +// +#define ARM_PLATFORM_ACPI_6_3_GHES_GENERIC_ADDRESS_STRUCT_INIT(Address) { = \ + 0, /* UINT8 Address Space ID */ \ + 64, /* Register Bit Width */ \ + 0, /* Register Bit Offset */ \ + 4, /* Access Size */ \ + Address /* CPER/Read Ack Addr */ \ +} + +//#pragma pack(1) + +// +// DMC-620 memory controller register definitions +// +typedef struct { + UINT32 MemcStatus; + UINT32 MemcConfig; + UINT32 MemcCmd; + UINT32 Reserved [0x1BD]; + UINT32 Err0Fr; + UINT32 Reserved1; + UINT32 Err0Ctlr0; + UINT32 Err0Ctlr1; + UINT32 Err0Status; + UINT8 Reserved2[0x740 - 0x714]; + UINT32 Err1Fr; + UINT32 Reserved3; + UINT32 Err1Ctlr; + UINT32 Reserved4; + UINT32 Err1Status; + UINT32 Reserved5; + UINT32 Err1Addr0; + UINT32 Err1Addr1; + UINT32 Err1Misc0; + UINT32 Err1Misc1; + UINT32 Err1Misc2; + UINT32 Err1Misc3; + UINT32 Err1Misc4; + UINT32 Err1Misc5; + UINT8 Reserved6[0x780 - 0x778]; + UINT32 Err2Fr; + UINT32 Reserved7; + UINT32 Err2Ctlr; + UINT32 Reserved8; + UINT32 Err2Status; + UINT32 Reserved9; + UINT32 Err2Addr0; + UINT32 Err2Addr1; + UINT32 Err2Misc0; + UINT32 Err2Misc1; + UINT32 Err2Misc2; + UINT32 Err2Misc3; + UINT32 Err2Misc4; + UINT32 Err2Misc5; + UINT8 Reserved10[0x7c0 - 0x7b8]; + //UINT32 Reserved11[0x58]; + UINT32 Reserved15[0x14];//hack + UINT32 Err4Status; + UINT32 Reserved16[0x43];//hack + UINT32 Errgsr; +} DMC620_REGS_TYPE; + +// +// DMC-620 memory controller error record register definition +// +typedef struct { + UINT32 ErrFr; + UINT32 Reserved; + UINT32 ErrCtlr; + UINT32 Reserved1; + UINT32 ErrStatus; + UINT32 Reserved2; + UINT32 ErrAddr0; + UINT32 ErrAddr1; + UINT32 ErrMisc0; + UINT32 ErrMisc1; + UINT32 ErrMisc2; + UINT32 ErrMisc3; + UINT32 ErrMisc4; + UINT32 ErrMisc5; + UINT8 Reserved3[0x780 - 0x778]; +} DMC620_ERR_REGS_TYPE; + +//#pragma pack() + +// +// List of supported error sources by DMC-620 memory controller +// +typedef enum { + DramEccCfh =3D 0, + DramEccFh, + ChiFh, + SramEccCfh, + SramEccFh, + DmcErrRecovery +} DMC_ERR_SOURCES; + +/** + MMI handler implementing the HEST error source desc protocol. + + Returns the error source descriptor information for all DMC(s) error sou= rces and + also returns its count and length. + + @param[in] This Pointer for this protocol + + @param[out] Buffer HEST error source descriptor Information + buffer. + @param[out] ErrorSourcesLength Total length of Error Source Descriptors + @param[out] ErrorSourceCount Total number of supported error sources. + + @retval EFI_SUCCESS Buffer has valid Error Source descriptor i= nformation. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + +**/ +EFI_STATUS +EFIAPI +DmcErrorSourceDescInfoGet ( + IN MM_HEST_ERROR_SOURCE_DESC_PROTOCOL *This, + OUT VOID **Buffer, + OUT UINTN *ErrorSourcesLength, + OUT UINTN *ErrorSourcesCount + ); + +/** + Allow reporting of supported DMC-620 error sources + + Install the Hest Error Source Descriptor protocol handler to allow publi= shing + of the supported DMC-620 memory controller error sources. + + @param[in] MmSystemTable Pointer to System table. + + @retval EFI_SUCCESS Protocol installation successful. + @retval EFI_INVALID_PARAMETER Invalid system table parameter. + +**/ + +EFI_STATUS +Dmc620InstallErrorSourceDescProtocol ( + IN EFI_MM_SYSTEM_TABLE *MmSystemTable + ); + +#endif // DMC620_MM_DRIVER_H_ diff --git a/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.c b/Platform/ARM/Driver= s/Dmc620Mm/Dmc620Mm.c new file mode 100644 index 000000000000..ee669085abea --- /dev/null +++ b/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.c @@ -0,0 +1,379 @@ +/** @file + DMC 620 Memory Controller error handling (Standalone MM) driver + + Supports Single Bit DRAM error handling for multiple DMC 620 instances. + On a error event, publishes the CPER error record of Memory type. + + Copyright (c) 2020, ARM Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +/** + Drain DMC-620 controller of any transactions. + + Performs pending direct_command operations and updates the register valu= es + with the next (new) values. The new values will be considered when the + DMC moves to ready state. + + @param [in] DmcCtrl Pointer to DMC620_x control registers + + @retval NONE. + +**/ +STATIC +VOID +Dmc620DrainController ( + IN DMC620_REGS_TYPE *DmcCtrl + ) +{ + UINT32 MemcStatus; + + MmioWrite32 ((UINTN)&DmcCtrl->MemcCmd, DMC620_MEMC_CMD_MEMC_CMD_EXECUTE_= DRAIN); + + do { + MemcStatus =3D MmioRead32 ((UINTN)&DmcCtrl->MemcStatus); + } while ((MemcStatus & DMC620_MEMC_STATUS_MEMC_STATUS_MASK) !=3D + DMC620_MEMC_STATUS_MEMC_STATUS_READY); +} + +/** + Helper function to handle the DMC-620 DRAM errors. + + Reads the DRAM error record registers. Creates a CPER error record of ty= pe + 'Memory Error' and populates it with DRAM error record registers. + + @param[in] DmcCtrl A pointer to DMC620 control registers. + @param[in] DmcInstance DMC instance which raised the RAS event. + @param[in] ErrRecType A type of the DMC error record. + @param[in] ErrorBlockBaseAddress Unique address for populating the error= block + status for given DMC error source. + + @return NONE. + +**/ +STATIC +VOID +Dmc620HandleDramError ( + IN DMC620_REGS_TYPE *DmcCtrl, + IN UINTN DmcInstance, + IN UINTN ErrRecType, + IN UINTN ErrorBlockBaseAddress + ) +{ + EFI_ACPI_6_3_GENERIC_ERROR_DATA_ENTRY_STRUCTURE *ErrBlockSectionDesc; + EFI_ACPI_6_3_GENERIC_ERROR_STATUS_STRUCTURE *ErrBlockStatusHeaderDat= a; + EFI_PLATFORM_MEMORY_ERROR_DATA MemorySectionInfo =3D {0= }; + DMC620_ERR_REGS_TYPE *ErrRecord; + EFI_GUID SectionType; + UINT32 ResetReg; + VOID *ErrBlockSectionData; + UINTN *ErrorStatusRegister; + UINTN *ReadAckRegister; + UINTN *ErrStatusBlock; + UINTN ErrStatus; + UINTN ErrAddr0; + UINTN ErrAddr1; + UINTN ErrMisc0; + UINTN ErrMisc1; + UINT8 CorrectedError; + + // + // Check the type of DRAM error (1-bit or 2-bit) and accordingly select + // error record to use. + // + if (ErrRecType =3D=3D DMC620_DRAM_ECC_CORRECTED_FH) { + DEBUG ((DEBUG_INFO, "DRAM ECC Corrected Fault (1-Bit ECC error) \n")); + ErrRecord =3D (DMC620_ERR_REGS_TYPE *)&DmcCtrl->Err1Fr; + CorrectedError =3D 1; + } + else { + DEBUG ((DEBUG_INFO, "DRAM ECC Fault Handling (2-bit ECC error)\n")); + ErrRecord =3D (DMC620_ERR_REGS_TYPE *)&DmcCtrl->Err2Fr; + CorrectedError =3D 0; + } + + // Read most recent DRAM error record registers. + do { + ErrStatus =3D MmioRead32 ((UINTN)&ErrRecord->ErrStatus); + ErrAddr0 =3D MmioRead32 ((UINTN)&ErrRecord->ErrAddr0); + ErrAddr1 =3D MmioRead32 ((UINTN)&ErrRecord->ErrAddr1); + ErrMisc0 =3D MmioRead32 ((UINTN)&ErrRecord->ErrMisc0); + ErrMisc1 =3D MmioRead32 ((UINTN)&ErrRecord->ErrMisc1); + + // Clear the status register so that new error records are populated. + ResetReg =3D MmioRead32 ((UINTN)&ErrRecord->ErrStatus); + MmioWrite32 ((UINTN)&ErrRecord->ErrStatus, ResetReg); + Dmc620DrainController (DmcCtrl); + } while (MmioRead32 ((UINTN)&ErrRecord->ErrStatus)); + + ErrStatus =3D MmioRead32 ((UINTN)&DmcCtrl->Err4Status);//hack + + //=20 + // Get Physical address of DRAM error from Address register and populate + // Memory Error Section. + // + if (ErrStatus & DMC620_ERR_STATUS_AV) { + DEBUG ((DEBUG_INFO, "DRAM Error: Address_0 : 0x%x Address_1 : 0x%x\n", + ErrAddr0, ErrAddr1)); + //=20 + // Populate Memory CPER section with DRAM error address (48 bits) and + // address mask fields. + // + MemorySectionInfo.ValidFields |=3D EFI_PLATFORM_MEMORY_PHY_ADDRESS_MAS= K_VALID; + MemorySectionInfo.PhysicalAddressMask =3D 0xFFFFFFFFFFFF; + MemorySectionInfo.ValidFields |=3D EFI_PLATFORM_MEMORY_PHY_ADDRESS_VAL= ID; + MemorySectionInfo.PhysicalAddress =3D (ErrAddr1 << 32) | ErrAddr0; + } + + // + // Read the Error Record Misc registers and populate relevant fields in + // Memory error section. + // + // Read DRAM MISC0 register and populate the Memory Error Section. + if ((ErrStatus & DMC620_ERR_STATUS_MV) + && (ErrMisc0 & DMC620_ERR_MISC0_VAILD)) + { + // Populate Memory Error Section wih DRAM column information. + MemorySectionInfo.ValidFields |=3D EFI_PLATFORM_MEMORY_COLUMN_VALID; + MemorySectionInfo.Column =3D ErrMisc0 & DMC620_ERR_MISC0_COLUMN_MASK; + + // + // Populate Memory Error Section with DRAM row information. + // Row bits (bit 16 and 17) are to be filled as extended. + // + MemorySectionInfo.ValidFields |=3D + EFI_PLATFORM_MEMORY_ERROR_EXTENDED_ROW_BIT_16_17_VALID; + MemorySectionInfo.Row =3D + (ErrMisc0 & DMC620_ERR_MISC0_ROW_MASK) >> DMC620_ERR_MISC0_ROW_SHIFT; + MemorySectionInfo.Extended =3D + (ErrMisc0 & DMC620_ERR_MISC0_ROW_MASK) >> (DMC620_ERR_MISC0_ROW_SHIF= T + 16); + + // Populate Memory Error Section wih DRAM rank information. + MemorySectionInfo.ValidFields |=3D EFI_PLATFORM_MEMORY_ERROR_RANK_NUM_= VALID; + MemorySectionInfo.RankNum =3D (ErrMisc0 & DMC620_ERR_MISC0_RANK_MASK) = >> + DMC620_ERR_MISC0_RANK_SHIFT; + } + + // Read DRAM MISC1 register and populate the Memory Error Section. + if ((ErrStatus & DMC620_ERR_STATUS_MV) + && (ErrMisc1 & DMC620_ERR_MISC1_VAILD)) + { + MemorySectionInfo.ValidFields |=3D EFI_PLATFORM_MEMORY_BANK_VALID; + MemorySectionInfo.Bank =3D (ErrMisc1 & DMC620_ERR_MISC1_BANK_MASK); + } + + // + // Misc registers 2..5 are not used and convey only the error counter + // information. They are cleared as they do not contribute in Error + // Record creation. + // + if (ErrStatus & DMC620_ERR_STATUS_MV) { + ResetReg =3D 0x0; + MmioWrite32 ((UINTN)&ErrRecord->ErrMisc2, ResetReg); + MmioWrite32 ((UINTN)&ErrRecord->ErrMisc3, ResetReg); + MmioWrite32 ((UINTN)&ErrRecord->ErrMisc4, ResetReg); + MmioWrite32 ((UINTN)&ErrRecord->ErrMisc5, ResetReg); + } + + // + // Reset error records Status register for recording new DRAM error synd= rome + // information. + // + ResetReg =3D MmioRead32 ((UINTN)&ErrRecord->ErrStatus); + MmioWrite32 ((UINTN)&ErrRecord->ErrStatus, ResetReg); + Dmc620DrainController (DmcCtrl); + + ErrStatus =3D 0;//hack + ResetReg =3D MmioRead32 ((UINTN)&DmcCtrl->Err4Status); + MmioWrite32 ((UINTN)&DmcCtrl->Err4Status, ResetReg); + Dmc620DrainController (DmcCtrl); + + // + // Allocate memory for Error Acknowledge register, Error Status register= and + // Error status block data. + // + ReadAckRegister =3D (UINTN *)ErrorBlockBaseAddress; + ErrorStatusRegister =3D (UINTN *)ErrorBlockBaseAddress + 1; + ErrStatusBlock =3D (UINTN *)ErrorStatusRegister + 1; + + // Initialize Error Status Register with Error Status Block address. + *ErrorStatusRegister =3D (UINTN)ErrStatusBlock; + + // + // Locate Block Status Header base address and populate it with Error St= atus + // Block Header information. + // + ErrBlockStatusHeaderData =3D (EFI_ACPI_6_3_GENERIC_ERROR_STATUS_STRUCTUR= E *) + ErrStatusBlock; + *ErrBlockStatusHeaderData =3D + (EFI_ACPI_6_3_GENERIC_ERROR_STATUS_STRUCTURE) { + .BlockStatus =3D { + .UncorrectableErrorValid =3D ((CorrectedError =3D=3D 0) ? 0:1), + .CorrectableErrorValid =3D ((CorrectedError =3D=3D 1) ? 1:0), + .MultipleUncorrectableErrors =3D 0x0, + .MultipleCorrectableErrors =3D 0x0, + .ErrorDataEntryCount =3D 0x1 + }, + .RawDataOffset =3D (sizeof(EFI_ACPI_6_3_GENERIC_ERROR_STATUS_STRUCTU= RE) + + sizeof(EFI_ACPI_6_3_GENERIC_ERROR_DATA_ENTRY_STRUCT= URE)), + .RawDataLength =3D 0, + .DataLength =3D (sizeof(EFI_ACPI_6_3_GENERIC_ERROR_DATA_ENTRY_STRUCT= URE) + + sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA)), + .ErrorSeverity =3D ((CorrectedError =3D=3D 1) ? + EFI_ACPI_6_3_ERROR_SEVERITY_CORRECTED: + EFI_ACPI_6_3_ERROR_SEVERITY_FATAL= ), + }; + + // + // Locate Section Descriptor base address and populate Error Status Sect= ion + // Descriptor data. + // + ErrBlockSectionDesc =3D (EFI_ACPI_6_3_GENERIC_ERROR_DATA_ENTRY_STRUCTURE= *) + (ErrBlockStatusHeaderData + 1); + *ErrBlockSectionDesc =3D + (EFI_ACPI_6_3_GENERIC_ERROR_DATA_ENTRY_STRUCTURE) { + .ErrorSeverity =3D ((CorrectedError =3D=3D 1) ? + EFI_ACPI_6_3_ERROR_SEVERITY_CORRECTED: + EFI_ACPI_6_3_ERROR_SEVERITY_FATAL), + .Revision =3D EFI_ACPI_6_3_GENERIC_ERROR_DATA_ENTRY_REVISION, + .ValidationBits =3D 0, + .Flags =3D 0, + .ErrorDataLength =3D sizeof (EFI_PLATFORM_MEMORY_ERROR_DATA), + .FruId =3D {0}, + .FruText =3D {0}, + .Timestamp =3D {0}, + }; + SectionType =3D (EFI_GUID) EFI_ERROR_SECTION_PLATFORM_MEMORY_GUID; + CopyGuid ((EFI_GUID *)ErrBlockSectionDesc->SectionType, &SectionType); + + // Locate Section base address and populate Memory Error Section data. + ErrBlockSectionData =3D (VOID *)(ErrBlockSectionDesc + 1); + CopyMem ( + ErrBlockSectionData, + (VOID *)&MemorySectionInfo, + sizeof (EFI_PLATFORM_MEMORY_ERROR_DATA) + ); +} + +/** + DMC620 RAS event handler. + + Mutiple DMC error processing support. Current implementation handles the= DRAM + ECC errors. + + @param[in] DispatchHandle The unique handle assigned to this handle= r by + MmiHandlerRegister(). + @param[in] Context Points to an optional handler context whi= ch + was specified when the handler was regist= ered. + @param[in, out] CommBuffer A pointer to a collection of data in memo= ry that + will be conveyed from a non-MM environmen= t into + an MM environment. + @param[in, out] CommBufferSize The size of the CommBuffer. + + @retval EFI_SUCCESS Event handler successful. + @retval Other Failure of event handler. + +**/ +STATIC +EFI_STATUS +EFIAPI +Dmc620ErrorEventHandler ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context, OPTIONAL + IN OUT VOID *CommBuffer, OPTIONAL + IN OUT UINTN *CommBufferSize OPTIONAL + ) +{ + DMC620_REGS_TYPE *DmcCtrl; + UINTN DmcIdx; + UINTN ErrGsr; + + // DMC instance which raised RAS error event. + DmcIdx =3D *(UINTN *)CommBuffer; + // Base address of the DMC instance. + DmcCtrl =3D (DMC620_REGS_TYPE *)(FixedPcdGet64 (PcdDmc620RegisterBase) + + (FixedPcdGet64 (PcdDmc620CtrlSize) * DmcIdx)); + + DEBUG (( + DEBUG_INFO, + "DMC error event raised for DMC: %d with DmcBaseAddr: 0x%x \n", + DmcIdx, (UINTN)DmcCtrl + )); + + ErrGsr =3D MmioRead32 ((UINTN)&DmcCtrl->Errgsr); + ErrGsr =3D 0x2; //HACK + + if (ErrGsr & DMC620_DRAM_ECC_CORRECTED_FH) { + // Handle corrected 1-bit DRAM ECC error. + Dmc620HandleDramError ( + DmcCtrl, + DmcIdx, + DMC620_DRAM_ECC_CORRECTED_FH, + FixedPcdGet64 (PcdDmc620DramOneBitErrorDataBase) + + (FixedPcdGet64 (PcdDmc620DramOneBitErrorDataSize) * DmcIdx)); + } else { + // ToDo: Add support for other DMC620 error sources. + DEBUG ((DEBUG_ERROR, "Unsupported DMC-620 error reported, ignoring\n")= ); + } + + // No data to send using the MM communication buffer so clear the comm b= uffer + // size. + *CommBufferSize =3D 0; + + return EFI_SUCCESS; +} + +/** + Initialize function for the driver. + + Registers MMI handlers to process RAS events on DMC and installs required + protocols to publish the error source descriptors. + + @param[in] ImageHandle Handle to image. + @param[in] SystemTable Pointer to System table. + + @retval EFI_SUCCESS On successful installation of RAS handlers for DMC. + @retval Other Failure in installing RAS handlers for DMC. + +**/ +EFI_STATUS +EFIAPI +Dmc620MmDriverInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_MM_SYSTEM_TABLE *SystemTable + ) +{ + EFI_MM_SYSTEM_TABLE *mMmst; + EFI_STATUS Status; + EFI_HANDLE DispatchHandle; + + ASSERT (SystemTable !=3D NULL); + mMmst =3D SystemTable; + + // Register RAS event MMI handlers. + Status =3D mMmst->MmiHandlerRegister ( + Dmc620ErrorEventHandler, + &gArmDmcEventHandlerGuid, + &DispatchHandle + ); + if (EFI_ERROR(Status)) { + DEBUG (( + DEBUG_ERROR, + "Registration failed for DMC RAS event handler, Status:%r\n", + Status + )); + + return Status; + } + + // Installs the HEST error source descriptor protocol. + Status =3D Dmc620InstallErrorSourceDescProtocol (SystemTable); + if (EFI_ERROR(Status)) { + mMmst->MmiHandlerUnRegister (DispatchHandle); + } + + return Status; +} diff --git a/Platform/ARM/Drivers/Dmc620Mm/Dmc620MmErrorSourceInfo.c b/Plat= form/ARM/Drivers/Dmc620Mm/Dmc620MmErrorSourceInfo.c new file mode 100644 index 000000000000..b7cc6368a2a4 --- /dev/null +++ b/Platform/ARM/Drivers/Dmc620Mm/Dmc620MmErrorSourceInfo.c @@ -0,0 +1,191 @@ +/** @file + DMC-620 Memory Controller HEST error source descriptors + + Implements the HEST Error Source Descriptor protocol. Publishes the Error + Sources supported using the GHESv2 type error source descriptor. + + Copyright (c) 2020, ARM Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +/** + Populate the DRAM Error Source Descriptor. + + Populate DMC-620 DRAM error source descriptor as a GHESv2 type in the HE= ST + table. The error source descriptor is populate with appropriate values + based on the instance number of DMC-620. + + @param[in] DmcIdx Instance number of the DMC-620. + @param[in] ErrorDesc HEST error source descriptor Information + +**/ +STATIC +VOID +EFIAPI +Dmc620SetupDramErrorDescriptor ( + IN EFI_ACPI_6_3_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE *Erro= rDesc, + IN UINTN DmcIdx + ) +{ + UINTN ErrorBlockData; +=20 + // + // Address of reserved memory for the error status block that will be us= ed + // to hold the information about the DRAM error. + // + ErrorBlockData =3D FixedPcdGet64 (PcdDmc620DramOneBitErrorDataBase) + + (FixedPcdGet64 (PcdDmc620DramOneBitErrorDataSize) * D= mcIdx); + + // Populate the DRAM error descriptor. + *ErrorDesc =3D + (EFI_ACPI_6_3_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE) { + .Type =3D EFI_ACPI_6_3_GENERIC_HARDWARE_ERROR_VERSION_2, + .SourceId =3D FixedPcdGet16 (PcdDmc620DramOneBitErrorSourceId) + Dmc= Idx, + .RelatedSourceId =3D 0xFFFF, + .Flags =3D 0, + .Enabled =3D 1, + .NumberOfRecordsToPreAllocate =3D 1, + .MaxSectionsPerRecord =3D 1, + .MaxRawDataLength =3D sizeof (EFI_PLATFORM_MEMORY_ERROR_DATA), + .ErrorStatusAddress =3D + ARM_PLATFORM_ACPI_6_3_GHES_GENERIC_ADDRESS_STRUCT_INIT ( + (ErrorBlockData + 8) + ), + .NotificationStructure =3D + ARM_PLATFORM_ACPI_6_3_GHES_NOTIFICATION_STRUCT_INIT ( + EFI_ACPI_6_3_HARDWARE_ERROR_NOTIFICATION_SOFTWARE_DELEGATED_EXCE= PTION, + 0, + FixedPcdGet32 (PcdDmc620DramErrorSdeiEventBase) + DmcIdx + ), + .ErrorStatusBlockLength =3D + sizeof (EFI_ACPI_6_3_GENERIC_ERROR_STATUS_STRUCTURE) + + sizeof (EFI_ACPI_6_3_GENERIC_ERROR_DATA_ENTRY_STRUCTURE) + + sizeof (EFI_PLATFORM_MEMORY_ERROR_DATA), + .ReadAckRegister =3D + ARM_PLATFORM_ACPI_6_3_GHES_GENERIC_ADDRESS_STRUCT_INIT (ErrorBlock= Data), + .ReadAckPreserve =3D 0, + .ReadAckWrite =3D 0 + }; +} + +/** + MMI handler implementing the HEST error source descriptor protocol. + + Returns the error source descriptor information for all DMC(s) error sou= rces + and also returns its count and length. Computes base addresses for each + supported error source and populate the global context with the base add= ress + information. + + @param[in] This Pointer for this protocol. + @param[out] Buffer HEST error source descriptor Information + buffer. + @param[out] ErrorSourcesLength Total length of Error Source Descriptors + @param[out] ErrorSourceCount Total number of supported error spurces. + + @retval EFI_SUCCESS Buffer has valid Error Source descriptor + information. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + +**/ +STATIC +EFI_STATUS +EFIAPI +Dmc620ErrorSourceDescInfoGet ( + IN MM_HEST_ERROR_SOURCE_DESC_PROTOCOL *This, + OUT VOID **Buffer, + OUT UINTN *ErrorSourcesLength, + OUT UINTN *ErrorSourcesCount + ) +{ + EFI_ACPI_6_3_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE *ErrorDes= criptor; + UINTN DmcIdx; + + // + // Update the error source length and error source count for error sourc= es + // supported by all DMCs. + // + *ErrorSourcesLength =3D + FixedPcdGet64 (PcdDmc620NumCtrl) * + FixedPcdGet64 (PcdDmc620ErrSourceCount) * + sizeof(EFI_ACPI_6_3_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE); + *ErrorSourcesCount =3D FixedPcdGet64 (PcdDmc620NumCtrl) * + FixedPcdGet64 (PcdDmc620ErrSourceCount); + + // + // If 'Buffer' is NULL, this invocation of the protocol handler is to + // determine the total size of all the error source descriptor instances. + // + if (Buffer =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + // Buffer to be updated with error source descriptor(s) information. + ErrorDescriptor =3D + (EFI_ACPI_6_3_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE *)*Buf= fer; + + // + // Populate the available error source descriptor for all the DMC-620 + // instances. + // + for (DmcIdx =3D 0; DmcIdx < FixedPcdGet64 (PcdDmc620NumCtrl); DmcIdx++) + { + // Add the one-bit DRAM error source descriptor.=20 + Dmc620SetupDramErrorDescriptor(ErrorDescriptor, DmcIdx); + ErrorDescriptor++; + } + + return EFI_SUCCESS; +} + +// +// DMC-620 MM_HEST_ERROR_SOURCE_DESC_PROTOCOL protocol instance. +// +STATIC MM_HEST_ERROR_SOURCE_DESC_PROTOCOL mDmc620ErrorSourceDesc =3D { + Dmc620ErrorSourceDescInfoGet +}; + +/** + Allow reporting of supported DMC-620 error sources + + Install the Hest Error Source Descriptor protocol handler to allow publi= shing + of the supported DMC-620 memory controller error sources. + + @param[in] MmSystemTable Pointer to System table. + + @retval EFI_SUCCESS Protocol installation successful. + @retval EFI_INVALID_PARAMETER Invalid system table parameter. + +**/ +EFI_STATUS +Dmc620InstallErrorSourceDescProtocol ( + IN EFI_MM_SYSTEM_TABLE *MmSystemTable + ) +{ + EFI_HANDLE mDmcHandle =3D NULL; + EFI_STATUS Status; + + // Check if the MmSystemTable is initialized. + if (MmSystemTable =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + // Install HEST error source descriptor protocol for DMC(s). + Status =3D MmSystemTable->MmInstallProtocolInterface ( + &mDmcHandle, + &gMmHestErrorSourceDescProtocolGuid, + EFI_NATIVE_INTERFACE, + &mDmc620ErrorSourceDesc + ); + if (EFI_ERROR(Status)) { + DEBUG (( + DEBUG_ERROR, + "Failed installing HEST error source descriptor protocol, status: %r= \n", + Status + )); + } + + return Status; +} --=20 2.17.1 -=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 (#66827): https://edk2.groups.io/g/devel/message/66827 Mute This Topic: https://groups.io/mt/77913845/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-