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