1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. 4*91f16700Schasinglulu * 5*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu #include <stdbool.h> 9*91f16700Schasinglulu 10*91f16700Schasinglulu #include <arch_helpers.h> 11*91f16700Schasinglulu #include <bl31/ea_handle.h> 12*91f16700Schasinglulu #include <bl31/ehf.h> 13*91f16700Schasinglulu #include <common/debug.h> 14*91f16700Schasinglulu #include <lib/extensions/ras.h> 15*91f16700Schasinglulu #include <lib/extensions/ras_arch.h> 16*91f16700Schasinglulu #include <plat/common/platform.h> 17*91f16700Schasinglulu 18*91f16700Schasinglulu #ifndef PLAT_RAS_PRI 19*91f16700Schasinglulu # error Platform must define RAS priority value 20*91f16700Schasinglulu #endif 21*91f16700Schasinglulu 22*91f16700Schasinglulu /* 23*91f16700Schasinglulu * Function to convert architecturally-defined primary error code SERR, 24*91f16700Schasinglulu * bits[7:0] from ERR<n>STATUS to its corresponding error string. 25*91f16700Schasinglulu */ 26*91f16700Schasinglulu const char *ras_serr_to_str(unsigned int serr) 27*91f16700Schasinglulu { 28*91f16700Schasinglulu const char *str[ERROR_STATUS_NUM_SERR] = { 29*91f16700Schasinglulu "No error", 30*91f16700Schasinglulu "IMPLEMENTATION DEFINED error", 31*91f16700Schasinglulu "Data value from (non-associative) internal memory", 32*91f16700Schasinglulu "IMPLEMENTATION DEFINED pin", 33*91f16700Schasinglulu "Assertion failure", 34*91f16700Schasinglulu "Error detected on internal data path", 35*91f16700Schasinglulu "Data value from associative memory", 36*91f16700Schasinglulu "Address/control value from associative memory", 37*91f16700Schasinglulu "Data value from a TLB", 38*91f16700Schasinglulu "Address/control value from a TLB", 39*91f16700Schasinglulu "Data value from producer", 40*91f16700Schasinglulu "Address/control value from producer", 41*91f16700Schasinglulu "Data value from (non-associative) external memory", 42*91f16700Schasinglulu "Illegal address (software fault)", 43*91f16700Schasinglulu "Illegal access (software fault)", 44*91f16700Schasinglulu "Illegal state (software fault)", 45*91f16700Schasinglulu "Internal data register", 46*91f16700Schasinglulu "Internal control register", 47*91f16700Schasinglulu "Error response from slave", 48*91f16700Schasinglulu "External timeout", 49*91f16700Schasinglulu "Internal timeout", 50*91f16700Schasinglulu "Deferred error from slave not supported at master" 51*91f16700Schasinglulu }; 52*91f16700Schasinglulu 53*91f16700Schasinglulu /* 54*91f16700Schasinglulu * All other values are reserved. Reserved values might be defined 55*91f16700Schasinglulu * in a future version of the architecture 56*91f16700Schasinglulu */ 57*91f16700Schasinglulu if (serr >= ERROR_STATUS_NUM_SERR) 58*91f16700Schasinglulu return "unknown SERR"; 59*91f16700Schasinglulu 60*91f16700Schasinglulu return str[serr]; 61*91f16700Schasinglulu } 62*91f16700Schasinglulu 63*91f16700Schasinglulu /* Handler that receives External Aborts on RAS-capable systems */ 64*91f16700Schasinglulu int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, 65*91f16700Schasinglulu void *handle, uint64_t flags) 66*91f16700Schasinglulu { 67*91f16700Schasinglulu unsigned int i, n_handled = 0; 68*91f16700Schasinglulu int probe_data, ret; 69*91f16700Schasinglulu struct err_record_info *info; 70*91f16700Schasinglulu 71*91f16700Schasinglulu const struct err_handler_data err_data = { 72*91f16700Schasinglulu .version = ERR_HANDLER_VERSION, 73*91f16700Schasinglulu .ea_reason = ea_reason, 74*91f16700Schasinglulu .interrupt = 0, 75*91f16700Schasinglulu .syndrome = (uint32_t) syndrome, 76*91f16700Schasinglulu .flags = flags, 77*91f16700Schasinglulu .cookie = cookie, 78*91f16700Schasinglulu .handle = handle 79*91f16700Schasinglulu }; 80*91f16700Schasinglulu 81*91f16700Schasinglulu for_each_err_record_info(i, info) { 82*91f16700Schasinglulu assert(info->probe != NULL); 83*91f16700Schasinglulu assert(info->handler != NULL); 84*91f16700Schasinglulu 85*91f16700Schasinglulu /* Continue probing until the record group signals no error */ 86*91f16700Schasinglulu while (true) { 87*91f16700Schasinglulu if (info->probe(info, &probe_data) == 0) 88*91f16700Schasinglulu break; 89*91f16700Schasinglulu 90*91f16700Schasinglulu /* Handle error */ 91*91f16700Schasinglulu ret = info->handler(info, probe_data, &err_data); 92*91f16700Schasinglulu if (ret != 0) 93*91f16700Schasinglulu return ret; 94*91f16700Schasinglulu 95*91f16700Schasinglulu n_handled++; 96*91f16700Schasinglulu } 97*91f16700Schasinglulu } 98*91f16700Schasinglulu 99*91f16700Schasinglulu return (n_handled != 0U) ? 1 : 0; 100*91f16700Schasinglulu } 101*91f16700Schasinglulu 102*91f16700Schasinglulu #if ENABLE_ASSERTIONS 103*91f16700Schasinglulu static void assert_interrupts_sorted(void) 104*91f16700Schasinglulu { 105*91f16700Schasinglulu unsigned int i, last; 106*91f16700Schasinglulu struct ras_interrupt *start = ras_interrupt_mappings.intrs; 107*91f16700Schasinglulu 108*91f16700Schasinglulu if (ras_interrupt_mappings.num_intrs == 0UL) 109*91f16700Schasinglulu return; 110*91f16700Schasinglulu 111*91f16700Schasinglulu last = start[0].intr_number; 112*91f16700Schasinglulu for (i = 1; i < ras_interrupt_mappings.num_intrs; i++) { 113*91f16700Schasinglulu assert(start[i].intr_number > last); 114*91f16700Schasinglulu last = start[i].intr_number; 115*91f16700Schasinglulu } 116*91f16700Schasinglulu } 117*91f16700Schasinglulu #endif 118*91f16700Schasinglulu 119*91f16700Schasinglulu /* 120*91f16700Schasinglulu * Given an RAS interrupt number, locate the registered handler and call it. If 121*91f16700Schasinglulu * no handler was found for the interrupt number, this function panics. 122*91f16700Schasinglulu */ 123*91f16700Schasinglulu static int ras_interrupt_handler(uint32_t intr_raw, uint32_t flags, 124*91f16700Schasinglulu void *handle, void *cookie) 125*91f16700Schasinglulu { 126*91f16700Schasinglulu struct ras_interrupt *ras_inrs = ras_interrupt_mappings.intrs; 127*91f16700Schasinglulu struct ras_interrupt *selected = NULL; 128*91f16700Schasinglulu int probe_data = 0; 129*91f16700Schasinglulu int start, end, mid, ret __unused; 130*91f16700Schasinglulu 131*91f16700Schasinglulu const struct err_handler_data err_data = { 132*91f16700Schasinglulu .version = ERR_HANDLER_VERSION, 133*91f16700Schasinglulu .interrupt = intr_raw, 134*91f16700Schasinglulu .flags = flags, 135*91f16700Schasinglulu .cookie = cookie, 136*91f16700Schasinglulu .handle = handle 137*91f16700Schasinglulu }; 138*91f16700Schasinglulu 139*91f16700Schasinglulu assert(ras_interrupt_mappings.num_intrs > 0UL); 140*91f16700Schasinglulu 141*91f16700Schasinglulu start = 0; 142*91f16700Schasinglulu end = (int)ras_interrupt_mappings.num_intrs - 1; 143*91f16700Schasinglulu while (start <= end) { 144*91f16700Schasinglulu mid = ((end + start) / 2); 145*91f16700Schasinglulu if (intr_raw == ras_inrs[mid].intr_number) { 146*91f16700Schasinglulu selected = &ras_inrs[mid]; 147*91f16700Schasinglulu break; 148*91f16700Schasinglulu } else if (intr_raw < ras_inrs[mid].intr_number) { 149*91f16700Schasinglulu /* Move left */ 150*91f16700Schasinglulu end = mid - 1; 151*91f16700Schasinglulu } else { 152*91f16700Schasinglulu /* Move right */ 153*91f16700Schasinglulu start = mid + 1; 154*91f16700Schasinglulu } 155*91f16700Schasinglulu } 156*91f16700Schasinglulu 157*91f16700Schasinglulu if (selected == NULL) { 158*91f16700Schasinglulu ERROR("RAS interrupt %u has no handler!\n", intr_raw); 159*91f16700Schasinglulu panic(); 160*91f16700Schasinglulu } 161*91f16700Schasinglulu 162*91f16700Schasinglulu if (selected->err_record->probe != NULL) { 163*91f16700Schasinglulu ret = selected->err_record->probe(selected->err_record, &probe_data); 164*91f16700Schasinglulu assert(ret != 0); 165*91f16700Schasinglulu } 166*91f16700Schasinglulu 167*91f16700Schasinglulu /* Call error handler for the record group */ 168*91f16700Schasinglulu assert(selected->err_record->handler != NULL); 169*91f16700Schasinglulu (void) selected->err_record->handler(selected->err_record, probe_data, 170*91f16700Schasinglulu &err_data); 171*91f16700Schasinglulu 172*91f16700Schasinglulu return 0; 173*91f16700Schasinglulu } 174*91f16700Schasinglulu 175*91f16700Schasinglulu void __init ras_init(void) 176*91f16700Schasinglulu { 177*91f16700Schasinglulu #if ENABLE_ASSERTIONS 178*91f16700Schasinglulu /* Check RAS interrupts are sorted */ 179*91f16700Schasinglulu assert_interrupts_sorted(); 180*91f16700Schasinglulu #endif 181*91f16700Schasinglulu 182*91f16700Schasinglulu /* Register RAS priority handler */ 183*91f16700Schasinglulu ehf_register_priority_handler(PLAT_RAS_PRI, ras_interrupt_handler); 184*91f16700Schasinglulu } 185