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