1362599ecSJeenu Viswambharan /* 2362599ecSJeenu Viswambharan * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. 3*8ca61538SDavid Pu * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. 4362599ecSJeenu Viswambharan * 5362599ecSJeenu Viswambharan * SPDX-License-Identifier: BSD-3-Clause 6362599ecSJeenu Viswambharan */ 7362599ecSJeenu Viswambharan 8c3cf06f1SAntonio Nino Diaz #ifndef RAS_H 9c3cf06f1SAntonio Nino Diaz #define RAS_H 10362599ecSJeenu Viswambharan 1130a8d96eSJeenu Viswambharan #define ERR_HANDLER_VERSION 1U 12362599ecSJeenu Viswambharan 13362599ecSJeenu Viswambharan /* Error record access mechanism */ 14362599ecSJeenu Viswambharan #define ERR_ACCESS_SYSREG 0 15362599ecSJeenu Viswambharan #define ERR_ACCESS_MEMMAP 1 16362599ecSJeenu Viswambharan 17362599ecSJeenu Viswambharan /* 18362599ecSJeenu Viswambharan * Register all error records on the platform. 19362599ecSJeenu Viswambharan * 20362599ecSJeenu Viswambharan * This macro must be used in the same file as the array of error record info 21362599ecSJeenu Viswambharan * are declared. Only then would ARRAY_SIZE() yield a meaningful value. 22362599ecSJeenu Viswambharan */ 23362599ecSJeenu Viswambharan #define REGISTER_ERR_RECORD_INFO(_records) \ 2430a8d96eSJeenu Viswambharan const struct err_record_mapping err_record_mappings = { \ 2530a8d96eSJeenu Viswambharan .err_records = (_records), \ 26362599ecSJeenu Viswambharan .num_err_records = ARRAY_SIZE(_records), \ 27362599ecSJeenu Viswambharan } 28362599ecSJeenu Viswambharan 29362599ecSJeenu Viswambharan /* Error record info iterator */ 30362599ecSJeenu Viswambharan #define for_each_err_record_info(_i, _info) \ 3130a8d96eSJeenu Viswambharan for ((_i) = 0, (_info) = err_record_mappings.err_records; \ 3230a8d96eSJeenu Viswambharan (_i) < err_record_mappings.num_err_records; \ 3330a8d96eSJeenu Viswambharan (_i)++, (_info)++) 34362599ecSJeenu Viswambharan 3530a8d96eSJeenu Viswambharan #define ERR_RECORD_COMMON_(_probe, _handler, _aux) \ 36362599ecSJeenu Viswambharan .probe = _probe, \ 37362599ecSJeenu Viswambharan .handler = _handler, \ 38362599ecSJeenu Viswambharan .aux_data = _aux, 39362599ecSJeenu Viswambharan 40362599ecSJeenu Viswambharan #define ERR_RECORD_SYSREG_V1(_idx_start, _num_idx, _probe, _handler, _aux) \ 41362599ecSJeenu Viswambharan { \ 42362599ecSJeenu Viswambharan .version = 1, \ 43362599ecSJeenu Viswambharan .sysreg.idx_start = _idx_start, \ 44362599ecSJeenu Viswambharan .sysreg.num_idx = _num_idx, \ 45362599ecSJeenu Viswambharan .access = ERR_ACCESS_SYSREG, \ 4630a8d96eSJeenu Viswambharan ERR_RECORD_COMMON_(_probe, _handler, _aux) \ 47362599ecSJeenu Viswambharan } 48362599ecSJeenu Viswambharan 49362599ecSJeenu Viswambharan #define ERR_RECORD_MEMMAP_V1(_base_addr, _size_num_k, _probe, _handler, _aux) \ 50362599ecSJeenu Viswambharan { \ 51362599ecSJeenu Viswambharan .version = 1, \ 52362599ecSJeenu Viswambharan .memmap.base_addr = _base_addr, \ 53362599ecSJeenu Viswambharan .memmap.size_num_k = _size_num_k, \ 54362599ecSJeenu Viswambharan .access = ERR_ACCESS_MEMMAP, \ 5530a8d96eSJeenu Viswambharan ERR_RECORD_COMMON_(_probe, _handler, _aux) \ 56362599ecSJeenu Viswambharan } 57362599ecSJeenu Viswambharan 58ca6d9185SJeenu Viswambharan /* 59ca6d9185SJeenu Viswambharan * Macro to be used to name and declare an array of RAS interrupts along with 60ca6d9185SJeenu Viswambharan * their handlers. 61ca6d9185SJeenu Viswambharan * 62ca6d9185SJeenu Viswambharan * This macro must be used in the same file as the array of interrupts are 63ca6d9185SJeenu Viswambharan * declared. Only then would ARRAY_SIZE() yield a meaningful value. Also, the 64ca6d9185SJeenu Viswambharan * array is expected to be sorted in the increasing order of interrupt number. 65ca6d9185SJeenu Viswambharan */ 66ca6d9185SJeenu Viswambharan #define REGISTER_RAS_INTERRUPTS(_array) \ 6730a8d96eSJeenu Viswambharan const struct ras_interrupt_mapping ras_interrupt_mappings = { \ 6830a8d96eSJeenu Viswambharan .intrs = (_array), \ 69ca6d9185SJeenu Viswambharan .num_intrs = ARRAY_SIZE(_array), \ 70ca6d9185SJeenu Viswambharan } 71ca6d9185SJeenu Viswambharan 72d5dfdeb6SJulius Werner #ifndef __ASSEMBLER__ 73362599ecSJeenu Viswambharan 74362599ecSJeenu Viswambharan #include <assert.h> 7509d40e0eSAntonio Nino Diaz 7609d40e0eSAntonio Nino Diaz #include <lib/extensions/ras_arch.h> 77362599ecSJeenu Viswambharan 78362599ecSJeenu Viswambharan struct err_record_info; 79362599ecSJeenu Viswambharan 80ca6d9185SJeenu Viswambharan struct ras_interrupt { 81ca6d9185SJeenu Viswambharan /* Interrupt number, and the associated error record info */ 82ca6d9185SJeenu Viswambharan unsigned int intr_number; 83ca6d9185SJeenu Viswambharan struct err_record_info *err_record; 84ca6d9185SJeenu Viswambharan void *cookie; 85ca6d9185SJeenu Viswambharan }; 86ca6d9185SJeenu Viswambharan 87362599ecSJeenu Viswambharan /* Function to probe a error record group for error */ 88362599ecSJeenu Viswambharan typedef int (*err_record_probe_t)(const struct err_record_info *info, 89362599ecSJeenu Viswambharan int *probe_data); 90362599ecSJeenu Viswambharan 91362599ecSJeenu Viswambharan /* Data passed to error record group handler */ 92362599ecSJeenu Viswambharan struct err_handler_data { 93362599ecSJeenu Viswambharan /* Info passed on from top-level exception handler */ 94362599ecSJeenu Viswambharan uint64_t flags; 95362599ecSJeenu Viswambharan void *cookie; 96362599ecSJeenu Viswambharan void *handle; 97362599ecSJeenu Viswambharan 98362599ecSJeenu Viswambharan /* Data structure version */ 99362599ecSJeenu Viswambharan unsigned int version; 100362599ecSJeenu Viswambharan 101362599ecSJeenu Viswambharan /* Reason for EA: one the ERROR_* constants */ 102362599ecSJeenu Viswambharan unsigned int ea_reason; 103362599ecSJeenu Viswambharan 104362599ecSJeenu Viswambharan /* 105362599ecSJeenu Viswambharan * For EAs received at vector, the value read from ESR; for an EA 106362599ecSJeenu Viswambharan * synchronized by ESB, the value of DISR. 107362599ecSJeenu Viswambharan */ 108362599ecSJeenu Viswambharan uint32_t syndrome; 109ca6d9185SJeenu Viswambharan 11073308618SAntonio Nino Diaz /* For errors signalled via interrupt, the raw interrupt ID; otherwise, 0. */ 111ca6d9185SJeenu Viswambharan unsigned int interrupt; 112362599ecSJeenu Viswambharan }; 113362599ecSJeenu Viswambharan 114362599ecSJeenu Viswambharan /* Function to handle error from an error record group */ 115362599ecSJeenu Viswambharan typedef int (*err_record_handler_t)(const struct err_record_info *info, 116362599ecSJeenu Viswambharan int probe_data, const struct err_handler_data *const data); 117362599ecSJeenu Viswambharan 118362599ecSJeenu Viswambharan /* Error record information */ 119362599ecSJeenu Viswambharan struct err_record_info { 120362599ecSJeenu Viswambharan /* Function to probe error record group for errors */ 121362599ecSJeenu Viswambharan err_record_probe_t probe; 122362599ecSJeenu Viswambharan 123362599ecSJeenu Viswambharan /* Function to handle error record group errors */ 124362599ecSJeenu Viswambharan err_record_handler_t handler; 125362599ecSJeenu Viswambharan 126362599ecSJeenu Viswambharan /* Opaque group-specific data */ 127362599ecSJeenu Viswambharan void *aux_data; 128362599ecSJeenu Viswambharan 129362599ecSJeenu Viswambharan /* Additional information for Standard Error Records */ 130362599ecSJeenu Viswambharan union { 131362599ecSJeenu Viswambharan struct { 132362599ecSJeenu Viswambharan /* 13373308618SAntonio Nino Diaz * For a group accessed via memory-mapped register, 134362599ecSJeenu Viswambharan * base address of the page hosting error records, and 135362599ecSJeenu Viswambharan * the size of the record group. 136362599ecSJeenu Viswambharan */ 137362599ecSJeenu Viswambharan uintptr_t base_addr; 138362599ecSJeenu Viswambharan 139362599ecSJeenu Viswambharan /* Size of group in number of KBs */ 140362599ecSJeenu Viswambharan unsigned int size_num_k; 141362599ecSJeenu Viswambharan } memmap; 142362599ecSJeenu Viswambharan 143362599ecSJeenu Viswambharan struct { 144362599ecSJeenu Viswambharan /* 14573308618SAntonio Nino Diaz * For error records accessed via system register, index of 146362599ecSJeenu Viswambharan * the error record. 147362599ecSJeenu Viswambharan */ 148362599ecSJeenu Viswambharan unsigned int idx_start; 149362599ecSJeenu Viswambharan unsigned int num_idx; 150362599ecSJeenu Viswambharan } sysreg; 151362599ecSJeenu Viswambharan }; 152362599ecSJeenu Viswambharan 153362599ecSJeenu Viswambharan /* Data structure version */ 154362599ecSJeenu Viswambharan unsigned int version; 155362599ecSJeenu Viswambharan 156362599ecSJeenu Viswambharan /* Error record access mechanism */ 157362599ecSJeenu Viswambharan unsigned int access:1; 158362599ecSJeenu Viswambharan }; 159362599ecSJeenu Viswambharan 160362599ecSJeenu Viswambharan struct err_record_mapping { 161362599ecSJeenu Viswambharan struct err_record_info *err_records; 162362599ecSJeenu Viswambharan size_t num_err_records; 163362599ecSJeenu Viswambharan }; 164362599ecSJeenu Viswambharan 165ca6d9185SJeenu Viswambharan struct ras_interrupt_mapping { 166ca6d9185SJeenu Viswambharan struct ras_interrupt *intrs; 167ca6d9185SJeenu Viswambharan size_t num_intrs; 168ca6d9185SJeenu Viswambharan }; 169ca6d9185SJeenu Viswambharan 17030a8d96eSJeenu Viswambharan extern const struct err_record_mapping err_record_mappings; 17130a8d96eSJeenu Viswambharan extern const struct ras_interrupt_mapping ras_interrupt_mappings; 172362599ecSJeenu Viswambharan 173362599ecSJeenu Viswambharan 174362599ecSJeenu Viswambharan /* 175362599ecSJeenu Viswambharan * Helper functions to probe memory-mapped and system registers implemented in 176362599ecSJeenu Viswambharan * Standard Error Record format 177362599ecSJeenu Viswambharan */ 178362599ecSJeenu Viswambharan static inline int ras_err_ser_probe_memmap(const struct err_record_info *info, 179362599ecSJeenu Viswambharan int *probe_data) 180362599ecSJeenu Viswambharan { 181362599ecSJeenu Viswambharan assert(info->version == ERR_HANDLER_VERSION); 182362599ecSJeenu Viswambharan 183362599ecSJeenu Viswambharan return ser_probe_memmap(info->memmap.base_addr, info->memmap.size_num_k, 184362599ecSJeenu Viswambharan probe_data); 185362599ecSJeenu Viswambharan } 186362599ecSJeenu Viswambharan 187362599ecSJeenu Viswambharan static inline int ras_err_ser_probe_sysreg(const struct err_record_info *info, 188362599ecSJeenu Viswambharan int *probe_data) 189362599ecSJeenu Viswambharan { 190362599ecSJeenu Viswambharan assert(info->version == ERR_HANDLER_VERSION); 191362599ecSJeenu Viswambharan 192362599ecSJeenu Viswambharan return ser_probe_sysreg(info->sysreg.idx_start, info->sysreg.num_idx, 193362599ecSJeenu Viswambharan probe_data); 194362599ecSJeenu Viswambharan } 195362599ecSJeenu Viswambharan 196*8ca61538SDavid Pu const char *ras_serr_to_str(unsigned int serr); 197362599ecSJeenu Viswambharan int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, 198362599ecSJeenu Viswambharan void *handle, uint64_t flags); 199ca6d9185SJeenu Viswambharan void ras_init(void); 200362599ecSJeenu Viswambharan 201d5dfdeb6SJulius Werner #endif /* __ASSEMBLER__ */ 202c3cf06f1SAntonio Nino Diaz 203c3cf06f1SAntonio Nino Diaz #endif /* RAS_H */ 204