1362599ecSJeenu Viswambharan /* 2*4c700c15SGovindraj Raja * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved. 38ca61538SDavid 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 228ca61538SDavid Pu /* 238ca61538SDavid Pu * Function to convert architecturally-defined primary error code SERR, 248ca61538SDavid Pu * bits[7:0] from ERR<n>STATUS to its corresponding error string. 258ca61538SDavid Pu */ 268ca61538SDavid Pu const char *ras_serr_to_str(unsigned int serr) 278ca61538SDavid Pu { 288ca61538SDavid Pu const char *str[ERROR_STATUS_NUM_SERR] = { 298ca61538SDavid Pu "No error", 308ca61538SDavid Pu "IMPLEMENTATION DEFINED error", 318ca61538SDavid Pu "Data value from (non-associative) internal memory", 328ca61538SDavid Pu "IMPLEMENTATION DEFINED pin", 338ca61538SDavid Pu "Assertion failure", 348ca61538SDavid Pu "Error detected on internal data path", 358ca61538SDavid Pu "Data value from associative memory", 368ca61538SDavid Pu "Address/control value from associative memory", 378ca61538SDavid Pu "Data value from a TLB", 388ca61538SDavid Pu "Address/control value from a TLB", 398ca61538SDavid Pu "Data value from producer", 408ca61538SDavid Pu "Address/control value from producer", 418ca61538SDavid Pu "Data value from (non-associative) external memory", 428ca61538SDavid Pu "Illegal address (software fault)", 438ca61538SDavid Pu "Illegal access (software fault)", 448ca61538SDavid Pu "Illegal state (software fault)", 458ca61538SDavid Pu "Internal data register", 468ca61538SDavid Pu "Internal control register", 478ca61538SDavid Pu "Error response from slave", 488ca61538SDavid Pu "External timeout", 498ca61538SDavid Pu "Internal timeout", 508ca61538SDavid Pu "Deferred error from slave not supported at master" 518ca61538SDavid Pu }; 528ca61538SDavid Pu 538ca61538SDavid Pu /* 548ca61538SDavid Pu * All other values are reserved. Reserved values might be defined 558ca61538SDavid Pu * in a future version of the architecture 568ca61538SDavid Pu */ 578ca61538SDavid Pu if (serr >= ERROR_STATUS_NUM_SERR) 588ca61538SDavid Pu return "unknown SERR"; 598ca61538SDavid Pu 608ca61538SDavid Pu return str[serr]; 618ca61538SDavid Pu } 628ca61538SDavid 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; 1420b1838a9SHeyi Guo end = (int)ras_interrupt_mappings.num_intrs - 1; 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