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 7c3cf06f1SAntonio Nino Diaz #ifndef RAS_H 8c3cf06f1SAntonio Nino Diaz #define RAS_H 9362599ecSJeenu Viswambharan 1030a8d96eSJeenu 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) \ 2330a8d96eSJeenu Viswambharan const struct err_record_mapping err_record_mappings = { \ 2430a8d96eSJeenu 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) \ 3030a8d96eSJeenu Viswambharan for ((_i) = 0, (_info) = err_record_mappings.err_records; \ 3130a8d96eSJeenu Viswambharan (_i) < err_record_mappings.num_err_records; \ 3230a8d96eSJeenu Viswambharan (_i)++, (_info)++) 33362599ecSJeenu Viswambharan 3430a8d96eSJeenu 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, \ 4530a8d96eSJeenu 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, \ 5430a8d96eSJeenu 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) \ 6630a8d96eSJeenu Viswambharan const struct ras_interrupt_mapping ras_interrupt_mappings = { \ 6730a8d96eSJeenu Viswambharan .intrs = (_array), \ 68ca6d9185SJeenu Viswambharan .num_intrs = ARRAY_SIZE(_array), \ 69ca6d9185SJeenu Viswambharan } 70ca6d9185SJeenu Viswambharan 71*d5dfdeb6SJulius Werner #ifndef __ASSEMBLER__ 72362599ecSJeenu Viswambharan 73362599ecSJeenu Viswambharan #include <assert.h> 7409d40e0eSAntonio Nino Diaz 7509d40e0eSAntonio Nino Diaz #include <lib/extensions/ras_arch.h> 76362599ecSJeenu Viswambharan 77362599ecSJeenu Viswambharan struct err_record_info; 78362599ecSJeenu Viswambharan 79ca6d9185SJeenu Viswambharan struct ras_interrupt { 80ca6d9185SJeenu Viswambharan /* Interrupt number, and the associated error record info */ 81ca6d9185SJeenu Viswambharan unsigned int intr_number; 82ca6d9185SJeenu Viswambharan struct err_record_info *err_record; 83ca6d9185SJeenu Viswambharan void *cookie; 84ca6d9185SJeenu Viswambharan }; 85ca6d9185SJeenu Viswambharan 86362599ecSJeenu Viswambharan /* Function to probe a error record group for error */ 87362599ecSJeenu Viswambharan typedef int (*err_record_probe_t)(const struct err_record_info *info, 88362599ecSJeenu Viswambharan int *probe_data); 89362599ecSJeenu Viswambharan 90362599ecSJeenu Viswambharan /* Data passed to error record group handler */ 91362599ecSJeenu Viswambharan struct err_handler_data { 92362599ecSJeenu Viswambharan /* Info passed on from top-level exception handler */ 93362599ecSJeenu Viswambharan uint64_t flags; 94362599ecSJeenu Viswambharan void *cookie; 95362599ecSJeenu Viswambharan void *handle; 96362599ecSJeenu Viswambharan 97362599ecSJeenu Viswambharan /* Data structure version */ 98362599ecSJeenu Viswambharan unsigned int version; 99362599ecSJeenu Viswambharan 100362599ecSJeenu Viswambharan /* Reason for EA: one the ERROR_* constants */ 101362599ecSJeenu Viswambharan unsigned int ea_reason; 102362599ecSJeenu Viswambharan 103362599ecSJeenu Viswambharan /* 104362599ecSJeenu Viswambharan * For EAs received at vector, the value read from ESR; for an EA 105362599ecSJeenu Viswambharan * synchronized by ESB, the value of DISR. 106362599ecSJeenu Viswambharan */ 107362599ecSJeenu Viswambharan uint32_t syndrome; 108ca6d9185SJeenu Viswambharan 10973308618SAntonio Nino Diaz /* For errors signalled via interrupt, the raw interrupt ID; otherwise, 0. */ 110ca6d9185SJeenu Viswambharan unsigned int interrupt; 111362599ecSJeenu Viswambharan }; 112362599ecSJeenu Viswambharan 113362599ecSJeenu Viswambharan /* Function to handle error from an error record group */ 114362599ecSJeenu Viswambharan typedef int (*err_record_handler_t)(const struct err_record_info *info, 115362599ecSJeenu Viswambharan int probe_data, const struct err_handler_data *const data); 116362599ecSJeenu Viswambharan 117362599ecSJeenu Viswambharan /* Error record information */ 118362599ecSJeenu Viswambharan struct err_record_info { 119362599ecSJeenu Viswambharan /* Function to probe error record group for errors */ 120362599ecSJeenu Viswambharan err_record_probe_t probe; 121362599ecSJeenu Viswambharan 122362599ecSJeenu Viswambharan /* Function to handle error record group errors */ 123362599ecSJeenu Viswambharan err_record_handler_t handler; 124362599ecSJeenu Viswambharan 125362599ecSJeenu Viswambharan /* Opaque group-specific data */ 126362599ecSJeenu Viswambharan void *aux_data; 127362599ecSJeenu Viswambharan 128362599ecSJeenu Viswambharan /* Additional information for Standard Error Records */ 129362599ecSJeenu Viswambharan union { 130362599ecSJeenu Viswambharan struct { 131362599ecSJeenu Viswambharan /* 13273308618SAntonio Nino Diaz * For a group accessed via memory-mapped register, 133362599ecSJeenu Viswambharan * base address of the page hosting error records, and 134362599ecSJeenu Viswambharan * the size of the record group. 135362599ecSJeenu Viswambharan */ 136362599ecSJeenu Viswambharan uintptr_t base_addr; 137362599ecSJeenu Viswambharan 138362599ecSJeenu Viswambharan /* Size of group in number of KBs */ 139362599ecSJeenu Viswambharan unsigned int size_num_k; 140362599ecSJeenu Viswambharan } memmap; 141362599ecSJeenu Viswambharan 142362599ecSJeenu Viswambharan struct { 143362599ecSJeenu Viswambharan /* 14473308618SAntonio Nino Diaz * For error records accessed via system register, index of 145362599ecSJeenu Viswambharan * the error record. 146362599ecSJeenu Viswambharan */ 147362599ecSJeenu Viswambharan unsigned int idx_start; 148362599ecSJeenu Viswambharan unsigned int num_idx; 149362599ecSJeenu Viswambharan } sysreg; 150362599ecSJeenu Viswambharan }; 151362599ecSJeenu Viswambharan 152362599ecSJeenu Viswambharan /* Data structure version */ 153362599ecSJeenu Viswambharan unsigned int version; 154362599ecSJeenu Viswambharan 155362599ecSJeenu Viswambharan /* Error record access mechanism */ 156362599ecSJeenu Viswambharan unsigned int access:1; 157362599ecSJeenu Viswambharan }; 158362599ecSJeenu Viswambharan 159362599ecSJeenu Viswambharan struct err_record_mapping { 160362599ecSJeenu Viswambharan struct err_record_info *err_records; 161362599ecSJeenu Viswambharan size_t num_err_records; 162362599ecSJeenu Viswambharan }; 163362599ecSJeenu Viswambharan 164ca6d9185SJeenu Viswambharan struct ras_interrupt_mapping { 165ca6d9185SJeenu Viswambharan struct ras_interrupt *intrs; 166ca6d9185SJeenu Viswambharan size_t num_intrs; 167ca6d9185SJeenu Viswambharan }; 168ca6d9185SJeenu Viswambharan 16930a8d96eSJeenu Viswambharan extern const struct err_record_mapping err_record_mappings; 17030a8d96eSJeenu Viswambharan extern const struct ras_interrupt_mapping ras_interrupt_mappings; 171362599ecSJeenu Viswambharan 172362599ecSJeenu Viswambharan 173362599ecSJeenu Viswambharan /* 174362599ecSJeenu Viswambharan * Helper functions to probe memory-mapped and system registers implemented in 175362599ecSJeenu Viswambharan * Standard Error Record format 176362599ecSJeenu Viswambharan */ 177362599ecSJeenu Viswambharan static inline int ras_err_ser_probe_memmap(const struct err_record_info *info, 178362599ecSJeenu Viswambharan int *probe_data) 179362599ecSJeenu Viswambharan { 180362599ecSJeenu Viswambharan assert(info->version == ERR_HANDLER_VERSION); 181362599ecSJeenu Viswambharan 182362599ecSJeenu Viswambharan return ser_probe_memmap(info->memmap.base_addr, info->memmap.size_num_k, 183362599ecSJeenu Viswambharan probe_data); 184362599ecSJeenu Viswambharan } 185362599ecSJeenu Viswambharan 186362599ecSJeenu Viswambharan static inline int ras_err_ser_probe_sysreg(const struct err_record_info *info, 187362599ecSJeenu Viswambharan int *probe_data) 188362599ecSJeenu Viswambharan { 189362599ecSJeenu Viswambharan assert(info->version == ERR_HANDLER_VERSION); 190362599ecSJeenu Viswambharan 191362599ecSJeenu Viswambharan return ser_probe_sysreg(info->sysreg.idx_start, info->sysreg.num_idx, 192362599ecSJeenu Viswambharan probe_data); 193362599ecSJeenu Viswambharan } 194362599ecSJeenu Viswambharan 195362599ecSJeenu Viswambharan int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, 196362599ecSJeenu Viswambharan void *handle, uint64_t flags); 197ca6d9185SJeenu Viswambharan void ras_init(void); 198362599ecSJeenu Viswambharan 199*d5dfdeb6SJulius Werner #endif /* __ASSEMBLER__ */ 200c3cf06f1SAntonio Nino Diaz 201c3cf06f1SAntonio Nino Diaz #endif /* RAS_H */ 202