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