mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-17 01:54:22 +00:00
Merge changes from topic "RAS_REFACTORING" into integration
* changes: feat(board/rdn2): enable base element RAM RAS support on RD-N2 platform feat(plat/arm): add memory map entry for CPER memory region feat(plat/arm): firmware first error handling support for base RAMs feat(plat/arm): update common platform RAS implementation feat(plat/sgi): remove RAS setup call from common code refactor(plat/sgi): deprecate DMC-620 RAS support fix(plat/common): register PLAT_SP_PRI only if not already registered fix(plat/sgi): update PLAT_SP_PRI macro definition fix(plat/arm): add RAS_FFH_SUPPORT check for RAS EHF priority
This commit is contained in:
commit
6b6cefbf7b
17 changed files with 359 additions and 207 deletions
|
@ -775,7 +775,9 @@ MEASURED_BOOT
|
|||
#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE)
|
||||
|
||||
/* Priority levels for ARM platforms */
|
||||
#if RAS_FFH_SUPPORT
|
||||
#define PLAT_RAS_PRI 0x10
|
||||
#endif
|
||||
#define PLAT_SDEI_CRITICAL_PRI 0x60
|
||||
#define PLAT_SDEI_NORMAL_PRI 0x70
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#define PLATFORM_DEF_H
|
||||
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
#include <sgi_sdei.h>
|
||||
#include <sgi_soc_platform_def_v2.h>
|
||||
|
||||
#if (CSS_SGI_PLATFORM_VARIANT == 1)
|
||||
|
|
14
plat/arm/board/rdn2/include/rdn2_ras.h
Normal file
14
plat/arm/board/rdn2/include/rdn2_ras.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* Copyright (c) 2023, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef RDN2_RAS_H
|
||||
#define RDN2_RAS_H
|
||||
|
||||
#include <sgi_ras.h>
|
||||
|
||||
extern struct plat_sgi_ras_config ras_config;
|
||||
|
||||
#endif /* RDN2_RAS_H */
|
|
@ -69,6 +69,12 @@ BL31_SOURCES += drivers/arm/gic/v3/gic600_multichip.c
|
|||
BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
|
||||
endif
|
||||
|
||||
ifeq (${RAS_FFH_SUPPORT},1)
|
||||
BL31_SOURCES += ${RDN2_BASE}/rdn2_ras.c \
|
||||
${CSS_ENT_BASE}/ras/sgi_ras_common.c \
|
||||
${CSS_ENT_BASE}/ras/sgi_ras_sram.c
|
||||
endif
|
||||
|
||||
# Add the FDT_SOURCES and options for Dynamic Config
|
||||
FDT_SOURCES += ${RDN2_BASE}/fdts/${PLAT}_fw_config.dts \
|
||||
${RDN2_BASE}/fdts/${PLAT}_tb_fw_config.dts
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <drivers/arm/gic600_multichip.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <rdn2_ras.h>
|
||||
#include <sgi_soc_platform_def_v2.h>
|
||||
#include <sgi_plat.h>
|
||||
|
||||
|
@ -134,5 +135,9 @@ void bl31_platform_setup(void)
|
|||
#endif
|
||||
|
||||
sgi_bl31_common_platform_setup();
|
||||
|
||||
#if RAS_FFH_SUPPORT
|
||||
sgi_ras_platform_setup(&ras_config);
|
||||
#endif
|
||||
}
|
||||
#endif /* IMAGE_BL31 */
|
||||
|
|
46
plat/arm/board/rdn2/rdn2_ras.c
Normal file
46
plat/arm/board/rdn2/rdn2_ras.c
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2023, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
#include <sgi_ras.h>
|
||||
#include <sgi_sdei.h>
|
||||
|
||||
struct sgi_ras_ev_map plat_ras_map[] = {
|
||||
/* Non Secure base RAM ECC CE interrupt */
|
||||
{SGI_SDEI_DS_EVENT_0, NS_RAM_ECC_CE_INT, SGI_RAS_INTR_TYPE_SPI},
|
||||
|
||||
/* Non Secure base RAM ECC UE interrupt */
|
||||
{SGI_SDEI_DS_EVENT_0, NS_RAM_ECC_UE_INT, SGI_RAS_INTR_TYPE_SPI},
|
||||
};
|
||||
|
||||
/* RAS error record list definition, used by the common RAS framework. */
|
||||
struct err_record_info plat_err_records[] = {
|
||||
/* Base element RAM Non-secure error record. */
|
||||
ERR_RECORD_MEMMAP_V1(SOC_NS_RAM_ERR_REC_BASE, 4, NULL,
|
||||
&sgi_ras_sram_intr_handler, 0),
|
||||
};
|
||||
|
||||
/* RAS error interrupt list definition, used by the common RAS framework. */
|
||||
struct ras_interrupt plat_ras_interrupts[] = {
|
||||
{
|
||||
.intr_number = NS_RAM_ECC_CE_INT,
|
||||
.err_record = &plat_err_records[0],
|
||||
}, {
|
||||
.intr_number = NS_RAM_ECC_UE_INT,
|
||||
.err_record = &plat_err_records[0],
|
||||
},
|
||||
};
|
||||
|
||||
/* Registers the RAS error record list with common RAS framework. */
|
||||
REGISTER_ERR_RECORD_INFO(plat_err_records);
|
||||
/* Registers the RAS error interrupt info list with common RAS framework. */
|
||||
REGISTER_RAS_INTERRUPTS(plat_ras_interrupts);
|
||||
|
||||
/* Platform RAS handling config data definition */
|
||||
struct plat_sgi_ras_config ras_config = {
|
||||
plat_ras_map,
|
||||
ARRAY_SIZE(plat_ras_map)
|
||||
};
|
|
@ -8,8 +8,16 @@
|
|||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#define RDN2_TZC_CPER_REGION \
|
||||
{CSS_SGI_SP_CPER_BUF_BASE, (CSS_SGI_SP_CPER_BUF_BASE + \
|
||||
CSS_SGI_SP_CPER_BUF_SIZE) - 1, TZC_REGION_S_NONE, \
|
||||
PLAT_ARM_TZC_NS_DEV_ACCESS}
|
||||
|
||||
static const arm_tzc_regions_info_t tzc_regions[] = {
|
||||
ARM_TZC_REGIONS_DEF,
|
||||
#if RAS_FFH_SUPPORT
|
||||
RDN2_TZC_CPER_REGION,
|
||||
#endif
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -204,7 +204,11 @@
|
|||
SOC_CSS_DEVICE_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
|
||||
|
||||
#if RAS_FFH_SUPPORT
|
||||
#define PLAT_SP_PRI PLAT_RAS_PRI
|
||||
#else
|
||||
#define PLAT_SP_PRI 0x10
|
||||
#endif
|
||||
|
||||
#if SPM_MM && RAS_FFH_SUPPORT
|
||||
/*
|
||||
|
|
|
@ -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,57 @@
|
|||
#ifndef SGI_RAS_H
|
||||
#define SGI_RAS_H
|
||||
|
||||
#include <lib/extensions/ras.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
/*
|
||||
* Mapping the RAS interrupt with SDEI event number and the event
|
||||
* id used with Standalone MM code
|
||||
* 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
|
||||
|
||||
/*
|
||||
* 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)*/
|
||||
};
|
||||
|
||||
int sgi_ras_intr_handler_setup(void);
|
||||
/* 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;
|
||||
};
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/* Base element RAM RAS interrupt handler function. */
|
||||
int sgi_ras_sram_intr_handler(const struct err_record_info *err_rec,
|
||||
int probe_data,
|
||||
const struct err_handler_data *const data);
|
||||
|
||||
#endif /* SGI_RAS_H */
|
||||
|
|
|
@ -58,6 +58,11 @@
|
|||
#define END_KEY_BASE (SOC_KEYS_BASE + 0x0044)
|
||||
#define END_KEY_SIZE U(32)
|
||||
|
||||
/* Base Element RAM error definitions */
|
||||
#define SOC_NS_RAM_ERR_REC_BASE UL(0x2A4C0000)
|
||||
#define NS_RAM_ECC_CE_INT U(87)
|
||||
#define NS_RAM_ECC_UE_INT U(88)
|
||||
|
||||
#define SOC_PLATFORM_PERIPH_MAP_DEVICE MAP_REGION_FLAT( \
|
||||
SOC_PLATFORM_PERIPH_BASE, \
|
||||
SOC_PLATFORM_PERIPH_SIZE, \
|
||||
|
|
99
plat/arm/css/sgi/ras/sgi_ras_common.c
Normal file
99
plat/arm/css/sgi/ras/sgi_ras_common.c
Normal file
|
@ -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;
|
||||
}
|
112
plat/arm/css/sgi/ras/sgi_ras_sram.c
Normal file
112
plat/arm/css/sgi/ras/sgi_ras_sram.c
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2023, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <bl31/interrupt_mgmt.h>
|
||||
#include <lib/el3_runtime/context_mgmt.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <services/sdei.h>
|
||||
#include <services/spm_mm_svc.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
#include <sgi_ras.h>
|
||||
|
||||
/* Base Element RAM Error Record offsets. */
|
||||
#define ERRSTATUS U(0)
|
||||
#define ERRCODE U(8)
|
||||
#define ERRADDR U(12)
|
||||
|
||||
/*
|
||||
* Base Element RAM error information data structure communicated as part of MM
|
||||
* Communication data payload.
|
||||
*/
|
||||
typedef struct sgi_sram_err_info {
|
||||
uint32_t err_status;
|
||||
uint32_t err_code;
|
||||
uint32_t err_addr;
|
||||
} sgi_sram_err_info_t;
|
||||
|
||||
/*
|
||||
* MM Communicate message header GUID to indicate the payload is intended for
|
||||
* base element RAM MM driver.
|
||||
*/
|
||||
struct efi_guid sram_ecc_event_guid = {
|
||||
0x7312db4f, 0xd0c4, 0x4fb5,
|
||||
{ 0x81, 0x2c, 0xb7, 0x4b, 0xc6, 0xc4, 0xa9, 0x38 }
|
||||
};
|
||||
|
||||
/* Base element RAM RAS error interrupt handler */
|
||||
int sgi_ras_sram_intr_handler(const struct err_record_info *err_rec,
|
||||
int probe_data,
|
||||
const struct err_handler_data *const data)
|
||||
{
|
||||
struct sgi_ras_ev_map *ras_map;
|
||||
mm_communicate_header_t *header;
|
||||
sgi_sram_err_info_t sram_info;
|
||||
uintptr_t base_addr;
|
||||
uint32_t clear_status, intr;
|
||||
int ret;
|
||||
|
||||
cm_el1_sysregs_context_save(NON_SECURE);
|
||||
intr = data->interrupt;
|
||||
|
||||
INFO("SGI: Base element RAM interrupt [%d] handler\n", intr);
|
||||
|
||||
/* Determine error record base address to read. */
|
||||
base_addr = 0;
|
||||
if (intr == NS_RAM_ECC_CE_INT || intr == NS_RAM_ECC_UE_INT) {
|
||||
base_addr = SOC_NS_RAM_ERR_REC_BASE;
|
||||
}
|
||||
sram_info.err_status = mmio_read_32(base_addr + ERRSTATUS);
|
||||
sram_info.err_code = mmio_read_32(base_addr + ERRCODE);
|
||||
sram_info.err_addr = mmio_read_32(base_addr + ERRADDR);
|
||||
|
||||
/* Clear the interrupt. */
|
||||
clear_status = mmio_read_32(base_addr + ERRSTATUS);
|
||||
mmio_write_32((base_addr + ERRSTATUS), clear_status);
|
||||
|
||||
/*
|
||||
* Prepare the MM Communication buffer to pass the base element RAM
|
||||
* error information to Secure Partition.
|
||||
*/
|
||||
header = (void *)PLAT_SPM_BUF_BASE;
|
||||
memset(header, 0, sizeof(*header));
|
||||
memcpy(&header->data, &sram_info, sizeof(sram_info));
|
||||
header->message_len = sizeof(sram_info);
|
||||
memcpy(&header->header_guid, (void *)&sram_ecc_event_guid,
|
||||
sizeof(struct efi_guid));
|
||||
|
||||
spm_mm_sp_call(MM_COMMUNICATE_AARCH64, (uint64_t)header, 0,
|
||||
plat_my_core_pos());
|
||||
|
||||
plat_ic_end_of_interrupt(intr);
|
||||
|
||||
/*
|
||||
* Find if this is a RAS interrupt. There must be an event against
|
||||
* this interrupt
|
||||
*/
|
||||
ras_map = sgi_find_ras_event_map_by_intr(intr);
|
||||
if (ras_map == NULL) {
|
||||
ERROR("SGI: RAS error info for interrupt id: %d not found\n",
|
||||
intr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Dispatch the event to the SDEI client */
|
||||
ret = sdei_dispatch_event(ras_map->sdei_ev_num);
|
||||
if (ret != 0) {
|
||||
/*
|
||||
* sdei_dispatch_event() may return failing result in some
|
||||
* cases, for example kernel may not have registered a handler
|
||||
* or RAS event may happen early during boot. We restore the NS
|
||||
* context when sdei_dispatch_event() returns failing result.
|
||||
*/
|
||||
ERROR("SDEI dispatch failed: %d", ret);
|
||||
cm_el1_sysregs_context_restore(NON_SECURE);
|
||||
cm_set_next_eret_context(NON_SECURE);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -54,10 +54,6 @@ BL31_SOURCES += ${INTERCONNECT_SOURCES} \
|
|||
${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.")
|
||||
|
|
|
@ -106,10 +106,6 @@ void sgi_bl31_common_platform_setup(void)
|
|||
{
|
||||
arm_bl31_platform_setup();
|
||||
|
||||
#if RAS_FFH_SUPPORT
|
||||
sgi_ras_intr_handler_setup();
|
||||
#endif
|
||||
|
||||
/* Configure the warm reboot SGI for primary core */
|
||||
css_setup_cpu_pwr_down_intr();
|
||||
|
||||
|
|
|
@ -87,6 +87,9 @@ const mmap_region_t plat_arm_secure_partition_mmap[] = {
|
|||
SOC_PLATFORM_PERIPH_MAP_DEVICE_USER,
|
||||
ARM_SP_IMAGE_MMAP,
|
||||
ARM_SP_IMAGE_NS_BUF_MMAP,
|
||||
#if RAS_FFH_SUPPORT
|
||||
CSS_SGI_SP_CPER_BUF_MMAP,
|
||||
#endif
|
||||
ARM_SP_IMAGE_RW_MMAP,
|
||||
ARM_SPM_BUF_EL0_MMAP,
|
||||
{0}
|
||||
|
|
|
@ -1,194 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2021, 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/el3_runtime/context_mgmt.h>
|
||||
#include <lib/extensions/ras.h>
|
||||
#include <plat/arm/common/arm_spm_def.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <services/sdei.h>
|
||||
#include <services/spm_mm_svc.h>
|
||||
|
||||
#include <sgi_ras.h>
|
||||
|
||||
static int sgi_ras_intr_handler(const struct err_record_info *err_rec,
|
||||
int probe_data,
|
||||
const struct err_handler_data *const data);
|
||||
typedef struct mm_communicate_header {
|
||||
struct efi_guid header_guid;
|
||||
size_t message_len;
|
||||
uint8_t data[8];
|
||||
} mm_communicate_header_t;
|
||||
|
||||
/*
|
||||
* GUID to indicate that the MM communication message is intended for DMC-620
|
||||
* MM driver.
|
||||
*/
|
||||
const struct efi_guid dmc620_ecc_event_guid = {
|
||||
0x5ef0afd5, 0xe01a, 0x4c30,
|
||||
{0x86, 0x19, 0x45, 0x46, 0x26, 0x91, 0x80, 0x98}
|
||||
};
|
||||
|
||||
struct sgi_ras_ev_map sgi575_ras_map[] = {
|
||||
|
||||
/* DMC 0 error ECC error interrupt*/
|
||||
{SGI_SDEI_DS_EVENT_0, 35},
|
||||
|
||||
/* DMC 1 error ECC error interrupt*/
|
||||
{SGI_SDEI_DS_EVENT_1, 39},
|
||||
};
|
||||
|
||||
#define SGI575_RAS_MAP_SIZE ARRAY_SIZE(sgi575_ras_map)
|
||||
|
||||
struct err_record_info sgi_err_records[] = {
|
||||
{
|
||||
/* DMC 0 error record info */
|
||||
.handler = &sgi_ras_intr_handler,
|
||||
.aux_data = (void *)0,
|
||||
}, {
|
||||
/* DMC 1 error record info */
|
||||
.handler = &sgi_ras_intr_handler,
|
||||
.aux_data = (void *)1,
|
||||
},
|
||||
};
|
||||
|
||||
struct ras_interrupt sgi_ras_interrupts[] = {
|
||||
{
|
||||
.intr_number = 35,
|
||||
.err_record = &sgi_err_records[0],
|
||||
}, {
|
||||
.intr_number = 39,
|
||||
.err_record = &sgi_err_records[1],
|
||||
}
|
||||
};
|
||||
|
||||
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 sgi575_ras_map;
|
||||
}
|
||||
|
||||
static int plat_sgi_get_ras_ev_map_size(void)
|
||||
{
|
||||
return SGI575_RAS_MAP_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find event mapping for a given interrupt number: On success, returns pointer
|
||||
* to the event mapping. On error, returns NULL.
|
||||
*/
|
||||
static struct sgi_ras_ev_map *find_ras_event_map_by_intr(uint32_t intr_num)
|
||||
{
|
||||
struct sgi_ras_ev_map *map = plat_sgi_get_ras_ev_map();
|
||||
int i;
|
||||
int size = plat_sgi_get_ras_ev_map_size();
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (map->intr == intr_num)
|
||||
return map;
|
||||
|
||||
map++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static int sgi_ras_intr_handler(const struct err_record_info *err_rec,
|
||||
int probe_data,
|
||||
const struct err_handler_data *const data)
|
||||
{
|
||||
struct sgi_ras_ev_map *ras_map;
|
||||
mm_communicate_header_t *header;
|
||||
uint32_t intr;
|
||||
int ret;
|
||||
|
||||
cm_el1_sysregs_context_save(NON_SECURE);
|
||||
intr = data->interrupt;
|
||||
|
||||
/*
|
||||
* Find if this is a RAS interrupt. There must be an event against
|
||||
* this interrupt
|
||||
*/
|
||||
ras_map = find_ras_event_map_by_intr(intr);
|
||||
assert(ras_map != NULL);
|
||||
|
||||
/*
|
||||
* Populate the MM_COMMUNICATE payload to share the
|
||||
* event info with StandaloneMM code. This allows us to use
|
||||
* MM_COMMUNICATE as a common entry mechanism into S-EL0. The
|
||||
* header data will be parsed in StandaloneMM to process the
|
||||
* corresponding event.
|
||||
*
|
||||
* TBD - Currently, the buffer allocated by SPM for communication
|
||||
* between EL3 and S-EL0 is being used(PLAT_SPM_BUF_BASE). But this
|
||||
* should happen via a dynamic mem allocation, which should be
|
||||
* managed by SPM -- the individual platforms then call the mem
|
||||
* alloc api to get memory for the payload.
|
||||
*/
|
||||
header = (void *) PLAT_SPM_BUF_BASE;
|
||||
memset(header, 0, sizeof(*header));
|
||||
memcpy(&header->data, &err_rec->aux_data, sizeof(err_rec->aux_data));
|
||||
header->message_len = sizeof(err_rec->aux_data);
|
||||
memcpy(&header->header_guid, (void *) &dmc620_ecc_event_guid,
|
||||
sizeof(const struct efi_guid));
|
||||
|
||||
spm_mm_sp_call(MM_COMMUNICATE_AARCH64, (uint64_t)header, 0,
|
||||
plat_my_core_pos());
|
||||
|
||||
/*
|
||||
* Do an EOI of the RAS interrupt. This allows the
|
||||
* sdei event to be dispatched at the SDEI event's
|
||||
* priority.
|
||||
*/
|
||||
plat_ic_end_of_interrupt(intr);
|
||||
|
||||
/* Dispatch the event to the SDEI client */
|
||||
ret = sdei_dispatch_event(ras_map->sdei_ev_num);
|
||||
if (ret != 0) {
|
||||
/*
|
||||
* sdei_dispatch_event() may return failing result in some cases,
|
||||
* for example kernel may not have registered a handler or RAS event
|
||||
* may happen early during boot. We restore the NS context when
|
||||
* sdei_dispatch_event() returns failing result.
|
||||
*/
|
||||
ERROR("SDEI dispatch failed: %d", ret);
|
||||
cm_el1_sysregs_context_restore(NON_SECURE);
|
||||
cm_set_next_eret_context(NON_SECURE);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
|
@ -24,9 +24,17 @@ ehf_pri_desc_t plat_exceptions[] = {
|
|||
/* Normal priority SDEI */
|
||||
EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SDEI_NORMAL_PRI),
|
||||
#endif
|
||||
|
||||
#if SPM_MM
|
||||
#if RAS_FFH_SUPPORT
|
||||
#if (PLAT_SP_PRI != PLAT_RAS_PRI)
|
||||
EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SP_PRI),
|
||||
#endif
|
||||
#else
|
||||
EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SP_PRI),
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Platform specific exceptions description */
|
||||
#ifdef PLAT_EHF_DESC
|
||||
PLAT_EHF_DESC,
|
||||
|
|
Loading…
Add table
Reference in a new issue