1 /* 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 15 #ifndef PLAT_RAS_PRI 16 # error Platform must define RAS priority value 17 #endif 18 19 /* Handler that receives External Aborts on RAS-capable systems */ 20 int 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, 30 .interrupt = 0, 31 .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 } 57 58 #if ENABLE_ASSERTIONS 59 static 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 */ 79 static 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 117 118 ret = selected->err_record->probe(selected->err_record, &probe_data); 119 assert(ret != 0); 120 121 /* Call error handler for the record group */ 122 assert(selected->err_record->handler != NULL); 123 selected->err_record->handler(selected->err_record, probe_data, 124 &err_data); 125 126 return 0; 127 } 128 129 void ras_init(void) 130 { 131 #if ENABLE_ASSERTIONS 132 /* Check RAS interrupts are sorted */ 133 assert_interrupts_sorted(); 134 #endif 135 136 /* Register RAS priority handler */ 137 ehf_register_priority_handler(PLAT_RAS_PRI, ras_interrupt_handler); 138 } 139