Sanitise includes across codebase
[project/bcm63xx/atf.git] / lib / extensions / ras / ras_common.c
1 /*
2 * Copyright (c) 2018, 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 start, end, mid, probe_data, ret __unused;
87
88 const struct err_handler_data err_data = {
89 .version = ERR_HANDLER_VERSION,
90 .interrupt = intr_raw,
91 .flags = flags,
92 .cookie = cookie,
93 .handle = handle
94 };
95
96 assert(ras_interrupt_mappings.num_intrs > 0UL);
97
98 start = 0;
99 end = (int) ras_interrupt_mappings.num_intrs;
100 while (start <= end) {
101 mid = ((end + start) / 2);
102 if (intr_raw == ras_inrs[mid].intr_number) {
103 selected = &ras_inrs[mid];
104 break;
105 } else if (intr_raw < ras_inrs[mid].intr_number) {
106 /* Move left */
107 end = mid - 1;
108 } else {
109 /* Move right */
110 start = mid + 1;
111 }
112 }
113
114 if (selected == NULL) {
115 ERROR("RAS interrupt %u has no handler!\n", intr_raw);
116 panic();
117 }
118
119 if (selected->err_record->probe != NULL) {
120 ret = selected->err_record->probe(selected->err_record, &probe_data);
121 assert(ret != 0);
122 }
123
124 /* Call error handler for the record group */
125 assert(selected->err_record->handler != NULL);
126 (void) selected->err_record->handler(selected->err_record, probe_data,
127 &err_data);
128
129 return 0;
130 }
131
132 void __init ras_init(void)
133 {
134 #if ENABLE_ASSERTIONS
135 /* Check RAS interrupts are sorted */
136 assert_interrupts_sorted();
137 #endif
138
139 /* Register RAS priority handler */
140 ehf_register_priority_handler(PLAT_RAS_PRI, ras_interrupt_handler);
141 }