123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- /*
- * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <stdbool.h>
- #include <arch_helpers.h>
- #include <bl31/ea_handle.h>
- #include <bl31/ehf.h>
- #include <common/debug.h>
- #include <lib/extensions/ras.h>
- #include <lib/extensions/ras_arch.h>
- #include <plat/common/platform.h>
- #ifndef PLAT_RAS_PRI
- # error Platform must define RAS priority value
- #endif
- /*
- * Function to convert architecturally-defined primary error code SERR,
- * bits[7:0] from ERR<n>STATUS to its corresponding error string.
- */
- const char *ras_serr_to_str(unsigned int serr)
- {
- const char *str[ERROR_STATUS_NUM_SERR] = {
- "No error",
- "IMPLEMENTATION DEFINED error",
- "Data value from (non-associative) internal memory",
- "IMPLEMENTATION DEFINED pin",
- "Assertion failure",
- "Error detected on internal data path",
- "Data value from associative memory",
- "Address/control value from associative memory",
- "Data value from a TLB",
- "Address/control value from a TLB",
- "Data value from producer",
- "Address/control value from producer",
- "Data value from (non-associative) external memory",
- "Illegal address (software fault)",
- "Illegal access (software fault)",
- "Illegal state (software fault)",
- "Internal data register",
- "Internal control register",
- "Error response from slave",
- "External timeout",
- "Internal timeout",
- "Deferred error from slave not supported at master"
- };
- /*
- * All other values are reserved. Reserved values might be defined
- * in a future version of the architecture
- */
- if (serr >= ERROR_STATUS_NUM_SERR)
- return "unknown SERR";
- return str[serr];
- }
- /* Handler that receives External Aborts on RAS-capable systems */
- int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
- void *handle, uint64_t flags)
- {
- unsigned int i, n_handled = 0;
- int probe_data, ret;
- struct err_record_info *info;
- const struct err_handler_data err_data = {
- .version = ERR_HANDLER_VERSION,
- .ea_reason = ea_reason,
- .interrupt = 0,
- .syndrome = (uint32_t) syndrome,
- .flags = flags,
- .cookie = cookie,
- .handle = handle
- };
- for_each_err_record_info(i, info) {
- assert(info->probe != NULL);
- assert(info->handler != NULL);
- /* Continue probing until the record group signals no error */
- while (true) {
- if (info->probe(info, &probe_data) == 0)
- break;
- /* Handle error */
- ret = info->handler(info, probe_data, &err_data);
- if (ret != 0)
- return ret;
- n_handled++;
- }
- }
- return (n_handled != 0U) ? 1 : 0;
- }
- #if ENABLE_ASSERTIONS
- static void assert_interrupts_sorted(void)
- {
- unsigned int i, last;
- struct ras_interrupt *start = ras_interrupt_mappings.intrs;
- if (ras_interrupt_mappings.num_intrs == 0UL)
- return;
- last = start[0].intr_number;
- for (i = 1; i < ras_interrupt_mappings.num_intrs; i++) {
- assert(start[i].intr_number > last);
- last = start[i].intr_number;
- }
- }
- #endif
- /*
- * Given an RAS interrupt number, locate the registered handler and call it. If
- * no handler was found for the interrupt number, this function panics.
- */
- static int ras_interrupt_handler(uint32_t intr_raw, uint32_t flags,
- void *handle, void *cookie)
- {
- struct ras_interrupt *ras_inrs = ras_interrupt_mappings.intrs;
- struct ras_interrupt *selected = NULL;
- int probe_data = 0;
- int start, end, mid, ret __unused;
- const struct err_handler_data err_data = {
- .version = ERR_HANDLER_VERSION,
- .interrupt = intr_raw,
- .flags = flags,
- .cookie = cookie,
- .handle = handle
- };
- assert(ras_interrupt_mappings.num_intrs > 0UL);
- start = 0;
- end = (int)ras_interrupt_mappings.num_intrs - 1;
- while (start <= end) {
- mid = ((end + start) / 2);
- if (intr_raw == ras_inrs[mid].intr_number) {
- selected = &ras_inrs[mid];
- break;
- } else if (intr_raw < ras_inrs[mid].intr_number) {
- /* Move left */
- end = mid - 1;
- } else {
- /* Move right */
- start = mid + 1;
- }
- }
- if (selected == NULL) {
- ERROR("RAS interrupt %u has no handler!\n", intr_raw);
- panic();
- }
- if (selected->err_record->probe != NULL) {
- ret = selected->err_record->probe(selected->err_record, &probe_data);
- assert(ret != 0);
- }
- /* Call error handler for the record group */
- assert(selected->err_record->handler != NULL);
- (void) selected->err_record->handler(selected->err_record, probe_data,
- &err_data);
- return 0;
- }
- void __init ras_init(void)
- {
- #if ENABLE_ASSERTIONS
- /* Check RAS interrupts are sorted */
- assert_interrupts_sorted();
- #endif
- /* Register RAS priority handler */
- ehf_register_priority_handler(PLAT_RAS_PRI, ras_interrupt_handler);
- }
|