xref: /rk3399_ARM-atf/include/lib/extensions/ras.h (revision d5dfdeb65ff5b7f24dded201d2945c7b74565ce8)
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