xref: /rk3399_ARM-atf/lib/extensions/ras/ras_common.c (revision eef90a772dc1c3b836c1e9304a22d805db3cf5b1)
1 /*
2  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <arch_helpers.h>
8 #include <debug.h>
9 #include <ea_handle.h>
10 #include <ehf.h>
11 #include <platform.h>
12 #include <ras.h>
13 #include <ras_arch.h>
14 
15 #ifndef PLAT_RAS_PRI
16 # error Platform must define RAS priority value
17 #endif
18 
19 /* Handler that receives External Aborts on RAS-capable systems */
20 int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
21 		void *handle, uint64_t flags)
22 {
23 	unsigned int i, n_handled = 0, ret;
24 	int probe_data;
25 	struct err_record_info *info;
26 
27 	const struct err_handler_data err_data = {
28 		.version = ERR_HANDLER_VERSION,
29 		.ea_reason = ea_reason,
30 		.interrupt = 0,
31 		.syndrome = syndrome,
32 		.flags = flags,
33 		.cookie = cookie,
34 		.handle = handle
35 	};
36 
37 	for_each_err_record_info(i, info) {
38 		assert(info->probe != NULL);
39 		assert(info->handler != NULL);
40 
41 		/* Continue probing until the record group signals no error */
42 		while (1) {
43 			if (info->probe(info, &probe_data) == 0)
44 				break;
45 
46 			/* Handle error */
47 			ret = info->handler(info, probe_data, &err_data);
48 			if (ret != 0)
49 				return ret;
50 
51 			n_handled++;
52 		}
53 	}
54 
55 	return (n_handled != 0);
56 }
57 
58 #if ENABLE_ASSERTIONS
59 static void assert_interrupts_sorted(void)
60 {
61 	unsigned int i, last;
62 	struct ras_interrupt *start = ras_interrupt_mapping.intrs;
63 
64 	if (ras_interrupt_mapping.num_intrs == 0)
65 		return;
66 
67 	last = start[0].intr_number;
68 	for (i = 1; i < ras_interrupt_mapping.num_intrs; i++) {
69 		assert(start[i].intr_number > last);
70 		last = start[i].intr_number;
71 	}
72 }
73 #endif
74 
75 /*
76  * Given an RAS interrupt number, locate the registered handler and call it. If
77  * no handler was found for the interrupt number, this function panics.
78  */
79 static int ras_interrupt_handler(uint32_t intr_raw, uint32_t flags,
80 		void *handle, void *cookie)
81 {
82 	struct ras_interrupt *ras_inrs = ras_interrupt_mapping.intrs;
83 	struct ras_interrupt *selected = NULL;
84 	int start, end, mid, probe_data, ret __unused;
85 
86 	const struct err_handler_data err_data = {
87 		.version = ERR_HANDLER_VERSION,
88 		.interrupt = intr_raw,
89 		.flags = flags,
90 		.cookie = cookie,
91 		.handle = handle
92 	};
93 
94 	assert(ras_interrupt_mapping.num_intrs > 0);
95 
96 	start = 0;
97 	end = ras_interrupt_mapping.num_intrs;
98 	while (start <= end) {
99 		mid = ((end + start) / 2);
100 		if (intr_raw == ras_inrs[mid].intr_number) {
101 			selected = &ras_inrs[mid];
102 			break;
103 		} else if (intr_raw < ras_inrs[mid].intr_number) {
104 			/* Move left */
105 			end = mid - 1;
106 		} else {
107 			/* Move right */
108 			start = mid + 1;
109 		}
110 	}
111 
112 	if (selected == NULL) {
113 		ERROR("RAS interrupt %u has no handler!\n", intr_raw);
114 		panic();
115 	}
116 
117 	if (selected->err_record->probe) {
118 		ret = selected->err_record->probe(selected->err_record, &probe_data);
119 		assert(ret != 0);
120 	}
121 
122 	/* Call error handler for the record group */
123 	assert(selected->err_record->handler != NULL);
124 	selected->err_record->handler(selected->err_record, probe_data,
125 			&err_data);
126 
127 	return 0;
128 }
129 
130 void ras_init(void)
131 {
132 #if ENABLE_ASSERTIONS
133 	/* Check RAS interrupts are sorted */
134 	assert_interrupts_sorted();
135 #endif
136 
137 	/* Register RAS priority handler */
138 	ehf_register_priority_handler(PLAT_RAS_PRI, ras_interrupt_handler);
139 }
140