xref: /rk3399_ARM-atf/lib/extensions/ras/ras_common.c (revision 8ca61538a0fe3aed6764a012317cbf61f09ebb61)
1362599ecSJeenu Viswambharan /*
2dbff5263SJustin Chadwell  * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
3*8ca61538SDavid Pu  * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
4362599ecSJeenu Viswambharan  *
5362599ecSJeenu Viswambharan  * SPDX-License-Identifier: BSD-3-Clause
6362599ecSJeenu Viswambharan  */
7362599ecSJeenu Viswambharan 
830a8d96eSJeenu Viswambharan #include <stdbool.h>
9362599ecSJeenu Viswambharan 
1009d40e0eSAntonio Nino Diaz #include <arch_helpers.h>
1109d40e0eSAntonio Nino Diaz #include <bl31/ea_handle.h>
1209d40e0eSAntonio Nino Diaz #include <bl31/ehf.h>
1309d40e0eSAntonio Nino Diaz #include <common/debug.h>
1409d40e0eSAntonio Nino Diaz #include <lib/extensions/ras.h>
1509d40e0eSAntonio Nino Diaz #include <lib/extensions/ras_arch.h>
1609d40e0eSAntonio Nino Diaz #include <plat/common/platform.h>
1709d40e0eSAntonio Nino Diaz 
18ca6d9185SJeenu Viswambharan #ifndef PLAT_RAS_PRI
19ca6d9185SJeenu Viswambharan # error Platform must define RAS priority value
20ca6d9185SJeenu Viswambharan #endif
21ca6d9185SJeenu Viswambharan 
22*8ca61538SDavid Pu /*
23*8ca61538SDavid Pu  * Function to convert architecturally-defined primary error code SERR,
24*8ca61538SDavid Pu  * bits[7:0] from ERR<n>STATUS to its corresponding error string.
25*8ca61538SDavid Pu  */
26*8ca61538SDavid Pu const char *ras_serr_to_str(unsigned int serr)
27*8ca61538SDavid Pu {
28*8ca61538SDavid Pu 	const char *str[ERROR_STATUS_NUM_SERR] = {
29*8ca61538SDavid Pu 		"No error",
30*8ca61538SDavid Pu 		"IMPLEMENTATION DEFINED error",
31*8ca61538SDavid Pu 		"Data value from (non-associative) internal memory",
32*8ca61538SDavid Pu 		"IMPLEMENTATION DEFINED pin",
33*8ca61538SDavid Pu 		"Assertion failure",
34*8ca61538SDavid Pu 		"Error detected on internal data path",
35*8ca61538SDavid Pu 		"Data value from associative memory",
36*8ca61538SDavid Pu 		"Address/control value from associative memory",
37*8ca61538SDavid Pu 		"Data value from a TLB",
38*8ca61538SDavid Pu 		"Address/control value from a TLB",
39*8ca61538SDavid Pu 		"Data value from producer",
40*8ca61538SDavid Pu 		"Address/control value from producer",
41*8ca61538SDavid Pu 		"Data value from (non-associative) external memory",
42*8ca61538SDavid Pu 		"Illegal address (software fault)",
43*8ca61538SDavid Pu 		"Illegal access (software fault)",
44*8ca61538SDavid Pu 		"Illegal state (software fault)",
45*8ca61538SDavid Pu 		"Internal data register",
46*8ca61538SDavid Pu 		"Internal control register",
47*8ca61538SDavid Pu 		"Error response from slave",
48*8ca61538SDavid Pu 		"External timeout",
49*8ca61538SDavid Pu 		"Internal timeout",
50*8ca61538SDavid Pu 		"Deferred error from slave not supported at master"
51*8ca61538SDavid Pu 	};
52*8ca61538SDavid Pu 
53*8ca61538SDavid Pu 	/*
54*8ca61538SDavid Pu 	 * All other values are reserved. Reserved values might be defined
55*8ca61538SDavid Pu 	 * in a future version of the architecture
56*8ca61538SDavid Pu 	 */
57*8ca61538SDavid Pu 	if (serr >= ERROR_STATUS_NUM_SERR)
58*8ca61538SDavid Pu 		return "unknown SERR";
59*8ca61538SDavid Pu 
60*8ca61538SDavid Pu 	return str[serr];
61*8ca61538SDavid Pu }
62*8ca61538SDavid Pu 
63362599ecSJeenu Viswambharan /* Handler that receives External Aborts on RAS-capable systems */
64362599ecSJeenu Viswambharan int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
65362599ecSJeenu Viswambharan 		void *handle, uint64_t flags)
66362599ecSJeenu Viswambharan {
6730a8d96eSJeenu Viswambharan 	unsigned int i, n_handled = 0;
6830a8d96eSJeenu Viswambharan 	int probe_data, ret;
69362599ecSJeenu Viswambharan 	struct err_record_info *info;
70362599ecSJeenu Viswambharan 
71362599ecSJeenu Viswambharan 	const struct err_handler_data err_data = {
72362599ecSJeenu Viswambharan 		.version = ERR_HANDLER_VERSION,
73362599ecSJeenu Viswambharan 		.ea_reason = ea_reason,
74ca6d9185SJeenu Viswambharan 		.interrupt = 0,
7530a8d96eSJeenu Viswambharan 		.syndrome = (uint32_t) syndrome,
76362599ecSJeenu Viswambharan 		.flags = flags,
77362599ecSJeenu Viswambharan 		.cookie = cookie,
78362599ecSJeenu Viswambharan 		.handle = handle
79362599ecSJeenu Viswambharan 	};
80362599ecSJeenu Viswambharan 
81362599ecSJeenu Viswambharan 	for_each_err_record_info(i, info) {
82362599ecSJeenu Viswambharan 		assert(info->probe != NULL);
83362599ecSJeenu Viswambharan 		assert(info->handler != NULL);
84362599ecSJeenu Viswambharan 
85362599ecSJeenu Viswambharan 		/* Continue probing until the record group signals no error */
8630a8d96eSJeenu Viswambharan 		while (true) {
87362599ecSJeenu Viswambharan 			if (info->probe(info, &probe_data) == 0)
88362599ecSJeenu Viswambharan 				break;
89362599ecSJeenu Viswambharan 
90362599ecSJeenu Viswambharan 			/* Handle error */
91362599ecSJeenu Viswambharan 			ret = info->handler(info, probe_data, &err_data);
92362599ecSJeenu Viswambharan 			if (ret != 0)
93362599ecSJeenu Viswambharan 				return ret;
94362599ecSJeenu Viswambharan 
95362599ecSJeenu Viswambharan 			n_handled++;
96362599ecSJeenu Viswambharan 		}
97362599ecSJeenu Viswambharan 	}
98362599ecSJeenu Viswambharan 
9930a8d96eSJeenu Viswambharan 	return (n_handled != 0U) ? 1 : 0;
100362599ecSJeenu Viswambharan }
101ca6d9185SJeenu Viswambharan 
102ca6d9185SJeenu Viswambharan #if ENABLE_ASSERTIONS
103ca6d9185SJeenu Viswambharan static void assert_interrupts_sorted(void)
104ca6d9185SJeenu Viswambharan {
105ca6d9185SJeenu Viswambharan 	unsigned int i, last;
10630a8d96eSJeenu Viswambharan 	struct ras_interrupt *start = ras_interrupt_mappings.intrs;
107ca6d9185SJeenu Viswambharan 
10830a8d96eSJeenu Viswambharan 	if (ras_interrupt_mappings.num_intrs == 0UL)
109ca6d9185SJeenu Viswambharan 		return;
110ca6d9185SJeenu Viswambharan 
111ca6d9185SJeenu Viswambharan 	last = start[0].intr_number;
11230a8d96eSJeenu Viswambharan 	for (i = 1; i < ras_interrupt_mappings.num_intrs; i++) {
113ca6d9185SJeenu Viswambharan 		assert(start[i].intr_number > last);
114ca6d9185SJeenu Viswambharan 		last = start[i].intr_number;
115ca6d9185SJeenu Viswambharan 	}
116ca6d9185SJeenu Viswambharan }
117ca6d9185SJeenu Viswambharan #endif
118ca6d9185SJeenu Viswambharan 
119ca6d9185SJeenu Viswambharan /*
120ca6d9185SJeenu Viswambharan  * Given an RAS interrupt number, locate the registered handler and call it. If
121ca6d9185SJeenu Viswambharan  * no handler was found for the interrupt number, this function panics.
122ca6d9185SJeenu Viswambharan  */
123ca6d9185SJeenu Viswambharan static int ras_interrupt_handler(uint32_t intr_raw, uint32_t flags,
124ca6d9185SJeenu Viswambharan 		void *handle, void *cookie)
125ca6d9185SJeenu Viswambharan {
12630a8d96eSJeenu Viswambharan 	struct ras_interrupt *ras_inrs = ras_interrupt_mappings.intrs;
127ca6d9185SJeenu Viswambharan 	struct ras_interrupt *selected = NULL;
128dbff5263SJustin Chadwell 	int probe_data = 0;
129dbff5263SJustin Chadwell 	int start, end, mid, ret __unused;
130ca6d9185SJeenu Viswambharan 
131ca6d9185SJeenu Viswambharan 	const struct err_handler_data err_data = {
132ca6d9185SJeenu Viswambharan 		.version = ERR_HANDLER_VERSION,
133ca6d9185SJeenu Viswambharan 		.interrupt = intr_raw,
134ca6d9185SJeenu Viswambharan 		.flags = flags,
135ca6d9185SJeenu Viswambharan 		.cookie = cookie,
136ca6d9185SJeenu Viswambharan 		.handle = handle
137ca6d9185SJeenu Viswambharan 	};
138ca6d9185SJeenu Viswambharan 
13930a8d96eSJeenu Viswambharan 	assert(ras_interrupt_mappings.num_intrs > 0UL);
140ca6d9185SJeenu Viswambharan 
141ca6d9185SJeenu Viswambharan 	start = 0;
14230a8d96eSJeenu Viswambharan 	end = (int) ras_interrupt_mappings.num_intrs;
143ca6d9185SJeenu Viswambharan 	while (start <= end) {
144ca6d9185SJeenu Viswambharan 		mid = ((end + start) / 2);
145ca6d9185SJeenu Viswambharan 		if (intr_raw == ras_inrs[mid].intr_number) {
146ca6d9185SJeenu Viswambharan 			selected = &ras_inrs[mid];
147ca6d9185SJeenu Viswambharan 			break;
148ca6d9185SJeenu Viswambharan 		} else if (intr_raw < ras_inrs[mid].intr_number) {
149ca6d9185SJeenu Viswambharan 			/* Move left */
150ca6d9185SJeenu Viswambharan 			end = mid - 1;
151ca6d9185SJeenu Viswambharan 		} else {
152ca6d9185SJeenu Viswambharan 			/* Move right */
153ca6d9185SJeenu Viswambharan 			start = mid + 1;
154ca6d9185SJeenu Viswambharan 		}
155ca6d9185SJeenu Viswambharan 	}
156ca6d9185SJeenu Viswambharan 
157ca6d9185SJeenu Viswambharan 	if (selected == NULL) {
158ca6d9185SJeenu Viswambharan 		ERROR("RAS interrupt %u has no handler!\n", intr_raw);
159ca6d9185SJeenu Viswambharan 		panic();
160ca6d9185SJeenu Viswambharan 	}
161ca6d9185SJeenu Viswambharan 
16230a8d96eSJeenu Viswambharan 	if (selected->err_record->probe != NULL) {
163ca6d9185SJeenu Viswambharan 		ret = selected->err_record->probe(selected->err_record, &probe_data);
164ca6d9185SJeenu Viswambharan 		assert(ret != 0);
1654576f73cSSughosh Ganu 	}
166ca6d9185SJeenu Viswambharan 
167ca6d9185SJeenu Viswambharan 	/* Call error handler for the record group */
168ca6d9185SJeenu Viswambharan 	assert(selected->err_record->handler != NULL);
16930a8d96eSJeenu Viswambharan 	(void) selected->err_record->handler(selected->err_record, probe_data,
170ca6d9185SJeenu Viswambharan 			&err_data);
171ca6d9185SJeenu Viswambharan 
172ca6d9185SJeenu Viswambharan 	return 0;
173ca6d9185SJeenu Viswambharan }
174ca6d9185SJeenu Viswambharan 
17587c85134SDaniel Boulby void __init ras_init(void)
176ca6d9185SJeenu Viswambharan {
177ca6d9185SJeenu Viswambharan #if ENABLE_ASSERTIONS
178ca6d9185SJeenu Viswambharan 	/* Check RAS interrupts are sorted */
179ca6d9185SJeenu Viswambharan 	assert_interrupts_sorted();
180ca6d9185SJeenu Viswambharan #endif
181ca6d9185SJeenu Viswambharan 
182ca6d9185SJeenu Viswambharan 	/* Register RAS priority handler */
183ca6d9185SJeenu Viswambharan 	ehf_register_priority_handler(PLAT_RAS_PRI, ras_interrupt_handler);
184ca6d9185SJeenu Viswambharan }
185