1362599ecSJeenu Viswambharan /*
2*4c700c15SGovindraj Raja * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
38ca61538SDavid 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 */
ras_err_ser_probe_memmap(const struct err_record_info * info,int * probe_data)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
ras_err_ser_probe_sysreg(const struct err_record_info * info,int * probe_data)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
1968ca61538SDavid 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