1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
4*54fd6939SJiyong Park *
5*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause
6*54fd6939SJiyong Park */
7*54fd6939SJiyong Park
8*54fd6939SJiyong Park #include <stdbool.h>
9*54fd6939SJiyong Park
10*54fd6939SJiyong Park #include <arch_helpers.h>
11*54fd6939SJiyong Park #include <bl31/ea_handle.h>
12*54fd6939SJiyong Park #include <bl31/ehf.h>
13*54fd6939SJiyong Park #include <common/debug.h>
14*54fd6939SJiyong Park #include <lib/extensions/ras.h>
15*54fd6939SJiyong Park #include <lib/extensions/ras_arch.h>
16*54fd6939SJiyong Park #include <plat/common/platform.h>
17*54fd6939SJiyong Park
18*54fd6939SJiyong Park #ifndef PLAT_RAS_PRI
19*54fd6939SJiyong Park # error Platform must define RAS priority value
20*54fd6939SJiyong Park #endif
21*54fd6939SJiyong Park
22*54fd6939SJiyong Park /*
23*54fd6939SJiyong Park * Function to convert architecturally-defined primary error code SERR,
24*54fd6939SJiyong Park * bits[7:0] from ERR<n>STATUS to its corresponding error string.
25*54fd6939SJiyong Park */
ras_serr_to_str(unsigned int serr)26*54fd6939SJiyong Park const char *ras_serr_to_str(unsigned int serr)
27*54fd6939SJiyong Park {
28*54fd6939SJiyong Park const char *str[ERROR_STATUS_NUM_SERR] = {
29*54fd6939SJiyong Park "No error",
30*54fd6939SJiyong Park "IMPLEMENTATION DEFINED error",
31*54fd6939SJiyong Park "Data value from (non-associative) internal memory",
32*54fd6939SJiyong Park "IMPLEMENTATION DEFINED pin",
33*54fd6939SJiyong Park "Assertion failure",
34*54fd6939SJiyong Park "Error detected on internal data path",
35*54fd6939SJiyong Park "Data value from associative memory",
36*54fd6939SJiyong Park "Address/control value from associative memory",
37*54fd6939SJiyong Park "Data value from a TLB",
38*54fd6939SJiyong Park "Address/control value from a TLB",
39*54fd6939SJiyong Park "Data value from producer",
40*54fd6939SJiyong Park "Address/control value from producer",
41*54fd6939SJiyong Park "Data value from (non-associative) external memory",
42*54fd6939SJiyong Park "Illegal address (software fault)",
43*54fd6939SJiyong Park "Illegal access (software fault)",
44*54fd6939SJiyong Park "Illegal state (software fault)",
45*54fd6939SJiyong Park "Internal data register",
46*54fd6939SJiyong Park "Internal control register",
47*54fd6939SJiyong Park "Error response from slave",
48*54fd6939SJiyong Park "External timeout",
49*54fd6939SJiyong Park "Internal timeout",
50*54fd6939SJiyong Park "Deferred error from slave not supported at master"
51*54fd6939SJiyong Park };
52*54fd6939SJiyong Park
53*54fd6939SJiyong Park /*
54*54fd6939SJiyong Park * All other values are reserved. Reserved values might be defined
55*54fd6939SJiyong Park * in a future version of the architecture
56*54fd6939SJiyong Park */
57*54fd6939SJiyong Park if (serr >= ERROR_STATUS_NUM_SERR)
58*54fd6939SJiyong Park return "unknown SERR";
59*54fd6939SJiyong Park
60*54fd6939SJiyong Park return str[serr];
61*54fd6939SJiyong Park }
62*54fd6939SJiyong Park
63*54fd6939SJiyong Park /* Handler that receives External Aborts on RAS-capable systems */
ras_ea_handler(unsigned int ea_reason,uint64_t syndrome,void * cookie,void * handle,uint64_t flags)64*54fd6939SJiyong Park int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
65*54fd6939SJiyong Park void *handle, uint64_t flags)
66*54fd6939SJiyong Park {
67*54fd6939SJiyong Park unsigned int i, n_handled = 0;
68*54fd6939SJiyong Park int probe_data, ret;
69*54fd6939SJiyong Park struct err_record_info *info;
70*54fd6939SJiyong Park
71*54fd6939SJiyong Park const struct err_handler_data err_data = {
72*54fd6939SJiyong Park .version = ERR_HANDLER_VERSION,
73*54fd6939SJiyong Park .ea_reason = ea_reason,
74*54fd6939SJiyong Park .interrupt = 0,
75*54fd6939SJiyong Park .syndrome = (uint32_t) syndrome,
76*54fd6939SJiyong Park .flags = flags,
77*54fd6939SJiyong Park .cookie = cookie,
78*54fd6939SJiyong Park .handle = handle
79*54fd6939SJiyong Park };
80*54fd6939SJiyong Park
81*54fd6939SJiyong Park for_each_err_record_info(i, info) {
82*54fd6939SJiyong Park assert(info->probe != NULL);
83*54fd6939SJiyong Park assert(info->handler != NULL);
84*54fd6939SJiyong Park
85*54fd6939SJiyong Park /* Continue probing until the record group signals no error */
86*54fd6939SJiyong Park while (true) {
87*54fd6939SJiyong Park if (info->probe(info, &probe_data) == 0)
88*54fd6939SJiyong Park break;
89*54fd6939SJiyong Park
90*54fd6939SJiyong Park /* Handle error */
91*54fd6939SJiyong Park ret = info->handler(info, probe_data, &err_data);
92*54fd6939SJiyong Park if (ret != 0)
93*54fd6939SJiyong Park return ret;
94*54fd6939SJiyong Park
95*54fd6939SJiyong Park n_handled++;
96*54fd6939SJiyong Park }
97*54fd6939SJiyong Park }
98*54fd6939SJiyong Park
99*54fd6939SJiyong Park return (n_handled != 0U) ? 1 : 0;
100*54fd6939SJiyong Park }
101*54fd6939SJiyong Park
102*54fd6939SJiyong Park #if ENABLE_ASSERTIONS
assert_interrupts_sorted(void)103*54fd6939SJiyong Park static void assert_interrupts_sorted(void)
104*54fd6939SJiyong Park {
105*54fd6939SJiyong Park unsigned int i, last;
106*54fd6939SJiyong Park struct ras_interrupt *start = ras_interrupt_mappings.intrs;
107*54fd6939SJiyong Park
108*54fd6939SJiyong Park if (ras_interrupt_mappings.num_intrs == 0UL)
109*54fd6939SJiyong Park return;
110*54fd6939SJiyong Park
111*54fd6939SJiyong Park last = start[0].intr_number;
112*54fd6939SJiyong Park for (i = 1; i < ras_interrupt_mappings.num_intrs; i++) {
113*54fd6939SJiyong Park assert(start[i].intr_number > last);
114*54fd6939SJiyong Park last = start[i].intr_number;
115*54fd6939SJiyong Park }
116*54fd6939SJiyong Park }
117*54fd6939SJiyong Park #endif
118*54fd6939SJiyong Park
119*54fd6939SJiyong Park /*
120*54fd6939SJiyong Park * Given an RAS interrupt number, locate the registered handler and call it. If
121*54fd6939SJiyong Park * no handler was found for the interrupt number, this function panics.
122*54fd6939SJiyong Park */
ras_interrupt_handler(uint32_t intr_raw,uint32_t flags,void * handle,void * cookie)123*54fd6939SJiyong Park static int ras_interrupt_handler(uint32_t intr_raw, uint32_t flags,
124*54fd6939SJiyong Park void *handle, void *cookie)
125*54fd6939SJiyong Park {
126*54fd6939SJiyong Park struct ras_interrupt *ras_inrs = ras_interrupt_mappings.intrs;
127*54fd6939SJiyong Park struct ras_interrupt *selected = NULL;
128*54fd6939SJiyong Park int probe_data = 0;
129*54fd6939SJiyong Park int start, end, mid, ret __unused;
130*54fd6939SJiyong Park
131*54fd6939SJiyong Park const struct err_handler_data err_data = {
132*54fd6939SJiyong Park .version = ERR_HANDLER_VERSION,
133*54fd6939SJiyong Park .interrupt = intr_raw,
134*54fd6939SJiyong Park .flags = flags,
135*54fd6939SJiyong Park .cookie = cookie,
136*54fd6939SJiyong Park .handle = handle
137*54fd6939SJiyong Park };
138*54fd6939SJiyong Park
139*54fd6939SJiyong Park assert(ras_interrupt_mappings.num_intrs > 0UL);
140*54fd6939SJiyong Park
141*54fd6939SJiyong Park start = 0;
142*54fd6939SJiyong Park end = (int)ras_interrupt_mappings.num_intrs - 1;
143*54fd6939SJiyong Park while (start <= end) {
144*54fd6939SJiyong Park mid = ((end + start) / 2);
145*54fd6939SJiyong Park if (intr_raw == ras_inrs[mid].intr_number) {
146*54fd6939SJiyong Park selected = &ras_inrs[mid];
147*54fd6939SJiyong Park break;
148*54fd6939SJiyong Park } else if (intr_raw < ras_inrs[mid].intr_number) {
149*54fd6939SJiyong Park /* Move left */
150*54fd6939SJiyong Park end = mid - 1;
151*54fd6939SJiyong Park } else {
152*54fd6939SJiyong Park /* Move right */
153*54fd6939SJiyong Park start = mid + 1;
154*54fd6939SJiyong Park }
155*54fd6939SJiyong Park }
156*54fd6939SJiyong Park
157*54fd6939SJiyong Park if (selected == NULL) {
158*54fd6939SJiyong Park ERROR("RAS interrupt %u has no handler!\n", intr_raw);
159*54fd6939SJiyong Park panic();
160*54fd6939SJiyong Park }
161*54fd6939SJiyong Park
162*54fd6939SJiyong Park if (selected->err_record->probe != NULL) {
163*54fd6939SJiyong Park ret = selected->err_record->probe(selected->err_record, &probe_data);
164*54fd6939SJiyong Park assert(ret != 0);
165*54fd6939SJiyong Park }
166*54fd6939SJiyong Park
167*54fd6939SJiyong Park /* Call error handler for the record group */
168*54fd6939SJiyong Park assert(selected->err_record->handler != NULL);
169*54fd6939SJiyong Park (void) selected->err_record->handler(selected->err_record, probe_data,
170*54fd6939SJiyong Park &err_data);
171*54fd6939SJiyong Park
172*54fd6939SJiyong Park return 0;
173*54fd6939SJiyong Park }
174*54fd6939SJiyong Park
ras_init(void)175*54fd6939SJiyong Park void __init ras_init(void)
176*54fd6939SJiyong Park {
177*54fd6939SJiyong Park #if ENABLE_ASSERTIONS
178*54fd6939SJiyong Park /* Check RAS interrupts are sorted */
179*54fd6939SJiyong Park assert_interrupts_sorted();
180*54fd6939SJiyong Park #endif
181*54fd6939SJiyong Park
182*54fd6939SJiyong Park /* Register RAS priority handler */
183*54fd6939SJiyong Park ehf_register_priority_handler(PLAT_RAS_PRI, ras_interrupt_handler);
184*54fd6939SJiyong Park }
185