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