1362599ecSJeenu Viswambharan /* 2dbff5263SJustin Chadwell * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. 3*8ca61538SDavid Pu * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. 4362599ecSJeenu Viswambharan * 5362599ecSJeenu Viswambharan * SPDX-License-Identifier: BSD-3-Clause 6362599ecSJeenu Viswambharan */ 7362599ecSJeenu Viswambharan 830a8d96eSJeenu Viswambharan #include <stdbool.h> 9362599ecSJeenu Viswambharan 1009d40e0eSAntonio Nino Diaz #include <arch_helpers.h> 1109d40e0eSAntonio Nino Diaz #include <bl31/ea_handle.h> 1209d40e0eSAntonio Nino Diaz #include <bl31/ehf.h> 1309d40e0eSAntonio Nino Diaz #include <common/debug.h> 1409d40e0eSAntonio Nino Diaz #include <lib/extensions/ras.h> 1509d40e0eSAntonio Nino Diaz #include <lib/extensions/ras_arch.h> 1609d40e0eSAntonio Nino Diaz #include <plat/common/platform.h> 1709d40e0eSAntonio Nino Diaz 18ca6d9185SJeenu Viswambharan #ifndef PLAT_RAS_PRI 19ca6d9185SJeenu Viswambharan # error Platform must define RAS priority value 20ca6d9185SJeenu Viswambharan #endif 21ca6d9185SJeenu Viswambharan 22*8ca61538SDavid Pu /* 23*8ca61538SDavid Pu * Function to convert architecturally-defined primary error code SERR, 24*8ca61538SDavid Pu * bits[7:0] from ERR<n>STATUS to its corresponding error string. 25*8ca61538SDavid Pu */ 26*8ca61538SDavid Pu const char *ras_serr_to_str(unsigned int serr) 27*8ca61538SDavid Pu { 28*8ca61538SDavid Pu const char *str[ERROR_STATUS_NUM_SERR] = { 29*8ca61538SDavid Pu "No error", 30*8ca61538SDavid Pu "IMPLEMENTATION DEFINED error", 31*8ca61538SDavid Pu "Data value from (non-associative) internal memory", 32*8ca61538SDavid Pu "IMPLEMENTATION DEFINED pin", 33*8ca61538SDavid Pu "Assertion failure", 34*8ca61538SDavid Pu "Error detected on internal data path", 35*8ca61538SDavid Pu "Data value from associative memory", 36*8ca61538SDavid Pu "Address/control value from associative memory", 37*8ca61538SDavid Pu "Data value from a TLB", 38*8ca61538SDavid Pu "Address/control value from a TLB", 39*8ca61538SDavid Pu "Data value from producer", 40*8ca61538SDavid Pu "Address/control value from producer", 41*8ca61538SDavid Pu "Data value from (non-associative) external memory", 42*8ca61538SDavid Pu "Illegal address (software fault)", 43*8ca61538SDavid Pu "Illegal access (software fault)", 44*8ca61538SDavid Pu "Illegal state (software fault)", 45*8ca61538SDavid Pu "Internal data register", 46*8ca61538SDavid Pu "Internal control register", 47*8ca61538SDavid Pu "Error response from slave", 48*8ca61538SDavid Pu "External timeout", 49*8ca61538SDavid Pu "Internal timeout", 50*8ca61538SDavid Pu "Deferred error from slave not supported at master" 51*8ca61538SDavid Pu }; 52*8ca61538SDavid Pu 53*8ca61538SDavid Pu /* 54*8ca61538SDavid Pu * All other values are reserved. Reserved values might be defined 55*8ca61538SDavid Pu * in a future version of the architecture 56*8ca61538SDavid Pu */ 57*8ca61538SDavid Pu if (serr >= ERROR_STATUS_NUM_SERR) 58*8ca61538SDavid Pu return "unknown SERR"; 59*8ca61538SDavid Pu 60*8ca61538SDavid Pu return str[serr]; 61*8ca61538SDavid Pu } 62*8ca61538SDavid Pu 63362599ecSJeenu Viswambharan /* Handler that receives External Aborts on RAS-capable systems */ 64362599ecSJeenu Viswambharan int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, 65362599ecSJeenu Viswambharan void *handle, uint64_t flags) 66362599ecSJeenu Viswambharan { 6730a8d96eSJeenu Viswambharan unsigned int i, n_handled = 0; 6830a8d96eSJeenu Viswambharan int probe_data, ret; 69362599ecSJeenu Viswambharan struct err_record_info *info; 70362599ecSJeenu Viswambharan 71362599ecSJeenu Viswambharan const struct err_handler_data err_data = { 72362599ecSJeenu Viswambharan .version = ERR_HANDLER_VERSION, 73362599ecSJeenu Viswambharan .ea_reason = ea_reason, 74ca6d9185SJeenu Viswambharan .interrupt = 0, 7530a8d96eSJeenu Viswambharan .syndrome = (uint32_t) syndrome, 76362599ecSJeenu Viswambharan .flags = flags, 77362599ecSJeenu Viswambharan .cookie = cookie, 78362599ecSJeenu Viswambharan .handle = handle 79362599ecSJeenu Viswambharan }; 80362599ecSJeenu Viswambharan 81362599ecSJeenu Viswambharan for_each_err_record_info(i, info) { 82362599ecSJeenu Viswambharan assert(info->probe != NULL); 83362599ecSJeenu Viswambharan assert(info->handler != NULL); 84362599ecSJeenu Viswambharan 85362599ecSJeenu Viswambharan /* Continue probing until the record group signals no error */ 8630a8d96eSJeenu Viswambharan while (true) { 87362599ecSJeenu Viswambharan if (info->probe(info, &probe_data) == 0) 88362599ecSJeenu Viswambharan break; 89362599ecSJeenu Viswambharan 90362599ecSJeenu Viswambharan /* Handle error */ 91362599ecSJeenu Viswambharan ret = info->handler(info, probe_data, &err_data); 92362599ecSJeenu Viswambharan if (ret != 0) 93362599ecSJeenu Viswambharan return ret; 94362599ecSJeenu Viswambharan 95362599ecSJeenu Viswambharan n_handled++; 96362599ecSJeenu Viswambharan } 97362599ecSJeenu Viswambharan } 98362599ecSJeenu Viswambharan 9930a8d96eSJeenu Viswambharan return (n_handled != 0U) ? 1 : 0; 100362599ecSJeenu Viswambharan } 101ca6d9185SJeenu Viswambharan 102ca6d9185SJeenu Viswambharan #if ENABLE_ASSERTIONS 103ca6d9185SJeenu Viswambharan static void assert_interrupts_sorted(void) 104ca6d9185SJeenu Viswambharan { 105ca6d9185SJeenu Viswambharan unsigned int i, last; 10630a8d96eSJeenu Viswambharan struct ras_interrupt *start = ras_interrupt_mappings.intrs; 107ca6d9185SJeenu Viswambharan 10830a8d96eSJeenu Viswambharan if (ras_interrupt_mappings.num_intrs == 0UL) 109ca6d9185SJeenu Viswambharan return; 110ca6d9185SJeenu Viswambharan 111ca6d9185SJeenu Viswambharan last = start[0].intr_number; 11230a8d96eSJeenu Viswambharan for (i = 1; i < ras_interrupt_mappings.num_intrs; i++) { 113ca6d9185SJeenu Viswambharan assert(start[i].intr_number > last); 114ca6d9185SJeenu Viswambharan last = start[i].intr_number; 115ca6d9185SJeenu Viswambharan } 116ca6d9185SJeenu Viswambharan } 117ca6d9185SJeenu Viswambharan #endif 118ca6d9185SJeenu Viswambharan 119ca6d9185SJeenu Viswambharan /* 120ca6d9185SJeenu Viswambharan * Given an RAS interrupt number, locate the registered handler and call it. If 121ca6d9185SJeenu Viswambharan * no handler was found for the interrupt number, this function panics. 122ca6d9185SJeenu Viswambharan */ 123ca6d9185SJeenu Viswambharan static int ras_interrupt_handler(uint32_t intr_raw, uint32_t flags, 124ca6d9185SJeenu Viswambharan void *handle, void *cookie) 125ca6d9185SJeenu Viswambharan { 12630a8d96eSJeenu Viswambharan struct ras_interrupt *ras_inrs = ras_interrupt_mappings.intrs; 127ca6d9185SJeenu Viswambharan struct ras_interrupt *selected = NULL; 128dbff5263SJustin Chadwell int probe_data = 0; 129dbff5263SJustin Chadwell int start, end, mid, ret __unused; 130ca6d9185SJeenu Viswambharan 131ca6d9185SJeenu Viswambharan const struct err_handler_data err_data = { 132ca6d9185SJeenu Viswambharan .version = ERR_HANDLER_VERSION, 133ca6d9185SJeenu Viswambharan .interrupt = intr_raw, 134ca6d9185SJeenu Viswambharan .flags = flags, 135ca6d9185SJeenu Viswambharan .cookie = cookie, 136ca6d9185SJeenu Viswambharan .handle = handle 137ca6d9185SJeenu Viswambharan }; 138ca6d9185SJeenu Viswambharan 13930a8d96eSJeenu Viswambharan assert(ras_interrupt_mappings.num_intrs > 0UL); 140ca6d9185SJeenu Viswambharan 141ca6d9185SJeenu Viswambharan start = 0; 14230a8d96eSJeenu Viswambharan end = (int) ras_interrupt_mappings.num_intrs; 143ca6d9185SJeenu Viswambharan while (start <= end) { 144ca6d9185SJeenu Viswambharan mid = ((end + start) / 2); 145ca6d9185SJeenu Viswambharan if (intr_raw == ras_inrs[mid].intr_number) { 146ca6d9185SJeenu Viswambharan selected = &ras_inrs[mid]; 147ca6d9185SJeenu Viswambharan break; 148ca6d9185SJeenu Viswambharan } else if (intr_raw < ras_inrs[mid].intr_number) { 149ca6d9185SJeenu Viswambharan /* Move left */ 150ca6d9185SJeenu Viswambharan end = mid - 1; 151ca6d9185SJeenu Viswambharan } else { 152ca6d9185SJeenu Viswambharan /* Move right */ 153ca6d9185SJeenu Viswambharan start = mid + 1; 154ca6d9185SJeenu Viswambharan } 155ca6d9185SJeenu Viswambharan } 156ca6d9185SJeenu Viswambharan 157ca6d9185SJeenu Viswambharan if (selected == NULL) { 158ca6d9185SJeenu Viswambharan ERROR("RAS interrupt %u has no handler!\n", intr_raw); 159ca6d9185SJeenu Viswambharan panic(); 160ca6d9185SJeenu Viswambharan } 161ca6d9185SJeenu Viswambharan 16230a8d96eSJeenu Viswambharan if (selected->err_record->probe != NULL) { 163ca6d9185SJeenu Viswambharan ret = selected->err_record->probe(selected->err_record, &probe_data); 164ca6d9185SJeenu Viswambharan assert(ret != 0); 1654576f73cSSughosh Ganu } 166ca6d9185SJeenu Viswambharan 167ca6d9185SJeenu Viswambharan /* Call error handler for the record group */ 168ca6d9185SJeenu Viswambharan assert(selected->err_record->handler != NULL); 16930a8d96eSJeenu Viswambharan (void) selected->err_record->handler(selected->err_record, probe_data, 170ca6d9185SJeenu Viswambharan &err_data); 171ca6d9185SJeenu Viswambharan 172ca6d9185SJeenu Viswambharan return 0; 173ca6d9185SJeenu Viswambharan } 174ca6d9185SJeenu Viswambharan 17587c85134SDaniel Boulby void __init ras_init(void) 176ca6d9185SJeenu Viswambharan { 177ca6d9185SJeenu Viswambharan #if ENABLE_ASSERTIONS 178ca6d9185SJeenu Viswambharan /* Check RAS interrupts are sorted */ 179ca6d9185SJeenu Viswambharan assert_interrupts_sorted(); 180ca6d9185SJeenu Viswambharan #endif 181ca6d9185SJeenu Viswambharan 182ca6d9185SJeenu Viswambharan /* Register RAS priority handler */ 183ca6d9185SJeenu Viswambharan ehf_register_priority_handler(PLAT_RAS_PRI, ras_interrupt_handler); 184ca6d9185SJeenu Viswambharan } 185