feat(plat/arm): update common platform RAS implementation
Refactor the RAS implementation to be used as common platform RAS
implementation for all the platforms. As part of refactoring this patch
extends support to configure interrupt as PPI interrupt type in addition
to currently supported SPI interrupts.
This patch defines a RAS config data structure to be defined by each
platform. The RAS config data structure carries the event map and size
information. Each platform code during initialization phase must define
this RAS config and register it with common platform RAS module.
Signed-off-by: Omkar Anand Kulkarni <omkar.kulkarni@arm.com>
Change-Id: I4019b31386a7e9c197bcc83bdca47876ee854d0f
diff --git a/plat/arm/css/sgi/include/sgi_ras.h b/plat/arm/css/sgi/include/sgi_ras.h
index e69a684..0c2cf24 100644
--- a/plat/arm/css/sgi/include/sgi_ras.h
+++ b/plat/arm/css/sgi/include/sgi_ras.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2023, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,15 +7,52 @@
#ifndef SGI_RAS_H
#define SGI_RAS_H
+#include <lib/extensions/ras.h>
+#include <plat/common/platform.h>
+
+/*
+ * Interrupt type supported.
+ * - SGI_RAS_INTR_TYPE_SPI: Denotes a SPI interrupt
+ * - SGI_RAS_INTR_TYPE_PPI: Denotes a PPI interrupt
+ */
+#define SGI_RAS_INTR_TYPE_SPI 0
+#define SGI_RAS_INTR_TYPE_PPI 1
+
/*
- * Mapping the RAS interrupt with SDEI event number and the event
- * id used with Standalone MM code
+ * MM Communicate information structure. Required to generate MM Communicate
+ * payload to be shared with Standalone MM.
*/
+typedef struct mm_communicate_header {
+ struct efi_guid header_guid;
+ size_t message_len;
+ uint8_t data[1];
+} mm_communicate_header_t;
+
+/* RAS error info data structure. */
struct sgi_ras_ev_map {
int sdei_ev_num; /* SDEI Event number */
int intr; /* Physical intr number */
+ int intr_type; /* Interrupt Type (SPI or PPI)*/
+};
+
+/* RAS config data structure. Must be defined by each platform. */
+struct plat_sgi_ras_config {
+ struct sgi_ras_ev_map *ev_map;
+ int ev_map_size;
};
-int sgi_ras_intr_handler_setup(void);
+/*
+ * Find event map for a given interrupt number. On success, returns pointer
+ * to the event map. On error, returns NULL.
+ */
+struct sgi_ras_ev_map *sgi_find_ras_event_map_by_intr(uint32_t intr_num);
+
+/*
+ * Initialization function for the framework.
+ *
+ * Registers RAS config provided by the platform and then configures and
+ * enables interrupt for each registered error. On success, return 0.
+ */
+int sgi_ras_platform_setup(struct plat_sgi_ras_config *config);
#endif /* SGI_RAS_H */
diff --git a/plat/arm/css/sgi/ras/sgi_ras_common.c b/plat/arm/css/sgi/ras/sgi_ras_common.c
new file mode 100644
index 0000000..9789670
--- /dev/null
+++ b/plat/arm/css/sgi/ras/sgi_ras_common.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2018-2023, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <bl31/interrupt_mgmt.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include <sgi_ras.h>
+
+static struct plat_sgi_ras_config *sgi_ras_config;
+
+/*
+ * Find event map for a given interrupt number. On success, returns pointer to
+ * the event map. On error, returns NULL.
+ */
+struct sgi_ras_ev_map *sgi_find_ras_event_map_by_intr(uint32_t intr_num)
+{
+ struct sgi_ras_ev_map *map;
+ int size;
+ int i;
+
+ if (sgi_ras_config == NULL) {
+ ERROR("RAS config is NULL\n");
+ return NULL;
+ }
+
+ map = sgi_ras_config->ev_map;
+ size = sgi_ras_config->ev_map_size;
+
+ for (i = 0; i < size; i++) {
+ if (map->intr == intr_num)
+ return map;
+
+ map++;
+ }
+
+ return NULL;
+}
+
+/*
+ * Programs GIC registers and configures interrupt ID's as Group0 EL3
+ * interrupts. Current support is to register PPI and SPI interrupts.
+ */
+static void sgi_ras_intr_configure(int intr, int intr_type)
+{
+ plat_ic_set_interrupt_type(intr, INTR_TYPE_EL3);
+ plat_ic_set_interrupt_priority(intr, PLAT_RAS_PRI);
+ plat_ic_clear_interrupt_pending(intr);
+
+ /* Routing mode option available only for SPI interrupts */
+ if (intr_type == SGI_RAS_INTR_TYPE_SPI) {
+ plat_ic_set_spi_routing(intr, INTR_ROUTING_MODE_ANY,
+ (u_register_t)read_mpidr_el1());
+ }
+ plat_ic_enable_interrupt(intr);
+}
+
+/*
+ * Initialization function for the framework.
+ *
+ * Registers RAS config provided by the platform and then configures and
+ * enables interrupt for each registered error. On success, return 0.
+ */
+int sgi_ras_platform_setup(struct plat_sgi_ras_config *config)
+{
+ struct sgi_ras_ev_map *map;
+ int size;
+ int i;
+
+ /* Check if parameter is valid. */
+ if (config == NULL) {
+ ERROR("SGI: Failed to register RAS config\n");
+ return -1;
+ }
+
+ /*
+ * Maintain a reference to the platform RAS config data for later
+ * use.
+ */
+ sgi_ras_config = config;
+
+ map = sgi_ras_config->ev_map;
+ size = sgi_ras_config->ev_map_size;
+
+ for (i = 0; i < size; i++) {
+ sgi_ras_intr_configure(map->intr, map->intr_type);
+ map++;
+ }
+
+ INFO("SGI: Platform RAS setup successful\n");
+
+ return 0;
+}
diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk
index 6d17bc2..358316c 100644
--- a/plat/arm/css/sgi/sgi-common.mk
+++ b/plat/arm/css/sgi/sgi-common.mk
@@ -54,10 +54,6 @@
${CSS_ENT_BASE}/sgi_bl31_setup.c \
${CSS_ENT_BASE}/sgi_topology.c
-ifeq (${RAS_FFH_SUPPORT},1)
-BL31_SOURCES += ${CSS_ENT_BASE}/sgi_ras.c
-endif
-
ifneq (${RESET_TO_BL31},0)
$(error "Using BL31 as the reset vector is not supported on ${PLAT} platform. \
Please set RESET_TO_BL31 to 0.")
diff --git a/plat/arm/css/sgi/sgi_ras.c b/plat/arm/css/sgi/sgi_ras.c
deleted file mode 100644
index 7ac43dd..0000000
--- a/plat/arm/css/sgi/sgi_ras.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2018-2023, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <string.h>
-
-#include <bl31/interrupt_mgmt.h>
-#include <lib/extensions/ras.h>
-#include <plat/common/platform.h>
-
-#include <sgi_ras.h>
-
-struct err_record_info sgi_err_records[] = {
-
-};
-
-struct ras_interrupt sgi_ras_interrupts[] = {
-
-};
-
-REGISTER_ERR_RECORD_INFO(sgi_err_records);
-REGISTER_RAS_INTERRUPTS(sgi_ras_interrupts);
-
-static struct sgi_ras_ev_map *plat_sgi_get_ras_ev_map(void)
-{
- return NULL;
-}
-
-static int plat_sgi_get_ras_ev_map_size(void)
-{
- return 0;
-}
-
-static void sgi_ras_intr_configure(int intr)
-{
- plat_ic_set_interrupt_type(intr, INTR_TYPE_EL3);
- plat_ic_set_interrupt_priority(intr, PLAT_RAS_PRI);
- plat_ic_clear_interrupt_pending(intr);
- plat_ic_set_spi_routing(intr, INTR_ROUTING_MODE_ANY,
- (u_register_t)read_mpidr_el1());
- plat_ic_enable_interrupt(intr);
-}
-
-int sgi_ras_intr_handler_setup(void)
-{
- int i;
- struct sgi_ras_ev_map *map = plat_sgi_get_ras_ev_map();
- int size = plat_sgi_get_ras_ev_map_size();
-
- for (i = 0; i < size; i++) {
- sgi_ras_intr_configure(map->intr);
- map++;
- }
-
- INFO("SGI: RAS Interrupt Handler successfully registered\n");
-
- return 0;
-}