1 /* 2 * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <stdbool.h> 8 9 #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 17 #ifndef PLAT_RAS_PRI 18 # error Platform must define RAS priority value 19 #endif 20 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) 24 { 25 unsigned int i, n_handled = 0; 26 int probe_data, ret; 27 struct err_record_info *info; 28 29 const struct err_handler_data err_data = { 30 .version = ERR_HANDLER_VERSION, 31 .ea_reason = ea_reason, 32 .interrupt = 0, 33 .syndrome = (uint32_t) syndrome, 34 .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 */ 44 while (true) { 45 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 57 return (n_handled != 0U) ? 1 : 0; 58 } 59 60 #if ENABLE_ASSERTIONS 61 static void assert_interrupts_sorted(void) 62 { 63 unsigned int i, last; 64 struct ras_interrupt *start = ras_interrupt_mappings.intrs; 65 66 if (ras_interrupt_mappings.num_intrs == 0UL) 67 return; 68 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; 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 */ 81 static int ras_interrupt_handler(uint32_t intr_raw, uint32_t flags, 82 void *handle, void *cookie) 83 { 84 struct ras_interrupt *ras_inrs = ras_interrupt_mappings.intrs; 85 struct ras_interrupt *selected = NULL; 86 int probe_data = 0; 87 int start, end, mid, ret __unused; 88 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 97 assert(ras_interrupt_mappings.num_intrs > 0UL); 98 99 start = 0; 100 end = (int) ras_interrupt_mappings.num_intrs; 101 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 120 if (selected->err_record->probe != NULL) { 121 ret = selected->err_record->probe(selected->err_record, &probe_data); 122 assert(ret != 0); 123 } 124 125 /* Call error handler for the record group */ 126 assert(selected->err_record->handler != NULL); 127 (void) selected->err_record->handler(selected->err_record, probe_data, 128 &err_data); 129 130 return 0; 131 } 132 133 void __init ras_init(void) 134 { 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 } 143