bsps/aarch64/zynqmp: Add memory error reporting

This adds error reporting for ZynqMP including L1 and L2 cache, on-chip
memory (OCM) error correcting code (ECC), and DDR ECC. OCM ECC supports
fault injection from within RTEMS. DDR ECC technically supports fault
injection as well, but requires that the program injecting faults
operate exclusively outside of DDR. The AArch64 port is not currently
capable of operating exclusively in OCM due to size constraints and
would need to be booted via JTAG or via a non-relocating u-boot to
accomplish this.
This commit is contained in:
Kinsey Moore
2024-06-21 05:57:21 +00:00
committed by Chris Johns
parent 27ec46f11b
commit b48166b9b6
19 changed files with 1909 additions and 5 deletions
+129
View File
@@ -0,0 +1,129 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/**
* @file
*
* @ingroup RTEMSBSPsAArch64XilinxZynqMP
*
* @brief This source file contains the implementation of zynqmp_ecc_init().
*/
/*
* Copyright (C) 2023 On-Line Applications Research Corporation (OAR)
* Written by Kinsey Moore <kinsey.moore@oarcorp.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <bsp.h>
#include <bsp/ecc_priv.h>
#include <bsp/irq.h>
#include <bsp/utility.h>
#include <rtems/score/aarch64-system-registers.h>
static Cache_Error_RAM_ID get_l1_ramid(uint64_t ramid)
{
switch (ramid) {
case 0x0:
return RAM_ID_L1I_TAG;
case 0x1:
return RAM_ID_L1I_DATA;
case 0x8:
return RAM_ID_L1D_TAG;
case 0x9:
return RAM_ID_L1D_DATA;
case 0xa:
return RAM_ID_L1D_DIRTY;
case 0x18:
return RAM_ID_TLB;
default:
return RAM_ID_UNKNOWN;
}
}
static Cache_Error_RAM_ID get_l2_ramid(uint64_t ramid)
{
switch (ramid) {
case 0x10:
return RAM_ID_L2_TAG;
case 0x11:
return RAM_ID_L2_DATA;
case 0x12:
return RAM_ID_SCU;
default:
return RAM_ID_UNKNOWN;
}
}
static void cache_handler(void *arg)
{
uint64_t l1val = _AArch64_Read_cpumerrsr_el1();
_AArch64_Write_cpumerrsr_el1(l1val);
uint64_t l2val = _AArch64_Read_l2merrsr_el1();
_AArch64_Write_l2merrsr_el1(l2val);
(void) arg;
if (l1val & AARCH64_CPUMERRSR_EL1_VALID) {
/* parse L1 data */
Cache_Error_Event cerr = {0, };
cerr.abort = l1val & AARCH64_CPUMERRSR_EL1_FATAL;
cerr.repeats = AARCH64_CPUMERRSR_EL1_REPEATERR_GET(l1val);
cerr.other_errors = AARCH64_CPUMERRSR_EL1_OTHERERR_GET(l1val);
cerr.ramid = get_l1_ramid(AARCH64_CPUMERRSR_EL1_RAMID_GET(l1val));
cerr.segment = AARCH64_CPUMERRSR_EL1_CPUIDWAY_GET(l1val);
cerr.address = AARCH64_CPUMERRSR_EL1_ADDR_GET(l1val);
zynqmp_invoke_ecc_handler(L1_CACHE, &cerr);
}
if (l2val & AARCH64_L2MERRSR_EL1_VALID) {
/* parse L2 data */
Cache_Error_Event cerr = {0, };
cerr.abort = l2val & AARCH64_L2MERRSR_EL1_FATAL;
cerr.repeats = AARCH64_L2MERRSR_EL1_REPEATERR_GET(l2val);
cerr.other_errors = AARCH64_L2MERRSR_EL1_OTHERERR_GET(l2val);
cerr.ramid = get_l2_ramid(AARCH64_L2MERRSR_EL1_RAMID_GET(l2val));
cerr.segment = AARCH64_L2MERRSR_EL1_CPUIDWAY_GET(l2val);
cerr.address = AARCH64_L2MERRSR_EL1_ADDR_GET(l2val);
zynqmp_invoke_ecc_handler(L2_CACHE, &cerr);
}
}
static rtems_interrupt_entry zynqmp_cache_ecc_entry;
rtems_status_code zynqmp_configure_cache_ecc( void )
{
rtems_interrupt_entry_initialize(
&zynqmp_cache_ecc_entry,
cache_handler,
NULL,
"L1/L2 Cache Errors"
);
return rtems_interrupt_entry_install(
ZYNQMP_IRQ_CACHE,
RTEMS_INTERRUPT_SHARED,
&zynqmp_cache_ecc_entry
);
}
File diff suppressed because it is too large Load Diff
+300
View File
@@ -0,0 +1,300 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/**
* @file
*
* @ingroup RTEMSBSPsAArch64XilinxZynqMP
*
* @brief This source file contains the implementation of OCM ECC support.
*/
/*
* Copyright (C) 2023 On-Line Applications Research Corporation (OAR)
* Written by Kinsey Moore <kinsey.moore@oarcorp.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <bsp.h>
#include <bsp/ecc_priv.h>
#include <bsp/irq.h>
#include <bsp/utility.h>
#include <libcpu/mmu-vmsav8-64.h>
static uintptr_t ocm_base = 0xFF960000;
/* ECC Control */
#define OCM_ECC_CTRL 0x14
/* 0 -> single error, 1 -> continuous errors */
#define OCM_ECC_CTRL_FI_MODE BSP_BIT32(2)
/* When bit is set, detection occurs without correction */
#define OCM_ECC_CTRL_DET_ONLY BSP_BIT32(1)
/* Enable ECC, should only be modified at system boot */
#define OCM_ECC_CTRL_ECC_ON_OFF BSP_BIT32(0)
/* Interrupt Enable */
#define OCM_IE 0xc
#define OCM_IE_UE_RMW BSP_BIT32(10)
#define OCM_IE_UE BSP_BIT32(7)
#define OCM_IE_CE BSP_BIT32(6)
/* Error Response Control */
#define OCM_ERR_CTRL 0x0
#define OCM_ERR_CTRL_UE_RES BSP_BIT32(3)
/*
* Fault Injection Data, four registers comprising 16 bytes of a data word
*
* Bits set to 1 toggle the corresponding bits of the next written word during a
* fault injection.
*/
#define OCM_FI_D0 0x4c
#define OCM_FI_D1 0x50
#define OCM_FI_D2 0x54
#define OCM_FI_D3 0x58
/* Fault Injection Syndrome */
#define OCM_FI_SY 0x5c
#define OCM_FI_SY_DATA(val) BSP_FLD32(val, 0, 15)
#define OCM_FI_SY_DATA_GET(reg) BSP_FLD32GET(reg, 0, 15)
#define OCM_FI_SY_DATA_SET(reg, val) BSP_FLD32SET(reg, val, 0, 15)
/* Fault Injection Counter */
#define OCM_FI_CNTR 0x74
#define OCM_FI_CNTR_COUNT(val) BSP_FLD32(val, 0, 23)
#define OCM_FI_CNTR_COUNT_GET(reg) BSP_FLD32GET(reg, 0, 23)
#define OCM_FI_CNTR_COUNT_SET(reg, val) BSP_FLD32SET(reg, val, 0, 23)
/* Interrupt Status */
#define OCM_IS 0x4
#define OCM_IS_UE_RMW BSP_BIT32(10)
#define OCM_IS_UE BSP_BIT32(7)
#define OCM_IS_CE BSP_BIT32(6)
/* Interrupt Mask */
#define OCM_IM 0x8
#define OCM_IM_UE_RMW BSP_BIT32(10)
#define OCM_IM_UE BSP_BIT32(7)
#define OCM_IM_CE BSP_BIT32(6)
void zynqmp_ocm_inject_fault( void )
{
volatile uint32_t *fi_d0 = (uint32_t*)(ocm_base + OCM_FI_D0);
volatile uint32_t *fi_cnt = (uint32_t*)(ocm_base + OCM_FI_CNTR);
volatile uint64_t *ocm_top = (uint64_t*)0xFFFFFFF0U;
volatile uint32_t *ecc_ctrl = (uint32_t*)(ocm_base + OCM_ECC_CTRL);
uint64_t ocm_tmp = *ocm_top;
/* Configure OCM to throw constant errors */
*ecc_ctrl |= OCM_ECC_CTRL_FI_MODE;
/* Inject a single bit error */
*fi_d0 = 1;
/* Configure the clock count after which errors will begin */
*fi_cnt = 0;
/* Insert a memory barrier to ensure that fault injection is active */
_AARCH64_Data_synchronization_barrier();
/* trigger fault with a write of data that was already at the given address */
*ocm_top = 0;
/* Insert a memory barrier to prevent optimization */
_AARCH64_Data_synchronization_barrier();
/* Perform read to force reporting of the error */
*ocm_top;
/* Disable constant fault mode */
*ecc_ctrl &= ~(OCM_ECC_CTRL_FI_MODE);
/* Insert a memory barrier to ensure the mode has changed */
_AARCH64_Data_synchronization_barrier();
/* Reset to original value now that constant errors are disabled */
*ocm_top = ocm_tmp;
}
/* Correctable Error First Failing Address */
#define OCM_CE_FFA 0x1c
#define OCM_CE_FFA_ADDR(val) BSP_FLD32(val, 0, 17)
#define OCM_CE_FFA_ADDR_GET(reg) BSP_FLD32GET(reg, 0, 17)
#define OCM_CE_FFA_ADDR_SET(reg, val) BSP_FLD32SET(reg, val, 0, 17)
/* Correctable Error First Failing Data, four registers comprising 16 bytes */
#define OCM_CE_FFD0 0x20
#define OCM_CE_FFD1 0x24
#define OCM_CE_FFD2 0x28
#define OCM_CE_FFD3 0x2c
/* Correctable Error First Failing ECC */
#define OCM_CE_FFE 0x1c
#define OCM_CE_FFE_SYNDROME(val) BSP_FLD32(val, 0, 15)
#define OCM_CE_FFE_SYNDROME_GET(reg) BSP_FLD32GET(reg, 0, 15)
#define OCM_CE_FFE_SYNDROME_SET(reg, val) BSP_FLD32SET(reg, val, 0, 15)
/* Uncorrectable Error First Failing Address */
#define OCM_UE_FFA 0x34
#define OCM_UE_FFA_ADDR(val) BSP_FLD32(val, 0, 17)
#define OCM_UE_FFA_ADDR_GET(reg) BSP_FLD32GET(reg, 0, 17)
#define OCM_UE_FFA_ADDR_SET(reg, val) BSP_FLD32SET(reg, val, 0, 17)
/* Uncorrectable Error First Failing Data, four registers comprising 16 bytes */
#define OCM_UE_FFD0 0x38
#define OCM_UE_FFD1 0x3c
#define OCM_UE_FFD2 0x40
#define OCM_UE_FFD3 0x44
/* Uncorrectable Error First Failing ECC */
#define OCM_UE_FFE 0x48
#define OCM_UE_FFE_SYNDROME(val) BSP_FLD32(val, 0, 15)
#define OCM_UE_FFE_SYNDROME_GET(reg) BSP_FLD32GET(reg, 0, 15)
#define OCM_UE_FFE_SYNDROME_SET(reg, val) BSP_FLD32SET(reg, val, 0, 15)
/* Read/Modify/Write Uncorrectable Error First Failing Address */
#define OCM_RMW_UE_FFA 0x70
#define OCM_RMW_UE_FFA_ADDR(val) BSP_FLD32(val, 0, 17)
#define OCM_RMW_UE_FFA_ADDR_GET(reg) BSP_FLD32GET(reg, 0, 17)
#define OCM_RMW_UE_FFA_ADDR_SET(reg, val) BSP_FLD32SET(reg, val, 0, 17)
static void ocm_handle_rmw( void )
{
volatile uint32_t *rmw_ffa = (uint32_t*)(ocm_base + OCM_RMW_UE_FFA);
OCM_Error_Info info;
info.type = OCM_UNCORRECTABLE_RMW;
info.offset = OCM_RMW_UE_FFA_ADDR_GET(*rmw_ffa);
zynqmp_invoke_ecc_handler(OCM_RAM, &info);
}
static void ocm_handle_ce( void )
{
volatile uint32_t *ce_ffa = (uint32_t*)(ocm_base + OCM_CE_FFA);
volatile uint32_t *ce_ffe = (uint32_t*)(ocm_base + OCM_CE_FFA);
volatile uint32_t *ce_ffd0 = (uint32_t*)(ocm_base + OCM_CE_FFD0);
volatile uint32_t *ce_ffd1 = (uint32_t*)(ocm_base + OCM_CE_FFD1);
volatile uint32_t *ce_ffd2 = (uint32_t*)(ocm_base + OCM_CE_FFD2);
volatile uint32_t *ce_ffd3 = (uint32_t*)(ocm_base + OCM_CE_FFD3);
OCM_Error_Info info;
info.type = OCM_CORRECTABLE;
info.offset = OCM_CE_FFA_ADDR_GET(*ce_ffa);
info.data0 = *ce_ffd0;
info.data1 = *ce_ffd1;
info.data2 = *ce_ffd2;
info.data3 = *ce_ffd3;
info.syndrome = OCM_CE_FFE_SYNDROME_GET(*ce_ffe);
zynqmp_invoke_ecc_handler(OCM_RAM, &info);
}
static void ocm_handle_ue( void )
{
volatile uint32_t *ue_ffa = (uint32_t*)(ocm_base + OCM_UE_FFA);
volatile uint32_t *ue_ffe = (uint32_t*)(ocm_base + OCM_UE_FFA);
volatile uint32_t *ue_ffd0 = (uint32_t*)(ocm_base + OCM_UE_FFD0);
volatile uint32_t *ue_ffd1 = (uint32_t*)(ocm_base + OCM_UE_FFD1);
volatile uint32_t *ue_ffd2 = (uint32_t*)(ocm_base + OCM_UE_FFD2);
volatile uint32_t *ue_ffd3 = (uint32_t*)(ocm_base + OCM_UE_FFD3);
OCM_Error_Info info;
info.type = OCM_UNCORRECTABLE;
info.offset = OCM_UE_FFA_ADDR_GET(*ue_ffa);
info.data0 = *ue_ffd0;
info.data1 = *ue_ffd1;
info.data2 = *ue_ffd2;
info.data3 = *ue_ffd3;
info.syndrome = OCM_UE_FFE_SYNDROME_GET(*ue_ffe);
zynqmp_invoke_ecc_handler(OCM_RAM, &info);
}
static void ocm_handler(void *arg)
{
volatile uint32_t *ocm_is = (uint32_t*)(ocm_base + OCM_IS);
uint32_t ocm_is_value = *ocm_is;
(void) arg;
/* Check and clear each error type after handling */
if ((ocm_is_value & OCM_IS_UE_RMW) != 0) {
ocm_handle_rmw();
*ocm_is = OCM_IS_UE_RMW;
}
if ((ocm_is_value & OCM_IS_CE) != 0) {
ocm_handle_ce();
*ocm_is = OCM_IS_CE;
}
if ((ocm_is_value & OCM_IS_UE) != 0) {
ocm_handle_ue();
*ocm_is = OCM_IS_UE;
}
}
static rtems_interrupt_entry zynqmp_ocm_ecc_entry;
rtems_status_code zynqmp_configure_ocm_ecc( void )
{
volatile uint32_t *err_ctrl = (uint32_t*)(ocm_base + OCM_ERR_CTRL);
volatile uint32_t *ecc_ctrl = (uint32_t*)(ocm_base + OCM_ECC_CTRL);
volatile uint32_t *int_enable = (uint32_t*)(ocm_base + OCM_IE);
rtems_status_code sc;
rtems_interrupt_entry_initialize(
&zynqmp_ocm_ecc_entry,
ocm_handler,
NULL,
"OCM RAM ECC"
);
sc = rtems_interrupt_entry_install(
ZYNQMP_IRQ_OCM,
RTEMS_INTERRUPT_SHARED,
&zynqmp_ocm_ecc_entry
);
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
if ((*ecc_ctrl & OCM_ECC_CTRL_ECC_ON_OFF) == 0) {
/*
* ECC is not enabled and should already have been by BOOT.bin. Enabling it
* now could corrupt existing data in the OCM.
*/
return RTEMS_NOT_CONFIGURED;
}
/*
* OCM_ERR_CTRL.UE_RES forces generation of a synchronous external abort
* instead of using interrupts to signal the fault
*/
*err_ctrl &= ~(OCM_ERR_CTRL_UE_RES);
/* Ensure ECC_CTRL is in the right state */
*ecc_ctrl &= ~(OCM_ECC_CTRL_DET_ONLY);
/* enable correctable and uncorrectable error interrupts */
*int_enable = OCM_IE_CE | OCM_IE_UE | OCM_IE_UE_RMW;
return RTEMS_SUCCESSFUL;
}
@@ -0,0 +1,209 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/**
* @file
*
* @ingroup RTEMSBSPsAArch64XilinxZynqMP
*
* @brief This header file provides internal APIs for managing ECC events.
*/
/*
* Copyright (C) 2024 On-Line Applications Research Corporation (OAR)
* Written by Kinsey Moore <kinsey.moore@oarcorp.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LIBBSP_AARCH64_XILINX_ZYNQMP_BSP_ECC_H
#define LIBBSP_AARCH64_XILINX_ZYNQMP_BSP_ECC_H
/**
* @addtogroup RTEMSBSPsAArch64
*
* @{
*/
//#include <bspopts.h>
#ifndef ASM
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* @brief Enumeration describing the possible types of ECC events
*/
typedef enum {
/* L1 Cache event information is delivered via Cache_Error_Event struct. */
L1_CACHE,
/* L2 Cache event information is delivered via Cache_Error_Event struct. */
L2_CACHE,
/*
* L1 and L2 cache are on a combined interrupt on ZynqMP. They are enabled as
* a single unit. The above individual L1 and L2 cache definitions will be
* used for reporting. Attempting to enable L1 or L2 individually will enable
* both.
*/
L1_L2_CACHE,
OCM_RAM,
DDR_RAM,
} ECC_Event_Type;
/**
* @brief The specific locations where a cache error can originate
*/
typedef enum {
RAM_ID_L1I_TAG,
RAM_ID_L1I_DATA,
RAM_ID_L1D_TAG,
RAM_ID_L1D_DATA,
RAM_ID_L1D_DIRTY,
RAM_ID_TLB,
RAM_ID_L2_TAG,
RAM_ID_L2_DATA,
RAM_ID_SCU,
RAM_ID_UNKNOWN
} Cache_Error_RAM_ID;
/**
* @brief Structure containing information about a Cache error
*/
typedef struct {
/* Indicates the RAM index address */
uint64_t address;
/* Indicates the type of RAM where the error originated */
Cache_Error_RAM_ID ramid;
/*
* Indicates the segment (way or bank) of the RAM where the error originated.
* Does not apply to L1D_DIRTY RAM ID. For SCU errors, this also indicates the
* associated CPU.
*/
uint8_t segment;
/* The number of times this specific error has occurred since last reset */
uint8_t repeats;
/* The number of times other errors have occurred since last reset */
uint8_t other_errors;
/* Whether any of the errors represented have caused a data abort */
bool abort;
} Cache_Error_Event;
/**
* @brief Typedef for ECC handlers
*
* Functions matching this prototype can be registered as the handler for ECC
* event callbacks. The data argument is a struct describing the event that
* occurred.
*/
typedef void (*zynqmp_ecc_handler)( ECC_Event_Type event, void *data );
/**
* @brief Enumeration describing the possible types of ECC events
*
* Note that the provided handler may be called from interrupt context.
*
* @param handler The handler to be called for all ECC error events
*/
void zynqmp_ecc_register_handler( zynqmp_ecc_handler handler );
/**
* @brief Enable ECC error reporting
*
* Enables ECC error reporting for the specified subsystem.
*
* @param event The ECC error event type to enable
*/
int zynqmp_ecc_enable( ECC_Event_Type event );
/**
* @brief Injects an ECC fault in the On-Chip Memory (OCM)
*/
void zynqmp_ocm_inject_fault( void );
/**
* @brief The types of OCM ECC errors
*/
typedef enum {
OCM_UNCORRECTABLE,
OCM_UNCORRECTABLE_RMW,
OCM_CORRECTABLE
} OCM_Error_Type;
/**
* @brief Structure containing information about a OCM ECC error
*/
typedef struct {
/* Describes the type of error being reported */
OCM_Error_Type type;
/* The offset into OCM where the error occurred */
uint32_t offset;
/* The data relevant to the error. Does not apply to RMW errors */
uint32_t data0;
uint32_t data1;
uint32_t data2;
uint32_t data3;
/* The ECC syndrome relevant to the error. Does not apply to RMW errors */
uint16_t syndrome;
} OCM_Error_Info;
/**
* @brief The types of DDR ECC errors
*/
typedef enum {
DDR_UNCORRECTABLE,
DDR_CORRECTABLE
} DDR_Error_Type;
/**
* @brief Structure containing information about a DDR ECC error
*/
typedef struct {
/* Describes the type of error being reported */
DDR_Error_Type type;
/* The DDR Rank where the error occurred */
uint32_t rank;
/* The DDR Bank Group where the error occurred */
uint32_t bank_group;
/* The DDR Bank where the error occurred */
uint32_t bank;
/* The DDR Row where the error occurred */
uint32_t row;
/* The DDR Column where the error occurred */
uint32_t column;
/*
* When mapping from SDRAM addressing back to AXI addressing, this is will
* only be a close approximation of the source address since bits can be
* discarded when converting from AXI to SDRAM.
*/
uint64_t address;
} DDR_Error_Info;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* ASM */
/** @} */
#endif /* LIBBSP_AARCH64_XILINX_ZYNQMP_BSP_ECC_H */
@@ -0,0 +1,104 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/**
* @file
*
* @ingroup RTEMSBSPsAArch64XilinxZynqMP
*
* @brief This header file provides internal APIs for managing ECC events.
*/
/*
* Copyright (C) 2024 On-Line Applications Research Corporation (OAR)
* Written by Kinsey Moore <kinsey.moore@oarcorp.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LIBBSP_AARCH64_XILINX_ZYNQMP_BSP_ECC_PRIV_H
#define LIBBSP_AARCH64_XILINX_ZYNQMP_BSP_ECC_PRIV_H
/**
* @addtogroup RTEMSBSPsAArch64
*
* @{
*/
#include <bspopts.h>
#ifndef ASM
#include <rtems.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <bsp/ecc.h>
/**
* @brief Initialize ECC reporting support
*
* This initializes the base ECC event reporting support for the platform.
*/
void zynqmp_ecc_init( void );
/**
* @brief Initialize BSP-specific ECC reporting
*
* Various BSPs may have different ECC capabilities. This allows those BSPs to
* initialize those facilities as necessary.
*/
void zynqmp_ecc_init_bsp( void );
/**
* @brief Configure Cache ECC reporting
*/
rtems_status_code zynqmp_configure_cache_ecc( void );
/**
* @brief Configure On-Chip Memory (OCM) ECC reporting
*/
rtems_status_code zynqmp_configure_ocm_ecc( void );
/**
* @brief Configure DDR Memory ECC reporting
*/
rtems_status_code zynqmp_configure_ddr_ecc( void );
/**
* @brief Invoke the ECC error handler
*
* @param event The ECC error event type to be raised
* @param data The details associated with the raised ECC error
*/
void zynqmp_invoke_ecc_handler( ECC_Event_Type event, void *data );
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* ASM */
/** @} */
#endif /* LIBBSP_AARCH64_XILINX_ZYNQMP_BSP_ECC_PRIV_H */
@@ -52,6 +52,7 @@ extern "C" {
/* Interrupts vectors */
#define BSP_TIMER_VIRT_PPI 27
#define BSP_TIMER_PHYS_NS_PPI 30
#define ZYNQMP_IRQ_OCM 42
#define ZYNQMP_IRQ_QSPI 47
#define ZYNQMP_IRQ_I2C_0 49
#define ZYNQMP_IRQ_I2C_1 50
@@ -61,6 +62,8 @@ extern "C" {
#define ZYNQMP_IRQ_ETHERNET_1 91
#define ZYNQMP_IRQ_ETHERNET_2 93
#define ZYNQMP_IRQ_ETHERNET_3 95
#define ZYNQMP_IRQ_DDR 144
#define ZYNQMP_IRQ_CACHE 183
/** @} */
@@ -36,6 +36,7 @@
#include <bsp.h>
#include <bsp/bootcard.h>
#include <bsp/ecc_priv.h>
#include <bsp/irq-generic.h>
#include <bsp/linker-symbols.h>
@@ -56,4 +57,5 @@ void bsp_start( void )
bsp_section_nocacheheap_begin,
(uintptr_t) bsp_section_nocacheheap_size
);
zynqmp_ecc_init();
}
@@ -0,0 +1,44 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/**
* @file
*
* @ingroup RTEMSBSPsAArch64XilinxZynqMP
*
* @brief This source file contains the implementation of zynqmp_ecc_init_bsp().
*/
/*
* Copyright (C) 2023 On-Line Applications Research Corporation (OAR)
* Written by Kinsey Moore <kinsey.moore@oarcorp.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <bsp.h>
#include <bsp/ecc_priv.h>
void zynqmp_ecc_init_bsp( void )
{
zynqmp_ecc_enable( DDR_RAM );
}
@@ -0,0 +1,92 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/**
* @file
*
* @ingroup RTEMSBSPsAArch64XilinxZynqMP
*
* @brief This source file contains the implementation of zynqmp_ecc_init().
*/
/*
* Copyright (C) 2023 On-Line Applications Research Corporation (OAR)
* Written by Kinsey Moore <kinsey.moore@oarcorp.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <bsp.h>
#include <bsp/ecc_priv.h>
#include <bsp/fatal.h>
#include <bsp/utility.h>
zynqmp_ecc_handler saved_handler = NULL;
void zynqmp_ecc_register_handler( zynqmp_ecc_handler handler )
{
saved_handler = handler;
}
void zynqmp_invoke_ecc_handler( ECC_Event_Type event, void *data )
{
if (saved_handler == NULL) {
bsp_fatal( BSP_FATAL_MEMORY_ECC_ERROR );
}
saved_handler(event, data);
}
int zynqmp_ecc_enable( ECC_Event_Type event )
{
rtems_status_code sc;
switch (event) {
case L1_CACHE:
case L2_CACHE:
case L1_L2_CACHE:
sc = zynqmp_configure_cache_ecc();
break;
case OCM_RAM:
sc = zynqmp_configure_ocm_ecc();
break;
case DDR_RAM:
sc = zynqmp_configure_ddr_ecc();
break;
default:
return 1;
}
if (sc != RTEMS_SUCCESSFUL) {
return 1;
}
return 0;
}
void zynqmp_ecc_init( void )
{
/* Do something on hardware */
zynqmp_ecc_enable( L1_L2_CACHE );
zynqmp_ecc_enable( OCM_RAM );
/* Call BSP-specific init function */
zynqmp_ecc_init_bsp();
}
@@ -0,0 +1,55 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/**
* @file
*
* @ingroup RTEMSBSPsAArch64XilinxZynqMP
*
* @brief This source file contains the implementation of zynqmp_ecc_init().
*/
/*
* Copyright (C) 2023 On-Line Applications Research Corporation (OAR)
* Written by Kinsey Moore <kinsey.moore@oarcorp.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <bsp.h>
#include <bsp/ecc_priv.h>
void zynqmp_ecc_register_handler( zynqmp_ecc_handler handler )
{
(void) handler;
/* Do nothing on QEMU */
}
int zynqmp_ecc_enable( ECC_Event_Type event )
{
(void) event;
/* Do nothing on QEMU */
return 0;
}
void zynqmp_ecc_init( void )
{
/* Do nothing on QEMU */
}
@@ -0,0 +1,43 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/**
* @file
*
* @ingroup RTEMSBSPsAArch64XilinxZynqMP
*
* @brief This source file contains the implementation of zynqmp_ecc_init_bsp().
*/
/*
* Copyright (C) 2023 On-Line Applications Research Corporation (OAR)
* Written by Kinsey Moore <kinsey.moore@oarcorp.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <bsp.h>
#include <bsp/ecc_priv.h>
void zynqmp_ecc_init_bsp( void )
{
/* Do nothing special for ZU3EG BSPs */
}
@@ -50,6 +50,11 @@ zynqmp_mmu_config_table[] = {
.begin = 0xfd000000U,
.end = 0xffc00000U,
.flags = AARCH64_MMU_DEVICE
/* Map OCM space */
}, {
.begin = 0xfffc0000U,
.end = 0x100000000U,
.flags = AARCH64_MMU_DATA_RW
}, {
.begin = 0x80000000U,
.end = 0x80100000U,
+1
View File
@@ -74,6 +74,7 @@ typedef enum {
BSP_FATAL_CONSOLE_REGISTER_DEV_2,
BSP_FATAL_MMU_ADDRESS_INVALID,
BSP_FATAL_HEAP_EXTEND_ERROR,
BSP_FATAL_MEMORY_ECC_ERROR,
/* ARM fatal codes */
BSP_ARM_A9MPCORE_FATAL_CLOCK_IRQ_INSTALL = BSP_FATAL_CODE_BLOCK(1),
@@ -17,5 +17,7 @@ links:
uid: linkcmds_lp64
- role: build-dependency
uid: objfdtcfc400x
source: []
source:
- bsps/aarch64/xilinx-zynqmp/start/bspstartecc_hw.c
- bsps/aarch64/xilinx-zynqmp/start/bspstartecc_cfc400x.c
type: build
@@ -19,5 +19,6 @@ links:
uid: linkcmds_ilp32
- role: build-dependency
uid: objfdtzynqmp
source: []
source:
- bsps/aarch64/xilinx-zynqmp/start/bspstartecc_qemu.c
type: build
@@ -19,5 +19,6 @@ links:
uid: linkcmds_lp64
- role: build-dependency
uid: objfdtzynqmp
source: []
source:
- bsps/aarch64/xilinx-zynqmp/start/bspstartecc_qemu.c
type: build
@@ -17,5 +17,7 @@ links:
uid: linkcmds_ilp32
- role: build-dependency
uid: objfdtzynqmp
source: []
source:
- bsps/aarch64/xilinx-zynqmp/start/bspstartecc_hw.c
- bsps/aarch64/xilinx-zynqmp/start/bspstartecc_zu3eg.c
type: build
@@ -17,5 +17,7 @@ links:
uid: linkcmds_lp64
- role: build-dependency
uid: objfdtzynqmp
source: []
source:
- bsps/aarch64/xilinx-zynqmp/start/bspstartecc_hw.c
- bsps/aarch64/xilinx-zynqmp/start/bspstartecc_zu3eg.c
type: build
@@ -20,6 +20,9 @@ source:
- bsps/aarch64/shared/cache/cache.c
- bsps/aarch64/shared/mmu/vmsav8-64.c
- bsps/aarch64/xilinx-zynqmp/console/console.c
- bsps/aarch64/xilinx-zynqmp/ecc/cache.c
- bsps/aarch64/xilinx-zynqmp/ecc/ddr.c
- bsps/aarch64/xilinx-zynqmp/ecc/ocm.c
- bsps/aarch64/xilinx-zynqmp/fdt/bsp_fdt.c
- bsps/aarch64/xilinx-zynqmp/start/bspstart.c
- bsps/aarch64/xilinx-zynqmp/start/bspstarthooks.c