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