blob: 36f9a95b661bac66ab6efc56754d358d22b7b1c0 [file] [log] [blame]
Jeenu Viswambharan2e2e8812017-12-08 15:38:21 +00001/*
Justin Chadwell72065ec2019-07-23 09:45:18 +01002 * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
David Pu70f65972019-03-18 15:14:49 -07003 * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
Jeenu Viswambharan2e2e8812017-12-08 15:38:21 +00004 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +01008#include <stdbool.h>
Jeenu Viswambharan2e2e8812017-12-08 15:38:21 +00009
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010#include <arch_helpers.h>
11#include <bl31/ea_handle.h>
12#include <bl31/ehf.h>
13#include <common/debug.h>
14#include <lib/extensions/ras.h>
15#include <lib/extensions/ras_arch.h>
16#include <plat/common/platform.h>
17
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +000018#ifndef PLAT_RAS_PRI
19# error Platform must define RAS priority value
20#endif
21
David Pu70f65972019-03-18 15:14:49 -070022/*
23 * Function to convert architecturally-defined primary error code SERR,
24 * bits[7:0] from ERR<n>STATUS to its corresponding error string.
25 */
26const char *ras_serr_to_str(unsigned int serr)
27{
28 const char *str[ERROR_STATUS_NUM_SERR] = {
29 "No error",
30 "IMPLEMENTATION DEFINED error",
31 "Data value from (non-associative) internal memory",
32 "IMPLEMENTATION DEFINED pin",
33 "Assertion failure",
34 "Error detected on internal data path",
35 "Data value from associative memory",
36 "Address/control value from associative memory",
37 "Data value from a TLB",
38 "Address/control value from a TLB",
39 "Data value from producer",
40 "Address/control value from producer",
41 "Data value from (non-associative) external memory",
42 "Illegal address (software fault)",
43 "Illegal access (software fault)",
44 "Illegal state (software fault)",
45 "Internal data register",
46 "Internal control register",
47 "Error response from slave",
48 "External timeout",
49 "Internal timeout",
50 "Deferred error from slave not supported at master"
51 };
52
53 /*
54 * All other values are reserved. Reserved values might be defined
55 * in a future version of the architecture
56 */
57 if (serr >= ERROR_STATUS_NUM_SERR)
58 return "unknown SERR";
59
60 return str[serr];
61}
62
Jeenu Viswambharan2e2e8812017-12-08 15:38:21 +000063/* Handler that receives External Aborts on RAS-capable systems */
64int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
65 void *handle, uint64_t flags)
66{
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010067 unsigned int i, n_handled = 0;
68 int probe_data, ret;
Jeenu Viswambharan2e2e8812017-12-08 15:38:21 +000069 struct err_record_info *info;
70
71 const struct err_handler_data err_data = {
72 .version = ERR_HANDLER_VERSION,
73 .ea_reason = ea_reason,
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +000074 .interrupt = 0,
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010075 .syndrome = (uint32_t) syndrome,
Jeenu Viswambharan2e2e8812017-12-08 15:38:21 +000076 .flags = flags,
77 .cookie = cookie,
78 .handle = handle
79 };
80
81 for_each_err_record_info(i, info) {
82 assert(info->probe != NULL);
83 assert(info->handler != NULL);
84
85 /* Continue probing until the record group signals no error */
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010086 while (true) {
Jeenu Viswambharan2e2e8812017-12-08 15:38:21 +000087 if (info->probe(info, &probe_data) == 0)
88 break;
89
90 /* Handle error */
91 ret = info->handler(info, probe_data, &err_data);
92 if (ret != 0)
93 return ret;
94
95 n_handled++;
96 }
97 }
98
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010099 return (n_handled != 0U) ? 1 : 0;
Jeenu Viswambharan2e2e8812017-12-08 15:38:21 +0000100}
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +0000101
102#if ENABLE_ASSERTIONS
103static void assert_interrupts_sorted(void)
104{
105 unsigned int i, last;
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +0100106 struct ras_interrupt *start = ras_interrupt_mappings.intrs;
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +0000107
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +0100108 if (ras_interrupt_mappings.num_intrs == 0UL)
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +0000109 return;
110
111 last = start[0].intr_number;
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +0100112 for (i = 1; i < ras_interrupt_mappings.num_intrs; i++) {
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +0000113 assert(start[i].intr_number > last);
114 last = start[i].intr_number;
115 }
116}
117#endif
118
119/*
120 * Given an RAS interrupt number, locate the registered handler and call it. If
121 * no handler was found for the interrupt number, this function panics.
122 */
123static int ras_interrupt_handler(uint32_t intr_raw, uint32_t flags,
124 void *handle, void *cookie)
125{
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +0100126 struct ras_interrupt *ras_inrs = ras_interrupt_mappings.intrs;
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +0000127 struct ras_interrupt *selected = NULL;
Justin Chadwell72065ec2019-07-23 09:45:18 +0100128 int probe_data = 0;
129 int start, end, mid, ret __unused;
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +0000130
131 const struct err_handler_data err_data = {
132 .version = ERR_HANDLER_VERSION,
133 .interrupt = intr_raw,
134 .flags = flags,
135 .cookie = cookie,
136 .handle = handle
137 };
138
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +0100139 assert(ras_interrupt_mappings.num_intrs > 0UL);
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +0000140
141 start = 0;
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +0100142 end = (int) ras_interrupt_mappings.num_intrs;
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +0000143 while (start <= end) {
144 mid = ((end + start) / 2);
145 if (intr_raw == ras_inrs[mid].intr_number) {
146 selected = &ras_inrs[mid];
147 break;
148 } else if (intr_raw < ras_inrs[mid].intr_number) {
149 /* Move left */
150 end = mid - 1;
151 } else {
152 /* Move right */
153 start = mid + 1;
154 }
155 }
156
157 if (selected == NULL) {
158 ERROR("RAS interrupt %u has no handler!\n", intr_raw);
159 panic();
160 }
161
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +0100162 if (selected->err_record->probe != NULL) {
Sughosh Ganud51f80f2018-05-12 11:02:31 +0530163 ret = selected->err_record->probe(selected->err_record, &probe_data);
164 assert(ret != 0);
165 }
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +0000166
167 /* Call error handler for the record group */
168 assert(selected->err_record->handler != NULL);
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +0100169 (void) selected->err_record->handler(selected->err_record, probe_data,
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +0000170 &err_data);
171
172 return 0;
173}
174
Daniel Boulby5753e492018-09-20 14:12:46 +0100175void __init ras_init(void)
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +0000176{
177#if ENABLE_ASSERTIONS
178 /* Check RAS interrupts are sorted */
179 assert_interrupts_sorted();
180#endif
181
182 /* Register RAS priority handler */
183 ehf_register_priority_handler(PLAT_RAS_PRI, ras_interrupt_handler);
184}