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