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