1362599ecSJeenu Viswambharan /* 2362599ecSJeenu Viswambharan * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. 3362599ecSJeenu Viswambharan * 4362599ecSJeenu Viswambharan * SPDX-License-Identifier: BSD-3-Clause 5362599ecSJeenu Viswambharan */ 6362599ecSJeenu Viswambharan 7*30a8d96eSJeenu Viswambharan #ifndef RAS_COMMON 8*30a8d96eSJeenu Viswambharan #define RAS_COMMON 9362599ecSJeenu Viswambharan 10*30a8d96eSJeenu Viswambharan #define ERR_HANDLER_VERSION 1U 11362599ecSJeenu Viswambharan 12362599ecSJeenu Viswambharan /* Error record access mechanism */ 13362599ecSJeenu Viswambharan #define ERR_ACCESS_SYSREG 0 14362599ecSJeenu Viswambharan #define ERR_ACCESS_MEMMAP 1 15362599ecSJeenu Viswambharan 16362599ecSJeenu Viswambharan /* 17362599ecSJeenu Viswambharan * Register all error records on the platform. 18362599ecSJeenu Viswambharan * 19362599ecSJeenu Viswambharan * This macro must be used in the same file as the array of error record info 20362599ecSJeenu Viswambharan * are declared. Only then would ARRAY_SIZE() yield a meaningful value. 21362599ecSJeenu Viswambharan */ 22362599ecSJeenu Viswambharan #define REGISTER_ERR_RECORD_INFO(_records) \ 23*30a8d96eSJeenu Viswambharan const struct err_record_mapping err_record_mappings = { \ 24*30a8d96eSJeenu Viswambharan .err_records = (_records), \ 25362599ecSJeenu Viswambharan .num_err_records = ARRAY_SIZE(_records), \ 26362599ecSJeenu Viswambharan } 27362599ecSJeenu Viswambharan 28362599ecSJeenu Viswambharan /* Error record info iterator */ 29362599ecSJeenu Viswambharan #define for_each_err_record_info(_i, _info) \ 30*30a8d96eSJeenu Viswambharan for ((_i) = 0, (_info) = err_record_mappings.err_records; \ 31*30a8d96eSJeenu Viswambharan (_i) < err_record_mappings.num_err_records; \ 32*30a8d96eSJeenu Viswambharan (_i)++, (_info)++) 33362599ecSJeenu Viswambharan 34*30a8d96eSJeenu Viswambharan #define ERR_RECORD_COMMON_(_probe, _handler, _aux) \ 35362599ecSJeenu Viswambharan .probe = _probe, \ 36362599ecSJeenu Viswambharan .handler = _handler, \ 37362599ecSJeenu Viswambharan .aux_data = _aux, 38362599ecSJeenu Viswambharan 39362599ecSJeenu Viswambharan #define ERR_RECORD_SYSREG_V1(_idx_start, _num_idx, _probe, _handler, _aux) \ 40362599ecSJeenu Viswambharan { \ 41362599ecSJeenu Viswambharan .version = 1, \ 42362599ecSJeenu Viswambharan .sysreg.idx_start = _idx_start, \ 43362599ecSJeenu Viswambharan .sysreg.num_idx = _num_idx, \ 44362599ecSJeenu Viswambharan .access = ERR_ACCESS_SYSREG, \ 45*30a8d96eSJeenu Viswambharan ERR_RECORD_COMMON_(_probe, _handler, _aux) \ 46362599ecSJeenu Viswambharan } 47362599ecSJeenu Viswambharan 48362599ecSJeenu Viswambharan #define ERR_RECORD_MEMMAP_V1(_base_addr, _size_num_k, _probe, _handler, _aux) \ 49362599ecSJeenu Viswambharan { \ 50362599ecSJeenu Viswambharan .version = 1, \ 51362599ecSJeenu Viswambharan .memmap.base_addr = _base_addr, \ 52362599ecSJeenu Viswambharan .memmap.size_num_k = _size_num_k, \ 53362599ecSJeenu Viswambharan .access = ERR_ACCESS_MEMMAP, \ 54*30a8d96eSJeenu Viswambharan ERR_RECORD_COMMON_(_probe, _handler, _aux) \ 55362599ecSJeenu Viswambharan } 56362599ecSJeenu Viswambharan 57ca6d9185SJeenu Viswambharan /* 58ca6d9185SJeenu Viswambharan * Macro to be used to name and declare an array of RAS interrupts along with 59ca6d9185SJeenu Viswambharan * their handlers. 60ca6d9185SJeenu Viswambharan * 61ca6d9185SJeenu Viswambharan * This macro must be used in the same file as the array of interrupts are 62ca6d9185SJeenu Viswambharan * declared. Only then would ARRAY_SIZE() yield a meaningful value. Also, the 63ca6d9185SJeenu Viswambharan * array is expected to be sorted in the increasing order of interrupt number. 64ca6d9185SJeenu Viswambharan */ 65ca6d9185SJeenu Viswambharan #define REGISTER_RAS_INTERRUPTS(_array) \ 66*30a8d96eSJeenu Viswambharan const struct ras_interrupt_mapping ras_interrupt_mappings = { \ 67*30a8d96eSJeenu Viswambharan .intrs = (_array), \ 68ca6d9185SJeenu Viswambharan .num_intrs = ARRAY_SIZE(_array), \ 69ca6d9185SJeenu Viswambharan } 70ca6d9185SJeenu Viswambharan 71362599ecSJeenu Viswambharan #ifndef __ASSEMBLY__ 72362599ecSJeenu Viswambharan 73362599ecSJeenu Viswambharan #include <assert.h> 74362599ecSJeenu Viswambharan #include <ras_arch.h> 75362599ecSJeenu Viswambharan 76362599ecSJeenu Viswambharan struct err_record_info; 77362599ecSJeenu Viswambharan 78ca6d9185SJeenu Viswambharan struct ras_interrupt { 79ca6d9185SJeenu Viswambharan /* Interrupt number, and the associated error record info */ 80ca6d9185SJeenu Viswambharan unsigned int intr_number; 81ca6d9185SJeenu Viswambharan struct err_record_info *err_record; 82ca6d9185SJeenu Viswambharan void *cookie; 83ca6d9185SJeenu Viswambharan }; 84ca6d9185SJeenu Viswambharan 85362599ecSJeenu Viswambharan /* Function to probe a error record group for error */ 86362599ecSJeenu Viswambharan typedef int (*err_record_probe_t)(const struct err_record_info *info, 87362599ecSJeenu Viswambharan int *probe_data); 88362599ecSJeenu Viswambharan 89362599ecSJeenu Viswambharan /* Data passed to error record group handler */ 90362599ecSJeenu Viswambharan struct err_handler_data { 91362599ecSJeenu Viswambharan /* Info passed on from top-level exception handler */ 92362599ecSJeenu Viswambharan uint64_t flags; 93362599ecSJeenu Viswambharan void *cookie; 94362599ecSJeenu Viswambharan void *handle; 95362599ecSJeenu Viswambharan 96362599ecSJeenu Viswambharan /* Data structure version */ 97362599ecSJeenu Viswambharan unsigned int version; 98362599ecSJeenu Viswambharan 99362599ecSJeenu Viswambharan /* Reason for EA: one the ERROR_* constants */ 100362599ecSJeenu Viswambharan unsigned int ea_reason; 101362599ecSJeenu Viswambharan 102362599ecSJeenu Viswambharan /* 103362599ecSJeenu Viswambharan * For EAs received at vector, the value read from ESR; for an EA 104362599ecSJeenu Viswambharan * synchronized by ESB, the value of DISR. 105362599ecSJeenu Viswambharan */ 106362599ecSJeenu Viswambharan uint32_t syndrome; 107ca6d9185SJeenu Viswambharan 108ca6d9185SJeenu Viswambharan /* For errors signalled via. interrupt, the raw interrupt ID; otherwise, 0. */ 109ca6d9185SJeenu Viswambharan unsigned int interrupt; 110362599ecSJeenu Viswambharan }; 111362599ecSJeenu Viswambharan 112362599ecSJeenu Viswambharan /* Function to handle error from an error record group */ 113362599ecSJeenu Viswambharan typedef int (*err_record_handler_t)(const struct err_record_info *info, 114362599ecSJeenu Viswambharan int probe_data, const struct err_handler_data *const data); 115362599ecSJeenu Viswambharan 116362599ecSJeenu Viswambharan /* Error record information */ 117362599ecSJeenu Viswambharan struct err_record_info { 118362599ecSJeenu Viswambharan /* Function to probe error record group for errors */ 119362599ecSJeenu Viswambharan err_record_probe_t probe; 120362599ecSJeenu Viswambharan 121362599ecSJeenu Viswambharan /* Function to handle error record group errors */ 122362599ecSJeenu Viswambharan err_record_handler_t handler; 123362599ecSJeenu Viswambharan 124362599ecSJeenu Viswambharan /* Opaque group-specific data */ 125362599ecSJeenu Viswambharan void *aux_data; 126362599ecSJeenu Viswambharan 127362599ecSJeenu Viswambharan /* Additional information for Standard Error Records */ 128362599ecSJeenu Viswambharan union { 129362599ecSJeenu Viswambharan struct { 130362599ecSJeenu Viswambharan /* 131362599ecSJeenu Viswambharan * For a group accessed via. memory-mapped register, 132362599ecSJeenu Viswambharan * base address of the page hosting error records, and 133362599ecSJeenu Viswambharan * the size of the record group. 134362599ecSJeenu Viswambharan */ 135362599ecSJeenu Viswambharan uintptr_t base_addr; 136362599ecSJeenu Viswambharan 137362599ecSJeenu Viswambharan /* Size of group in number of KBs */ 138362599ecSJeenu Viswambharan unsigned int size_num_k; 139362599ecSJeenu Viswambharan } memmap; 140362599ecSJeenu Viswambharan 141362599ecSJeenu Viswambharan struct { 142362599ecSJeenu Viswambharan /* 143362599ecSJeenu Viswambharan * For error records accessed via. system register, index of 144362599ecSJeenu Viswambharan * the error record. 145362599ecSJeenu Viswambharan */ 146362599ecSJeenu Viswambharan unsigned int idx_start; 147362599ecSJeenu Viswambharan unsigned int num_idx; 148362599ecSJeenu Viswambharan } sysreg; 149362599ecSJeenu Viswambharan }; 150362599ecSJeenu Viswambharan 151362599ecSJeenu Viswambharan /* Data structure version */ 152362599ecSJeenu Viswambharan unsigned int version; 153362599ecSJeenu Viswambharan 154362599ecSJeenu Viswambharan /* Error record access mechanism */ 155362599ecSJeenu Viswambharan unsigned int access:1; 156362599ecSJeenu Viswambharan }; 157362599ecSJeenu Viswambharan 158362599ecSJeenu Viswambharan struct err_record_mapping { 159362599ecSJeenu Viswambharan struct err_record_info *err_records; 160362599ecSJeenu Viswambharan size_t num_err_records; 161362599ecSJeenu Viswambharan }; 162362599ecSJeenu Viswambharan 163ca6d9185SJeenu Viswambharan struct ras_interrupt_mapping { 164ca6d9185SJeenu Viswambharan struct ras_interrupt *intrs; 165ca6d9185SJeenu Viswambharan size_t num_intrs; 166ca6d9185SJeenu Viswambharan }; 167ca6d9185SJeenu Viswambharan 168*30a8d96eSJeenu Viswambharan extern const struct err_record_mapping err_record_mappings; 169*30a8d96eSJeenu Viswambharan extern const struct ras_interrupt_mapping ras_interrupt_mappings; 170362599ecSJeenu Viswambharan 171362599ecSJeenu Viswambharan 172362599ecSJeenu Viswambharan /* 173362599ecSJeenu Viswambharan * Helper functions to probe memory-mapped and system registers implemented in 174362599ecSJeenu Viswambharan * Standard Error Record format 175362599ecSJeenu Viswambharan */ 176362599ecSJeenu Viswambharan static inline int ras_err_ser_probe_memmap(const struct err_record_info *info, 177362599ecSJeenu Viswambharan int *probe_data) 178362599ecSJeenu Viswambharan { 179362599ecSJeenu Viswambharan assert(info->version == ERR_HANDLER_VERSION); 180362599ecSJeenu Viswambharan 181362599ecSJeenu Viswambharan return ser_probe_memmap(info->memmap.base_addr, info->memmap.size_num_k, 182362599ecSJeenu Viswambharan probe_data); 183362599ecSJeenu Viswambharan } 184362599ecSJeenu Viswambharan 185362599ecSJeenu Viswambharan static inline int ras_err_ser_probe_sysreg(const struct err_record_info *info, 186362599ecSJeenu Viswambharan int *probe_data) 187362599ecSJeenu Viswambharan { 188362599ecSJeenu Viswambharan assert(info->version == ERR_HANDLER_VERSION); 189362599ecSJeenu Viswambharan 190362599ecSJeenu Viswambharan return ser_probe_sysreg(info->sysreg.idx_start, info->sysreg.num_idx, 191362599ecSJeenu Viswambharan probe_data); 192362599ecSJeenu Viswambharan } 193362599ecSJeenu Viswambharan 194362599ecSJeenu Viswambharan int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, 195362599ecSJeenu Viswambharan void *handle, uint64_t flags); 196ca6d9185SJeenu Viswambharan void ras_init(void); 197362599ecSJeenu Viswambharan 198362599ecSJeenu Viswambharan #endif /* __ASSEMBLY__ */ 199*30a8d96eSJeenu Viswambharan #endif /* RAS_COMMON */ 200