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