blob: 64a48524b8a9b368fc99a17847688d72b5adda54 [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.
Jeenu Viswambharan2e2e8812017-12-08 15:38:21 +00003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +01007#include <stdbool.h>
Jeenu Viswambharan2e2e8812017-12-08 15:38:21 +00008
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00009#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
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +000017#ifndef PLAT_RAS_PRI
18# error Platform must define RAS priority value
19#endif
20
Jeenu Viswambharan2e2e8812017-12-08 15:38:21 +000021/* Handler that receives External Aborts on RAS-capable systems */
22int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
23 void *handle, uint64_t flags)
24{
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010025 unsigned int i, n_handled = 0;
26 int probe_data, ret;
Jeenu Viswambharan2e2e8812017-12-08 15:38:21 +000027 struct err_record_info *info;
28
29 const struct err_handler_data err_data = {
30 .version = ERR_HANDLER_VERSION,
31 .ea_reason = ea_reason,
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +000032 .interrupt = 0,
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010033 .syndrome = (uint32_t) syndrome,
Jeenu Viswambharan2e2e8812017-12-08 15:38:21 +000034 .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 */
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010044 while (true) {
Jeenu Viswambharan2e2e8812017-12-08 15:38:21 +000045 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
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010057 return (n_handled != 0U) ? 1 : 0;
Jeenu Viswambharan2e2e8812017-12-08 15:38:21 +000058}
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +000059
60#if ENABLE_ASSERTIONS
61static void assert_interrupts_sorted(void)
62{
63 unsigned int i, last;
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010064 struct ras_interrupt *start = ras_interrupt_mappings.intrs;
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +000065
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010066 if (ras_interrupt_mappings.num_intrs == 0UL)
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +000067 return;
68
69 last = start[0].intr_number;
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010070 for (i = 1; i < ras_interrupt_mappings.num_intrs; i++) {
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +000071 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 */
81static int ras_interrupt_handler(uint32_t intr_raw, uint32_t flags,
82 void *handle, void *cookie)
83{
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010084 struct ras_interrupt *ras_inrs = ras_interrupt_mappings.intrs;
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +000085 struct ras_interrupt *selected = NULL;
Justin Chadwell72065ec2019-07-23 09:45:18 +010086 int probe_data = 0;
87 int start, end, mid, ret __unused;
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +000088
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
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010097 assert(ras_interrupt_mappings.num_intrs > 0UL);
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +000098
99 start = 0;
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +0100100 end = (int) ras_interrupt_mappings.num_intrs;
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +0000101 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
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +0100120 if (selected->err_record->probe != NULL) {
Sughosh Ganud51f80f2018-05-12 11:02:31 +0530121 ret = selected->err_record->probe(selected->err_record, &probe_data);
122 assert(ret != 0);
123 }
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +0000124
125 /* Call error handler for the record group */
126 assert(selected->err_record->handler != NULL);
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +0100127 (void) selected->err_record->handler(selected->err_record, probe_data,
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +0000128 &err_data);
129
130 return 0;
131}
132
Daniel Boulby5753e492018-09-20 14:12:46 +0100133void __init ras_init(void)
Jeenu Viswambharand86cc5b2017-12-12 10:34:58 +0000134{
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}