Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | /*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/arch/cpu.h>
#include <zephyr/kernel_structs.h>
#include <inttypes.h>
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
FUNC_NORETURN void z_nios2_fatal_error(unsigned int reason,
const struct arch_esf *esf)
{
#if CONFIG_EXCEPTION_DEBUG
if (esf != NULL) {
/* Subtract 4 from EA since we added 4 earlier so that the
* faulting instruction isn't retried.
*
* TODO: Only caller-saved registers get saved upon exception
* entry. We may want to introduce a config option to save and
* dump all registers, at the expense of some stack space.
*/
LOG_ERR("Faulting instruction: 0x%08x", esf->instr - 4);
LOG_ERR(" r1: 0x%08x r2: 0x%08x r3: 0x%08x r4: 0x%08x",
esf->r1, esf->r2, esf->r3, esf->r4);
LOG_ERR(" r5: 0x%08x r6: 0x%08x r7: 0x%08x r8: 0x%08x",
esf->r5, esf->r6, esf->r7, esf->r8);
LOG_ERR(" r9: 0x%08x r10: 0x%08x r11: 0x%08x r12: 0x%08x",
esf->r9, esf->r10, esf->r11, esf->r12);
LOG_ERR(" r13: 0x%08x r14: 0x%08x r15: 0x%08x ra: 0x%08x",
esf->r13, esf->r14, esf->r15, esf->ra);
LOG_ERR("estatus: %08x", esf->estatus);
}
#endif /* CONFIG_EXCEPTION_DEBUG */
z_fatal_error(reason, esf);
CODE_UNREACHABLE;
}
#if defined(CONFIG_EXTRA_EXCEPTION_INFO) && \
(defined(CONFIG_PRINTK) || defined(CONFIG_LOG)) \
&& defined(ALT_CPU_HAS_EXTRA_EXCEPTION_INFO)
static char *cause_str(uint32_t cause_code)
{
switch (cause_code) {
case 0:
return "reset";
case 1:
return "processor-only reset request";
case 2:
return "interrupt";
case 3:
return "trap";
case 4:
return "unimplemented instruction";
case 5:
return "illegal instruction";
case 6:
return "misaligned data address";
case 7:
return "misaligned destination address";
case 8:
return "division error";
case 9:
return "supervisor-only instruction address";
case 10:
return "supervisor-only instruction";
case 11:
return "supervisor-only data address";
case 12:
return "TLB miss";
case 13:
return "TLB permission violation (execute)";
case 14:
return "TLB permission violation (read)";
case 15:
return "TLB permission violation (write)";
case 16:
return "MPU region violation (instruction)";
case 17:
return "MPU region violation (data)";
case 18:
return "ECC TLB error";
case 19:
return "ECC fetch error (instruction)";
case 20:
return "ECC register file error";
case 21:
return "ECC data error";
case 22:
return "ECC data cache writeback error";
case 23:
return "bus instruction fetch error";
case 24:
return "bus data region violation";
default:
return "unknown";
}
}
#endif
FUNC_NORETURN void _Fault(const struct arch_esf *esf)
{
#if defined(CONFIG_PRINTK) || defined(CONFIG_LOG)
/* Unfortunately, completely unavailable on Nios II/e cores */
#ifdef ALT_CPU_HAS_EXTRA_EXCEPTION_INFO
uint32_t exc_reg, badaddr_reg, eccftl;
enum nios2_exception_cause cause;
exc_reg = z_nios2_creg_read(NIOS2_CR_EXCEPTION);
/* Bit 31 indicates potentially fatal ECC error */
eccftl = (exc_reg & NIOS2_EXCEPTION_REG_ECCFTL_MASK) != 0U;
/* Bits 2-6 contain the cause code */
cause = (exc_reg & NIOS2_EXCEPTION_REG_CAUSE_MASK)
>> NIOS2_EXCEPTION_REG_CAUSE_OFST;
LOG_ERR("Exception cause: %d ECCFTL: 0x%x", cause, eccftl);
#if CONFIG_EXTRA_EXCEPTION_INFO
LOG_ERR("reason: %s", cause_str(cause));
#endif
if (BIT(cause) & NIOS2_BADADDR_CAUSE_MASK) {
badaddr_reg = z_nios2_creg_read(NIOS2_CR_BADADDR);
LOG_ERR("Badaddr: 0x%x", badaddr_reg);
}
#endif /* ALT_CPU_HAS_EXTRA_EXCEPTION_INFO */
#endif /* CONFIG_PRINTK || CONFIG_LOG */
z_nios2_fatal_error(K_ERR_CPU_EXCEPTION, esf);
}
#ifdef ALT_CPU_HAS_DEBUG_STUB
FUNC_NORETURN void arch_system_halt(unsigned int reason)
{
ARG_UNUSED(reason);
z_nios2_break();
CODE_UNREACHABLE;
}
#endif
|