2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
4 * SPDX-License-Identifier: BSD-3-Clause
9 #include <arch_helpers.h>
10 #include <bl31/ea_handle.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>
18 # error Platform must define RAS priority value
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
)
25 unsigned int i
, n_handled
= 0;
27 struct err_record_info
*info
;
29 const struct err_handler_data err_data
= {
30 .version
= ERR_HANDLER_VERSION
,
31 .ea_reason
= ea_reason
,
33 .syndrome
= (uint32_t) syndrome
,
39 for_each_err_record_info(i
, info
) {
40 assert(info
->probe
!= NULL
);
41 assert(info
->handler
!= NULL
);
43 /* Continue probing until the record group signals no error */
45 if (info
->probe(info
, &probe_data
) == 0)
49 ret
= info
->handler(info
, probe_data
, &err_data
);
57 return (n_handled
!= 0U) ? 1 : 0;
61 static void assert_interrupts_sorted(void)
64 struct ras_interrupt
*start
= ras_interrupt_mappings
.intrs
;
66 if (ras_interrupt_mappings
.num_intrs
== 0UL)
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
;
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.
81 static int ras_interrupt_handler(uint32_t intr_raw
, uint32_t flags
,
82 void *handle
, void *cookie
)
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
;
88 const struct err_handler_data err_data
= {
89 .version
= ERR_HANDLER_VERSION
,
90 .interrupt
= intr_raw
,
96 assert(ras_interrupt_mappings
.num_intrs
> 0UL);
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
];
105 } else if (intr_raw
< ras_inrs
[mid
].intr_number
) {
114 if (selected
== NULL
) {
115 ERROR("RAS interrupt %u has no handler!\n", intr_raw
);
119 if (selected
->err_record
->probe
!= NULL
) {
120 ret
= selected
->err_record
->probe(selected
->err_record
, &probe_data
);
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
,
132 void __init
ras_init(void)
134 #if ENABLE_ASSERTIONS
135 /* Check RAS interrupts are sorted */
136 assert_interrupts_sorted();
139 /* Register RAS priority handler */
140 ehf_register_priority_handler(PLAT_RAS_PRI
, ras_interrupt_handler
);