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