[edk2-devel] [edk2-platforms][PATCH 33/34] Platform/Ampere: Add AcpiApeiLib

Nhi Pham via groups.io nhi=os.amperecomputing.com at groups.io
Wed Dec 9 09:25:30 UTC 2020


From: Quan Nguyen <quan at os.amperecomputing.com>

This patch adds ACPI APEI helper library to support RAS features.

Signed-off-by: Nhi Pham <nhi at os.amperecomputing.com>
Signed-off-by: Quan Nguyen <quan at os.amperecomputing.com>
---
 Platform/Ampere/Library/AcpiApeiLib/AcpiApeiLib.inf |  39 ++++
 Platform/Ampere/Include/Library/AcpiApeiLib.h       | 158 ++++++++++++++
 Platform/Ampere/Library/AcpiApeiLib/AcpiApeiLib.c   | 227 ++++++++++++++++++++
 3 files changed, 424 insertions(+)

diff --git a/Platform/Ampere/Library/AcpiApeiLib/AcpiApeiLib.inf b/Platform/Ampere/Library/AcpiApeiLib/AcpiApeiLib.inf
new file mode 100644
index 000000000000..def5265c4113
--- /dev/null
+++ b/Platform/Ampere/Library/AcpiApeiLib/AcpiApeiLib.inf
@@ -0,0 +1,39 @@
+## @file
+#
+# Copyright (c) 2020, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                   = 0x0001001B
+  VERSION_STRING                = 1.0
+  BASE_NAME                     = AcpiApeiLib
+  MODULE_TYPE                   = BASE
+  LIBRARY_CLASS                 = AcpiApeiLib
+  FILE_GUID                     = DFC50F0A-C3D1-11E6-A4A6-CEC0C932CE01
+
+[Sources.common]
+  AcpiApeiLib.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  MdePkg/MdePkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  Silicon/Ampere/AmperePkg.dec
+  Silicon/Ampere/AmpereAltraPkg/Ac01Pkg.dec
+
+[LibraryClasses]
+  ArmLib
+  ArmPlatformLib
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  DxeServicesLib
+  IoLib
+  MemoryAllocationLib
+  PrintLib
+  TimerLib
+  UefiLib
+  SMProLib
diff --git a/Platform/Ampere/Include/Library/AcpiApeiLib.h b/Platform/Ampere/Include/Library/AcpiApeiLib.h
new file mode 100644
index 000000000000..963932d02ec9
--- /dev/null
+++ b/Platform/Ampere/Include/Library/AcpiApeiLib.h
@@ -0,0 +1,158 @@
+/** @file
+
+  Copyright (c) 2020, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _ACPI_APEI_LIB_H_
+#define _ACPI_APEI_LIB_H_
+
+#include <Base.h>
+#include <Guid/Cper.h>
+#include <IndustryStandard/Acpi63.h>
+
+/*
+ * BERT entry list
+ *
+ * All errors in BERT fall under one Error Source
+ */
+
+#define ACPI_APEI_BERT_MAX 1
+
+/*
+ * GHES entry list
+ *
+ * NOTE, adding more GHES entries requires you to add more GHES
+ * entries in the HEST.adt file.
+ */
+
+typedef enum {
+    ACPI_APEI_GHES_CPU = 0,
+    ACPI_APEI_GHES_L2C,
+    ACPI_APEI_GHES_L3C,
+    ACPI_APEI_GHES_MCU,
+    ACPI_APEI_GHES_IOB_RBM,
+    ACPI_APEI_GHES_IOB_GLBL,
+    ACPI_APEI_GHES_IOB_TRANS,
+    ACPI_APEI_GHES_XGIC,
+    ACPI_APEI_GHES_SMMU,
+    ACPI_APEI_GHES_SOC,
+    ACPI_APEI_GHES_SOC_MCU,
+    ACPI_APEI_GHES_MPA,
+    ACPI_APEI_GHES_MAX
+} ACPI_APEI_GHES_ENTRY;
+
+/*
+ * For each GHES entry, there is Error Status and Error Data that needs
+ * to be gathered and reported. The Error Data is stored in the following
+ * APEI Data Structures.
+ */
+
+#pragma pack(1)
+typedef struct {
+  EFI_ACPI_6_3_GENERIC_ERROR_DATA_ENTRY_STRUCTURE GED;
+  EFI_PROCESSOR_GENERIC_ERROR_DATA                PError;
+} ACPI_APEI_ERROR_DATA;
+
+typedef struct {
+  EFI_ACPI_6_3_GENERIC_ERROR_DATA_ENTRY_STRUCTURE GED;
+  EFI_PLATFORM_MEMORY_ERROR_DATA                  MError;
+} ACPI_APEI_MEM_ERROR_DATA;
+
+/*
+ * Error Status with one or more Error Data sections per error
+ * record make up an Error Status Block (ESB). The ESB will be
+ * linked to a GHES entry via the Error Status Address.
+ */
+
+#define ACPI_APEI_ESB_MAX_BERT_ERRORS    8
+#define ACPI_APEI_ESB_MAX_GHES_ERRORS    1
+#define ACPI_APEI_ESB_MAX_ERROR_INFO     23
+#define ACPI_APEI_ESB_FIRMWARE_MEMORY    984
+
+typedef struct {
+  EFI_ACPI_6_3_GENERIC_ERROR_STATUS_STRUCTURE    GES;
+  ACPI_APEI_ERROR_DATA                           data;
+  ACPI_APEI_ERROR_DATA                           info[ACPI_APEI_ESB_MAX_ERROR_INFO];
+} ACPI_APEI_ESB;
+
+
+/*
+ * Version 2 of RAS_APEI_ES between BIOS and Firmware.
+ *
+ * This is the memory view of Error Source Data for BERT and GHES entries
+ */
+
+typedef struct {
+  UINT32                     ErrorDataEntryCount;
+  UINT32                     Length;
+  ACPI_APEI_ESB              ESB[ACPI_APEI_ESB_MAX_BERT_ERRORS];
+} RAS_APEI_BERT_DATA;
+
+typedef struct {
+  UINT64                     ErrorStatusAddress;
+  UINT32                     ErrorDataEntryCount;
+  UINT32                     Length;
+  ACPI_APEI_ESB              ESB[ACPI_APEI_ESB_MAX_GHES_ERRORS];
+  UINT32                     Reserved; /* Reserved - keep data 64bit aligned */
+  UINT8                      FirmwareMemory[ACPI_APEI_ESB_FIRMWARE_MEMORY];
+} RAS_APEI_GHES_DATA;
+
+typedef struct {
+  UINT64 Resv1;              /* v1 ErrorStatusAddress set to 0 */
+  UINT64 Resv2;              /* v1 GES set to 0 */
+  UINT32                     TotalLength;
+  UINT32                     ErrorSourceCount;
+  RAS_APEI_BERT_DATA         ErrorSourceData[ACPI_APEI_BERT_MAX];
+} RAS_APEI_BERT_ES;
+
+typedef struct {
+  UINT64 Resv1;              /* v1 ErrorStatusAddress set to 0 */
+  UINT64 Resv2;              /* v1 GES set to 0 */
+  UINT32                     TotalLength;
+  UINT32                     ErrorSourceCount;
+  RAS_APEI_GHES_DATA         ErrorSourceData[ACPI_APEI_GHES_MAX];
+} RAS_APEI_GHES_ES;
+
+/*
+ * Version 1 of RAS_APEI_ES between BIOS and Firmware.
+ *
+ * This interface structure is no longer used. It is here
+ * only as reference for Version 2.
+ */
+
+typedef struct {
+  UINT64 ErrorStatusAddress; /* pointer to GHES.ErrorStatusAddress */
+  UINT64 Ges;                /* pointer to GES (use to report ErrorBlockStatus) */
+  UINT32 ErrorBlockStatus;   /* ErrorBlockStatus to report */
+  UINT32 Resv;               /* Reserved */
+} RAS_APEI_ES_VERSION_1;
+#pragma pack()
+
+/*
+ * AcpiApeiLib interface
+ */
+
+EFI_STATUS
+AcpiApeiLibInit (VOID);
+
+RAS_APEI_BERT_DATA*
+AcpiApeiLibGetBertData (VOID);
+
+RAS_APEI_GHES_DATA*
+AcpiApeiLibGetGhesData (
+  IN UINT32 ErrorSourceIdx
+  );
+
+#define APEI_ERROR_DETECTION_PMPRO        0
+#define APEI_ERROR_DETECTION_ATF          1
+
+EFI_STATUS
+AcpiApeiLibEnable (
+  UINT8 Enable,
+  UINT8 FwErrorDetection
+  );
+
+#endif /* _ACPI_APEI_LIB_H_ */
diff --git a/Platform/Ampere/Library/AcpiApeiLib/AcpiApeiLib.c b/Platform/Ampere/Library/AcpiApeiLib/AcpiApeiLib.c
new file mode 100644
index 000000000000..9962429d26d4
--- /dev/null
+++ b/Platform/Ampere/Library/AcpiApeiLib/AcpiApeiLib.c
@@ -0,0 +1,227 @@
+/** @file
+
+  Copyright (c) 2020, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/AcpiApeiLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/ArmLib.h>
+
+#define SMC_XRAS_PROXY_FUNC_ID  0xc300ff07
+
+enum {
+  SMC_XRAS_SET_APEI_PTR = 1,
+  SMC_XRAS_GET_APEI_PTR,
+  SMC_XRAS_ENABLE,
+  SMC_XRAS_DISABLE
+};
+
+/*
+ * Reserved Memory
+ */
+STATIC RAS_APEI_GHES_ES *FwRasApeiGhesLookUpTable = NULL;
+STATIC RAS_APEI_BERT_ES *FwRasApeiBertLookUpTable = NULL;
+
+/*
+ * AcpiApeiLibAllocateReservedMemForErrorSourceTable
+ */
+STATIC EFI_STATUS
+AcpiApeiLibAllocateReservedMemForErrorSourceTable (VOID)
+{
+  UINT32 Length;
+
+  /*
+   * Allocate reserved memory for each Error Source and initialize it.
+   */
+  Length = sizeof (RAS_APEI_GHES_ES);
+  FwRasApeiGhesLookUpTable = (RAS_APEI_GHES_ES *) AllocateReservedZeroPool (Length);
+  if (FwRasApeiGhesLookUpTable == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  FwRasApeiGhesLookUpTable->TotalLength = Length;
+  FwRasApeiGhesLookUpTable->ErrorSourceCount = ACPI_APEI_GHES_MAX;
+
+  /*
+   * Allocate a BootErrorSource.
+   *
+   * BERT does not distinguish errors based on an Error Source Like the HEST
+   * table does by using GHES entries. All errors in BERT fall under one Error
+   * Source (let's call it the BERT Error Source).
+   */
+  Length = sizeof (RAS_APEI_BERT_ES);
+  FwRasApeiBertLookUpTable = (RAS_APEI_BERT_ES *) AllocateReservedZeroPool (Length);
+  if (FwRasApeiBertLookUpTable == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  FwRasApeiBertLookUpTable->TotalLength = Length;
+  FwRasApeiBertLookUpTable->ErrorSourceCount = ACPI_APEI_BERT_MAX;
+
+  return EFI_SUCCESS;
+}
+
+/*
+ * AcpiApeiLibFreeReservedMem
+ */
+STATIC VOID
+AcpiApeiLibFreeReservedMem (VOID)
+{
+  if (FwRasApeiGhesLookUpTable != NULL) {
+    FreePool (FwRasApeiGhesLookUpTable);
+    FwRasApeiGhesLookUpTable = NULL;
+  }
+
+  if (FwRasApeiBertLookUpTable != NULL) {
+    FreePool (FwRasApeiBertLookUpTable);
+    FwRasApeiBertLookUpTable = NULL;
+  }
+}
+
+/*
+ * AcpiApeiLibAllocateReservedMem
+ */
+STATIC EFI_STATUS
+AcpiApeiLibAllocateReservedMem(VOID)
+{
+  EFI_STATUS Status;
+
+  /*
+   * Reserve Memory For ACPI/APEI ErrorSourceTable
+   */
+  Status = AcpiApeiLibAllocateReservedMemForErrorSourceTable ();
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR,
+      "%a: Allocating APEI Reserved Memory for ErrorSourceTable failed\n",
+      __FUNCTION__));
+    goto Error;
+  }
+
+  return Status;
+
+Error:
+  AcpiApeiLibFreeReservedMem ();
+  return Status;
+}
+
+/*
+ * AcpiApeiLibGetGhesData
+ */
+RAS_APEI_GHES_DATA*
+AcpiApeiLibGetGhesData (
+  IN UINT32 ErrorSourceIdx
+  )
+{
+  if ((FwRasApeiGhesLookUpTable == NULL) || (ErrorSourceIdx >= ACPI_APEI_GHES_MAX))
+    return NULL;
+
+  return &FwRasApeiGhesLookUpTable->ErrorSourceData[ErrorSourceIdx];
+}
+
+/*
+ * AcpiApeiLibGetBertData
+ */
+RAS_APEI_BERT_DATA*
+AcpiApeiLibGetBertData (VOID)
+{
+  if (FwRasApeiBertLookUpTable == NULL)
+    return NULL;
+
+  return &FwRasApeiBertLookUpTable->ErrorSourceData[0];
+}
+
+/*
+ * AcpiApeiLibInit
+ */
+EFI_STATUS
+AcpiApeiLibInit (VOID)
+{
+  EFI_STATUS Status;
+
+  /*
+   * Allocate Reserve Memory
+   */
+  Status = AcpiApeiLibAllocateReservedMem ();
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+STATIC VOID
+AcpiApeiLibAtfRasEnable (
+  UINT8 Enable
+  )
+{
+  ARM_SMC_ARGS SmcArgs;
+
+  SmcArgs.Arg0 = SMC_XRAS_PROXY_FUNC_ID;
+  SmcArgs.Arg1 = (Enable != 0) ? SMC_XRAS_ENABLE : SMC_XRAS_DISABLE;
+  SmcArgs.Arg2 = 0;
+  SmcArgs.Arg3 = 0;
+  SmcArgs.Arg4 = 0;
+
+  ArmCallSmc (&SmcArgs);
+}
+
+STATIC VOID
+AcpiApeiLibAtfApeiSetup (
+  UINT64 ApeiGhesPtr,
+  UINT64 ApeiBertPtr
+  )
+{
+  ARM_SMC_ARGS SmcArgs;
+
+  SmcArgs.Arg0 = SMC_XRAS_PROXY_FUNC_ID;
+  SmcArgs.Arg1 = SMC_XRAS_SET_APEI_PTR;
+  SmcArgs.Arg2 = ApeiGhesPtr;
+  SmcArgs.Arg3 = ApeiBertPtr;
+  SmcArgs.Arg4 = 0;
+
+  ArmCallSmc (&SmcArgs);
+}
+
+/*
+ * AcpiApeiLibEnable
+ */
+EFI_STATUS
+AcpiApeiLibEnable (
+  UINT8 Enable,
+  UINT8 FwErrorDetection
+  )
+{
+  UINT64 ApeiGhesPtr;
+  UINT64 ApeiBertPtr;
+
+  ArmInvalidateDataCache ();
+
+  if (Enable != 0) {
+    /*
+     * Setup firmware (e.g. ATF) for RAS_APEI module support
+     */
+    ApeiGhesPtr = (UINT64) FwRasApeiGhesLookUpTable;
+    ApeiBertPtr = (UINT64) FwRasApeiBertLookUpTable;
+
+    if (FwErrorDetection == APEI_ERROR_DETECTION_ATF) {
+      AcpiApeiLibAtfApeiSetup (ApeiGhesPtr, ApeiBertPtr);
+    }
+  }
+
+  if (FwErrorDetection == APEI_ERROR_DETECTION_ATF) {
+    AcpiApeiLibAtfRasEnable (Enable);
+  }
+
+  return EFI_SUCCESS;
+}
-- 
2.17.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#68533): https://edk2.groups.io/g/devel/message/68533
Mute This Topic: https://groups.io/mt/78825520/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list