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