xref: /arm-trusted-firmware/lib/extensions/ras/ras_common.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2018-2021, 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 #include <stdbool.h>
9*91f16700Schasinglulu 
10*91f16700Schasinglulu #include <arch_helpers.h>
11*91f16700Schasinglulu #include <bl31/ea_handle.h>
12*91f16700Schasinglulu #include <bl31/ehf.h>
13*91f16700Schasinglulu #include <common/debug.h>
14*91f16700Schasinglulu #include <lib/extensions/ras.h>
15*91f16700Schasinglulu #include <lib/extensions/ras_arch.h>
16*91f16700Schasinglulu #include <plat/common/platform.h>
17*91f16700Schasinglulu 
18*91f16700Schasinglulu #ifndef PLAT_RAS_PRI
19*91f16700Schasinglulu # error Platform must define RAS priority value
20*91f16700Schasinglulu #endif
21*91f16700Schasinglulu 
22*91f16700Schasinglulu /*
23*91f16700Schasinglulu  * Function to convert architecturally-defined primary error code SERR,
24*91f16700Schasinglulu  * bits[7:0] from ERR<n>STATUS to its corresponding error string.
25*91f16700Schasinglulu  */
26*91f16700Schasinglulu const char *ras_serr_to_str(unsigned int serr)
27*91f16700Schasinglulu {
28*91f16700Schasinglulu 	const char *str[ERROR_STATUS_NUM_SERR] = {
29*91f16700Schasinglulu 		"No error",
30*91f16700Schasinglulu 		"IMPLEMENTATION DEFINED error",
31*91f16700Schasinglulu 		"Data value from (non-associative) internal memory",
32*91f16700Schasinglulu 		"IMPLEMENTATION DEFINED pin",
33*91f16700Schasinglulu 		"Assertion failure",
34*91f16700Schasinglulu 		"Error detected on internal data path",
35*91f16700Schasinglulu 		"Data value from associative memory",
36*91f16700Schasinglulu 		"Address/control value from associative memory",
37*91f16700Schasinglulu 		"Data value from a TLB",
38*91f16700Schasinglulu 		"Address/control value from a TLB",
39*91f16700Schasinglulu 		"Data value from producer",
40*91f16700Schasinglulu 		"Address/control value from producer",
41*91f16700Schasinglulu 		"Data value from (non-associative) external memory",
42*91f16700Schasinglulu 		"Illegal address (software fault)",
43*91f16700Schasinglulu 		"Illegal access (software fault)",
44*91f16700Schasinglulu 		"Illegal state (software fault)",
45*91f16700Schasinglulu 		"Internal data register",
46*91f16700Schasinglulu 		"Internal control register",
47*91f16700Schasinglulu 		"Error response from slave",
48*91f16700Schasinglulu 		"External timeout",
49*91f16700Schasinglulu 		"Internal timeout",
50*91f16700Schasinglulu 		"Deferred error from slave not supported at master"
51*91f16700Schasinglulu 	};
52*91f16700Schasinglulu 
53*91f16700Schasinglulu 	/*
54*91f16700Schasinglulu 	 * All other values are reserved. Reserved values might be defined
55*91f16700Schasinglulu 	 * in a future version of the architecture
56*91f16700Schasinglulu 	 */
57*91f16700Schasinglulu 	if (serr >= ERROR_STATUS_NUM_SERR)
58*91f16700Schasinglulu 		return "unknown SERR";
59*91f16700Schasinglulu 
60*91f16700Schasinglulu 	return str[serr];
61*91f16700Schasinglulu }
62*91f16700Schasinglulu 
63*91f16700Schasinglulu /* Handler that receives External Aborts on RAS-capable systems */
64*91f16700Schasinglulu int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
65*91f16700Schasinglulu 		void *handle, uint64_t flags)
66*91f16700Schasinglulu {
67*91f16700Schasinglulu 	unsigned int i, n_handled = 0;
68*91f16700Schasinglulu 	int probe_data, ret;
69*91f16700Schasinglulu 	struct err_record_info *info;
70*91f16700Schasinglulu 
71*91f16700Schasinglulu 	const struct err_handler_data err_data = {
72*91f16700Schasinglulu 		.version = ERR_HANDLER_VERSION,
73*91f16700Schasinglulu 		.ea_reason = ea_reason,
74*91f16700Schasinglulu 		.interrupt = 0,
75*91f16700Schasinglulu 		.syndrome = (uint32_t) syndrome,
76*91f16700Schasinglulu 		.flags = flags,
77*91f16700Schasinglulu 		.cookie = cookie,
78*91f16700Schasinglulu 		.handle = handle
79*91f16700Schasinglulu 	};
80*91f16700Schasinglulu 
81*91f16700Schasinglulu 	for_each_err_record_info(i, info) {
82*91f16700Schasinglulu 		assert(info->probe != NULL);
83*91f16700Schasinglulu 		assert(info->handler != NULL);
84*91f16700Schasinglulu 
85*91f16700Schasinglulu 		/* Continue probing until the record group signals no error */
86*91f16700Schasinglulu 		while (true) {
87*91f16700Schasinglulu 			if (info->probe(info, &probe_data) == 0)
88*91f16700Schasinglulu 				break;
89*91f16700Schasinglulu 
90*91f16700Schasinglulu 			/* Handle error */
91*91f16700Schasinglulu 			ret = info->handler(info, probe_data, &err_data);
92*91f16700Schasinglulu 			if (ret != 0)
93*91f16700Schasinglulu 				return ret;
94*91f16700Schasinglulu 
95*91f16700Schasinglulu 			n_handled++;
96*91f16700Schasinglulu 		}
97*91f16700Schasinglulu 	}
98*91f16700Schasinglulu 
99*91f16700Schasinglulu 	return (n_handled != 0U) ? 1 : 0;
100*91f16700Schasinglulu }
101*91f16700Schasinglulu 
102*91f16700Schasinglulu #if ENABLE_ASSERTIONS
103*91f16700Schasinglulu static void assert_interrupts_sorted(void)
104*91f16700Schasinglulu {
105*91f16700Schasinglulu 	unsigned int i, last;
106*91f16700Schasinglulu 	struct ras_interrupt *start = ras_interrupt_mappings.intrs;
107*91f16700Schasinglulu 
108*91f16700Schasinglulu 	if (ras_interrupt_mappings.num_intrs == 0UL)
109*91f16700Schasinglulu 		return;
110*91f16700Schasinglulu 
111*91f16700Schasinglulu 	last = start[0].intr_number;
112*91f16700Schasinglulu 	for (i = 1; i < ras_interrupt_mappings.num_intrs; i++) {
113*91f16700Schasinglulu 		assert(start[i].intr_number > last);
114*91f16700Schasinglulu 		last = start[i].intr_number;
115*91f16700Schasinglulu 	}
116*91f16700Schasinglulu }
117*91f16700Schasinglulu #endif
118*91f16700Schasinglulu 
119*91f16700Schasinglulu /*
120*91f16700Schasinglulu  * Given an RAS interrupt number, locate the registered handler and call it. If
121*91f16700Schasinglulu  * no handler was found for the interrupt number, this function panics.
122*91f16700Schasinglulu  */
123*91f16700Schasinglulu static int ras_interrupt_handler(uint32_t intr_raw, uint32_t flags,
124*91f16700Schasinglulu 		void *handle, void *cookie)
125*91f16700Schasinglulu {
126*91f16700Schasinglulu 	struct ras_interrupt *ras_inrs = ras_interrupt_mappings.intrs;
127*91f16700Schasinglulu 	struct ras_interrupt *selected = NULL;
128*91f16700Schasinglulu 	int probe_data = 0;
129*91f16700Schasinglulu 	int start, end, mid, ret __unused;
130*91f16700Schasinglulu 
131*91f16700Schasinglulu 	const struct err_handler_data err_data = {
132*91f16700Schasinglulu 		.version = ERR_HANDLER_VERSION,
133*91f16700Schasinglulu 		.interrupt = intr_raw,
134*91f16700Schasinglulu 		.flags = flags,
135*91f16700Schasinglulu 		.cookie = cookie,
136*91f16700Schasinglulu 		.handle = handle
137*91f16700Schasinglulu 	};
138*91f16700Schasinglulu 
139*91f16700Schasinglulu 	assert(ras_interrupt_mappings.num_intrs > 0UL);
140*91f16700Schasinglulu 
141*91f16700Schasinglulu 	start = 0;
142*91f16700Schasinglulu 	end = (int)ras_interrupt_mappings.num_intrs - 1;
143*91f16700Schasinglulu 	while (start <= end) {
144*91f16700Schasinglulu 		mid = ((end + start) / 2);
145*91f16700Schasinglulu 		if (intr_raw == ras_inrs[mid].intr_number) {
146*91f16700Schasinglulu 			selected = &ras_inrs[mid];
147*91f16700Schasinglulu 			break;
148*91f16700Schasinglulu 		} else if (intr_raw < ras_inrs[mid].intr_number) {
149*91f16700Schasinglulu 			/* Move left */
150*91f16700Schasinglulu 			end = mid - 1;
151*91f16700Schasinglulu 		} else {
152*91f16700Schasinglulu 			/* Move right */
153*91f16700Schasinglulu 			start = mid + 1;
154*91f16700Schasinglulu 		}
155*91f16700Schasinglulu 	}
156*91f16700Schasinglulu 
157*91f16700Schasinglulu 	if (selected == NULL) {
158*91f16700Schasinglulu 		ERROR("RAS interrupt %u has no handler!\n", intr_raw);
159*91f16700Schasinglulu 		panic();
160*91f16700Schasinglulu 	}
161*91f16700Schasinglulu 
162*91f16700Schasinglulu 	if (selected->err_record->probe != NULL) {
163*91f16700Schasinglulu 		ret = selected->err_record->probe(selected->err_record, &probe_data);
164*91f16700Schasinglulu 		assert(ret != 0);
165*91f16700Schasinglulu 	}
166*91f16700Schasinglulu 
167*91f16700Schasinglulu 	/* Call error handler for the record group */
168*91f16700Schasinglulu 	assert(selected->err_record->handler != NULL);
169*91f16700Schasinglulu 	(void) selected->err_record->handler(selected->err_record, probe_data,
170*91f16700Schasinglulu 			&err_data);
171*91f16700Schasinglulu 
172*91f16700Schasinglulu 	return 0;
173*91f16700Schasinglulu }
174*91f16700Schasinglulu 
175*91f16700Schasinglulu void __init ras_init(void)
176*91f16700Schasinglulu {
177*91f16700Schasinglulu #if ENABLE_ASSERTIONS
178*91f16700Schasinglulu 	/* Check RAS interrupts are sorted */
179*91f16700Schasinglulu 	assert_interrupts_sorted();
180*91f16700Schasinglulu #endif
181*91f16700Schasinglulu 
182*91f16700Schasinglulu 	/* Register RAS priority handler */
183*91f16700Schasinglulu 	ehf_register_priority_handler(PLAT_RAS_PRI, ras_interrupt_handler);
184*91f16700Schasinglulu }
185