1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. 4*91f16700Schasinglulu * 5*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu #ifndef RAS_H 9*91f16700Schasinglulu #define RAS_H 10*91f16700Schasinglulu 11*91f16700Schasinglulu #define ERR_HANDLER_VERSION 1U 12*91f16700Schasinglulu 13*91f16700Schasinglulu /* Error record access mechanism */ 14*91f16700Schasinglulu #define ERR_ACCESS_SYSREG 0 15*91f16700Schasinglulu #define ERR_ACCESS_MEMMAP 1 16*91f16700Schasinglulu 17*91f16700Schasinglulu /* 18*91f16700Schasinglulu * Register all error records on the platform. 19*91f16700Schasinglulu * 20*91f16700Schasinglulu * This macro must be used in the same file as the array of error record info 21*91f16700Schasinglulu * are declared. Only then would ARRAY_SIZE() yield a meaningful value. 22*91f16700Schasinglulu */ 23*91f16700Schasinglulu #define REGISTER_ERR_RECORD_INFO(_records) \ 24*91f16700Schasinglulu const struct err_record_mapping err_record_mappings = { \ 25*91f16700Schasinglulu .err_records = (_records), \ 26*91f16700Schasinglulu .num_err_records = ARRAY_SIZE(_records), \ 27*91f16700Schasinglulu } 28*91f16700Schasinglulu 29*91f16700Schasinglulu /* Error record info iterator */ 30*91f16700Schasinglulu #define for_each_err_record_info(_i, _info) \ 31*91f16700Schasinglulu for ((_i) = 0, (_info) = err_record_mappings.err_records; \ 32*91f16700Schasinglulu (_i) < err_record_mappings.num_err_records; \ 33*91f16700Schasinglulu (_i)++, (_info)++) 34*91f16700Schasinglulu 35*91f16700Schasinglulu #define ERR_RECORD_COMMON_(_probe, _handler, _aux) \ 36*91f16700Schasinglulu .probe = _probe, \ 37*91f16700Schasinglulu .handler = _handler, \ 38*91f16700Schasinglulu .aux_data = _aux, 39*91f16700Schasinglulu 40*91f16700Schasinglulu #define ERR_RECORD_SYSREG_V1(_idx_start, _num_idx, _probe, _handler, _aux) \ 41*91f16700Schasinglulu { \ 42*91f16700Schasinglulu .version = 1, \ 43*91f16700Schasinglulu .sysreg.idx_start = _idx_start, \ 44*91f16700Schasinglulu .sysreg.num_idx = _num_idx, \ 45*91f16700Schasinglulu .access = ERR_ACCESS_SYSREG, \ 46*91f16700Schasinglulu ERR_RECORD_COMMON_(_probe, _handler, _aux) \ 47*91f16700Schasinglulu } 48*91f16700Schasinglulu 49*91f16700Schasinglulu #define ERR_RECORD_MEMMAP_V1(_base_addr, _size_num_k, _probe, _handler, _aux) \ 50*91f16700Schasinglulu { \ 51*91f16700Schasinglulu .version = 1, \ 52*91f16700Schasinglulu .memmap.base_addr = _base_addr, \ 53*91f16700Schasinglulu .memmap.size_num_k = _size_num_k, \ 54*91f16700Schasinglulu .access = ERR_ACCESS_MEMMAP, \ 55*91f16700Schasinglulu ERR_RECORD_COMMON_(_probe, _handler, _aux) \ 56*91f16700Schasinglulu } 57*91f16700Schasinglulu 58*91f16700Schasinglulu /* 59*91f16700Schasinglulu * Macro to be used to name and declare an array of RAS interrupts along with 60*91f16700Schasinglulu * their handlers. 61*91f16700Schasinglulu * 62*91f16700Schasinglulu * This macro must be used in the same file as the array of interrupts are 63*91f16700Schasinglulu * declared. Only then would ARRAY_SIZE() yield a meaningful value. Also, the 64*91f16700Schasinglulu * array is expected to be sorted in the increasing order of interrupt number. 65*91f16700Schasinglulu */ 66*91f16700Schasinglulu #define REGISTER_RAS_INTERRUPTS(_array) \ 67*91f16700Schasinglulu const struct ras_interrupt_mapping ras_interrupt_mappings = { \ 68*91f16700Schasinglulu .intrs = (_array), \ 69*91f16700Schasinglulu .num_intrs = ARRAY_SIZE(_array), \ 70*91f16700Schasinglulu } 71*91f16700Schasinglulu 72*91f16700Schasinglulu #ifndef __ASSEMBLER__ 73*91f16700Schasinglulu 74*91f16700Schasinglulu #include <assert.h> 75*91f16700Schasinglulu 76*91f16700Schasinglulu #include <lib/extensions/ras_arch.h> 77*91f16700Schasinglulu 78*91f16700Schasinglulu struct err_record_info; 79*91f16700Schasinglulu 80*91f16700Schasinglulu struct ras_interrupt { 81*91f16700Schasinglulu /* Interrupt number, and the associated error record info */ 82*91f16700Schasinglulu unsigned int intr_number; 83*91f16700Schasinglulu struct err_record_info *err_record; 84*91f16700Schasinglulu void *cookie; 85*91f16700Schasinglulu }; 86*91f16700Schasinglulu 87*91f16700Schasinglulu /* Function to probe a error record group for error */ 88*91f16700Schasinglulu typedef int (*err_record_probe_t)(const struct err_record_info *info, 89*91f16700Schasinglulu int *probe_data); 90*91f16700Schasinglulu 91*91f16700Schasinglulu /* Data passed to error record group handler */ 92*91f16700Schasinglulu struct err_handler_data { 93*91f16700Schasinglulu /* Info passed on from top-level exception handler */ 94*91f16700Schasinglulu uint64_t flags; 95*91f16700Schasinglulu void *cookie; 96*91f16700Schasinglulu void *handle; 97*91f16700Schasinglulu 98*91f16700Schasinglulu /* Data structure version */ 99*91f16700Schasinglulu unsigned int version; 100*91f16700Schasinglulu 101*91f16700Schasinglulu /* Reason for EA: one the ERROR_* constants */ 102*91f16700Schasinglulu unsigned int ea_reason; 103*91f16700Schasinglulu 104*91f16700Schasinglulu /* 105*91f16700Schasinglulu * For EAs received at vector, the value read from ESR; for an EA 106*91f16700Schasinglulu * synchronized by ESB, the value of DISR. 107*91f16700Schasinglulu */ 108*91f16700Schasinglulu uint32_t syndrome; 109*91f16700Schasinglulu 110*91f16700Schasinglulu /* For errors signalled via interrupt, the raw interrupt ID; otherwise, 0. */ 111*91f16700Schasinglulu unsigned int interrupt; 112*91f16700Schasinglulu }; 113*91f16700Schasinglulu 114*91f16700Schasinglulu /* Function to handle error from an error record group */ 115*91f16700Schasinglulu typedef int (*err_record_handler_t)(const struct err_record_info *info, 116*91f16700Schasinglulu int probe_data, const struct err_handler_data *const data); 117*91f16700Schasinglulu 118*91f16700Schasinglulu /* Error record information */ 119*91f16700Schasinglulu struct err_record_info { 120*91f16700Schasinglulu /* Function to probe error record group for errors */ 121*91f16700Schasinglulu err_record_probe_t probe; 122*91f16700Schasinglulu 123*91f16700Schasinglulu /* Function to handle error record group errors */ 124*91f16700Schasinglulu err_record_handler_t handler; 125*91f16700Schasinglulu 126*91f16700Schasinglulu /* Opaque group-specific data */ 127*91f16700Schasinglulu void *aux_data; 128*91f16700Schasinglulu 129*91f16700Schasinglulu /* Additional information for Standard Error Records */ 130*91f16700Schasinglulu union { 131*91f16700Schasinglulu struct { 132*91f16700Schasinglulu /* 133*91f16700Schasinglulu * For a group accessed via memory-mapped register, 134*91f16700Schasinglulu * base address of the page hosting error records, and 135*91f16700Schasinglulu * the size of the record group. 136*91f16700Schasinglulu */ 137*91f16700Schasinglulu uintptr_t base_addr; 138*91f16700Schasinglulu 139*91f16700Schasinglulu /* Size of group in number of KBs */ 140*91f16700Schasinglulu unsigned int size_num_k; 141*91f16700Schasinglulu } memmap; 142*91f16700Schasinglulu 143*91f16700Schasinglulu struct { 144*91f16700Schasinglulu /* 145*91f16700Schasinglulu * For error records accessed via system register, index of 146*91f16700Schasinglulu * the error record. 147*91f16700Schasinglulu */ 148*91f16700Schasinglulu unsigned int idx_start; 149*91f16700Schasinglulu unsigned int num_idx; 150*91f16700Schasinglulu } sysreg; 151*91f16700Schasinglulu }; 152*91f16700Schasinglulu 153*91f16700Schasinglulu /* Data structure version */ 154*91f16700Schasinglulu unsigned int version; 155*91f16700Schasinglulu 156*91f16700Schasinglulu /* Error record access mechanism */ 157*91f16700Schasinglulu unsigned int access:1; 158*91f16700Schasinglulu }; 159*91f16700Schasinglulu 160*91f16700Schasinglulu struct err_record_mapping { 161*91f16700Schasinglulu struct err_record_info *err_records; 162*91f16700Schasinglulu size_t num_err_records; 163*91f16700Schasinglulu }; 164*91f16700Schasinglulu 165*91f16700Schasinglulu struct ras_interrupt_mapping { 166*91f16700Schasinglulu struct ras_interrupt *intrs; 167*91f16700Schasinglulu size_t num_intrs; 168*91f16700Schasinglulu }; 169*91f16700Schasinglulu 170*91f16700Schasinglulu extern const struct err_record_mapping err_record_mappings; 171*91f16700Schasinglulu extern const struct ras_interrupt_mapping ras_interrupt_mappings; 172*91f16700Schasinglulu 173*91f16700Schasinglulu 174*91f16700Schasinglulu /* 175*91f16700Schasinglulu * Helper functions to probe memory-mapped and system registers implemented in 176*91f16700Schasinglulu * Standard Error Record format 177*91f16700Schasinglulu */ 178*91f16700Schasinglulu static inline int ras_err_ser_probe_memmap(const struct err_record_info *info, 179*91f16700Schasinglulu int *probe_data) 180*91f16700Schasinglulu { 181*91f16700Schasinglulu assert(info->version == ERR_HANDLER_VERSION); 182*91f16700Schasinglulu 183*91f16700Schasinglulu return ser_probe_memmap(info->memmap.base_addr, info->memmap.size_num_k, 184*91f16700Schasinglulu probe_data); 185*91f16700Schasinglulu } 186*91f16700Schasinglulu 187*91f16700Schasinglulu static inline int ras_err_ser_probe_sysreg(const struct err_record_info *info, 188*91f16700Schasinglulu int *probe_data) 189*91f16700Schasinglulu { 190*91f16700Schasinglulu assert(info->version == ERR_HANDLER_VERSION); 191*91f16700Schasinglulu 192*91f16700Schasinglulu return ser_probe_sysreg(info->sysreg.idx_start, info->sysreg.num_idx, 193*91f16700Schasinglulu probe_data); 194*91f16700Schasinglulu } 195*91f16700Schasinglulu 196*91f16700Schasinglulu const char *ras_serr_to_str(unsigned int serr); 197*91f16700Schasinglulu int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, 198*91f16700Schasinglulu void *handle, uint64_t flags); 199*91f16700Schasinglulu void ras_init(void); 200*91f16700Schasinglulu 201*91f16700Schasinglulu #endif /* __ASSEMBLER__ */ 202*91f16700Schasinglulu 203*91f16700Schasinglulu #endif /* RAS_H */ 204