Skip to content

Commit 12f775f

Browse files
committed
arch: microblaze: Fault Management
Internal references: FWRIVERHD-4979 Signed-off-by: Alp Sayin <alpsayin@gmail.com>
1 parent b86408f commit 12f775f

File tree

1 file changed

+164
-0
lines changed

1 file changed

+164
-0
lines changed

arch/microblaze/core/fatal.c

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/*
2+
* Copyright (c) 2023 Advanced Micro Devices, Inc. (AMD)
3+
* Copyright (c) 2023 Alp Sayin <alpsayin@gmail.com>
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
9+
10+
#include <zephyr/init.h>
11+
#include <zephyr/kernel.h>
12+
#include <zephyr/logging/log.h>
13+
#include <zephyr/sys/printk.h>
14+
15+
#include <offsets_short.h>
16+
17+
/* Hardware includes. */
18+
#include "microblaze/mb_interface.h"
19+
#include "microblaze/microblaze_regs.h"
20+
21+
LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
22+
23+
/* The number of bytes a MicroBlaze instruction consumes. */
24+
#define MICROBLAZE_INSTRUCTION_SIZE 4
25+
26+
extern void _exception_handler_entry(void *exception_id);
27+
28+
/* Used by assembly routine _exception_handler_entry to store sp */
29+
void *stack_pointer_on_exception_entry;
30+
31+
FUNC_NORETURN void z_microblaze_fatal_error(unsigned int reason,
32+
const microblaze_register_dump_t *dump)
33+
{
34+
if (dump != NULL && IS_ENABLED(CONFIG_MICROBLAZE_DUMP_ON_EXCEPTION)) {
35+
printk("r1:\t0x%08x\t(sp)\n", dump->esf.r1);
36+
printk("r2:\t0x%08x\t(small data area)\n", dump->esf.r2);
37+
printk("r3:\t0x%x\t\t(retval 1)\n", dump->esf.r3);
38+
printk("r4:\t0x%x\t\t(retval 2)\n", dump->esf.r4);
39+
printk("r5:\t0x%x\t\t(arg1)\n", dump->esf.r5);
40+
printk("r6:\t0x%x\t\t(arg2)\n", dump->esf.r6);
41+
printk("r7:\t0x%x\t\t(arg3)\n", dump->esf.r7);
42+
printk("r8:\t0x%x\t\t(arg4)\n", dump->esf.r8);
43+
printk("r9:\t0x%x\t\t(arg5)\n", dump->esf.r9);
44+
printk("r10:\t0x%x\t\t(arg6)\n", dump->esf.r10);
45+
printk("r11:\t0x%08x\t(temp1)\n", dump->esf.r11);
46+
printk("r12:\t0x%08x\t(temp2)\n", dump->esf.r12);
47+
printk("r13:\t0x%08x\t(rw small data area)\n", dump->esf.r13);
48+
printk("r14:\t0x%08x\t(return from interrupt)\n", dump->esf.r14);
49+
printk("r15:\t0x%08x\t(return from subroutine)\n", dump->esf.r15);
50+
printk("r16:\t0x%08x\t(return from trap)\n", dump->esf.r16);
51+
printk("r17:\t0x%08x\t(return from exception)\n", dump->esf.r17);
52+
printk("r18:\t0x%08x\t(compiler/assembler temp)\n", dump->esf.r18);
53+
printk("r19:\t0x%08x\t(global offset table ptr)\n", dump->esf.r19);
54+
printk("r20:\t0x%x\n", dump->esf.r20);
55+
printk("r21:\t0x%x\n", dump->esf.r21);
56+
printk("r22:\t0x%x\n", dump->esf.r22);
57+
printk("r23:\t0x%x\n", dump->esf.r23);
58+
printk("r24:\t0x%x\n", dump->esf.r24);
59+
printk("r25:\t0x%x\n", dump->esf.r25);
60+
printk("r26:\t0x%x\n", dump->esf.r26);
61+
printk("r27:\t0x%x\n", dump->esf.r27);
62+
printk("r28:\t0x%x\n", dump->esf.r28);
63+
printk("r29:\t0x%x\n", dump->esf.r29);
64+
printk("r30:\t0x%x\n", dump->esf.r30);
65+
printk("r31:\t0x%x\n", dump->esf.r31);
66+
67+
printk("MSR:\t0x%08x\t(exc)\n", dump->esf.msr);
68+
#if defined(CONFIG_USE_HARDWARE_FLOAT_INSTR)
69+
printk("FSR:\t%08x\n", dump->esf.fsr);
70+
#endif
71+
printk("ESR:\t0x%08x\n", dump->esr);
72+
printk("EAR:\t0x%x\n", dump->ear);
73+
printk("EDR:\t0x%x\n", dump->edr);
74+
printk("PC:\t0x%x\n", dump->pc);
75+
}
76+
77+
/* This hack allows us to re-enable exceptions properly before continuing.
78+
* r15 is safe to use becaue this function is noreturn.
79+
*/
80+
__asm__ volatile("\tmfs r15, rpc\n"
81+
"\trted r15, 0x8\n"
82+
"\tnop\n");
83+
84+
printk("MSR:\t0x%08x\t(%s)\n", mfmsr(), __func__);
85+
86+
z_fatal_error(reason, &dump->esf);
87+
CODE_UNREACHABLE;
88+
}
89+
90+
static char *cause_str(uint32_t cause)
91+
{
92+
switch (cause) {
93+
case 0:
94+
return "stream exception";
95+
case 1:
96+
return "unaligned data access exception";
97+
case 2:
98+
return "illegal op-code exception";
99+
case 3:
100+
return "instruction bus error exception";
101+
case 4:
102+
return "data bus error exception";
103+
case 5:
104+
return "divide exception";
105+
case 6:
106+
return "floating point unit exception";
107+
case 7:
108+
return "privileged instruction exception";
109+
case 8:
110+
return "stack protection violation exception";
111+
case 9:
112+
return "data storage exception";
113+
case 10:
114+
return "instruction storage exception";
115+
case 11:
116+
return "data TLB miss exception";
117+
case 12:
118+
return "instruction TLB miss exception";
119+
default:
120+
return "unknown";
121+
}
122+
}
123+
124+
FUNC_NORETURN void _Fault(uint32_t esr, uint32_t ear, uint32_t edr)
125+
{
126+
static microblaze_register_dump_t microblaze_register_dump = {0};
127+
/* Log the simplest possible exception information before anything */
128+
uint32_t cause = (mfesr() & CAUSE_EXP_MASK) >> CAUSE_EXP_SHIFT;
129+
130+
LOG_ERR("");
131+
LOG_ERR("Cause: %d, %s", cause, cause_str(cause));
132+
133+
/* Fill an register dump structure with the MicroBlaze context as it
134+
* was immediately before the exception occurrence.
135+
*/
136+
137+
__ASSERT_NO_MSG(stack_pointer_on_exception_entry);
138+
z_arch_esf_t *sp_ptr = (z_arch_esf_t *)stack_pointer_on_exception_entry;
139+
140+
/* Obtain the values of registers that were stacked prior to this function
141+
* being called, and may have changed since they were stacked.
142+
*/
143+
microblaze_register_dump.esf = *sp_ptr;
144+
microblaze_register_dump.esf.r1 = ((uint32_t)sp_ptr) + sizeof(z_arch_esf_t);
145+
microblaze_register_dump.esr = esr;
146+
microblaze_register_dump.ear = ear;
147+
microblaze_register_dump.edr = edr;
148+
149+
/* Move the saved program counter back to the instruction that was executed
150+
* when the exception occurred. This is only valid for certain types of
151+
* exception.
152+
*/
153+
microblaze_register_dump.pc =
154+
microblaze_register_dump.esf.r17 - MICROBLAZE_INSTRUCTION_SIZE;
155+
156+
/* Also fill in a string that describes what type of exception this is.
157+
* The string uses the same ID names as defined in the MicroBlaze standard
158+
* library exception header files.
159+
*/
160+
microblaze_register_dump.exception_cause_str = cause_str(cause);
161+
162+
z_microblaze_fatal_error(K_ERR_CPU_EXCEPTION, &microblaze_register_dump);
163+
CODE_UNREACHABLE;
164+
}

0 commit comments

Comments
 (0)