1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006 by Thom Johansen
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
26 #include "gcc_extensions.h"
29 #include <backtrace.h>
31 static const char* const uiename
[] = {
32 "Undefined instruction",
39 void __attribute__((weak
,naked
)) data_abort_handler(void)
48 void __attribute__((weak
,naked
)) software_int_handler(void)
57 void __attribute__((weak
,naked
)) reserved_handler(void)
66 void __attribute__((weak
,naked
)) prefetch_abort_handler(void)
75 void __attribute__((weak
,naked
)) undef_instr_handler(void)
81 "tst r1, #(1 << 5) \n" // T bit set ?
82 "subne r0, lr, #2 \n" // if yes, offset to THUMB instruction
89 /* Unexpected Interrupt or Exception handler. Currently only deals with
90 exceptions, but will deal with interrupts later.
92 void NORETURN_ATTR
UIE(unsigned int pc
, unsigned int num
)
94 /* safe guard variable - we call backtrace() only on first
95 * UIE call. This prevent endless loop if backtrace() touches
96 * memory regions which cause abort
98 static bool triggered
= false;
101 lcd_set_backdrop(NULL
);
102 lcd_set_drawmode(DRMODE_SOLID
);
103 lcd_set_foreground(LCD_BLACK
);
104 lcd_set_background(LCD_WHITE
);
108 lcd_setfont(FONT_SYSFIXED
);
109 lcd_set_viewport(NULL
);
111 lcd_putsf(0, line
++, "%s at %08x" IF_COP(" (%d)"), uiename
[num
], pc
IF_COP(, CURRENT_CORE
));
113 #if !defined(CPU_ARM7TDMI) && (CONFIG_CPU != RK27XX) /* arm7tdmi has no MPU/MMU */
114 if(num
== 1 || num
== 2) /* prefetch / data abort */
116 register unsigned status
;
119 /* ARMv6 has 2 different registers for prefetch & data aborts */
120 if(num
== 1) /* instruction prefetch abort */
121 asm volatile( "mrc p15, 0, %0, c5, c0, 1\n" : "=r"(status
));
124 asm volatile( "mrc p15, 0, %0, c5, c0, 0\n" : "=r"(status
));
126 lcd_putsf(0, line
++, "FSR 0x%x", status
);
128 unsigned int domain
= (status
>> 4) & 0xf;
129 unsigned int fault
= status
& 0xf;
131 fault
|= (status
& (1<<10)) >> 6; /* fault is 5 bits on armv6 */
133 lcd_putsf(0, line
++, "(domain %d, fault %d)", domain
, fault
);
135 if(num
== 2) /* data abort */
137 register unsigned address
;
138 /* read FAR (fault address register) */
139 asm volatile( "mrc p15, 0, %0, c6, c0\n" : "=r"(address
));
140 lcd_putsf(0, line
++, "address 0x%8x", address
);
142 lcd_putsf(0, line
++, (status
& (1<<11)) ? "(write)" : "(read)");
145 } /* num == 1 || num == 2 // prefetch/data abort */
146 #endif /* !defined(CPU_ARM7TDMI */
151 backtrace(pc
, __get_sp(), &line
);
156 disable_interrupt(IRQ_FIQ_STATUS
);
158 system_exception_wait(); /* If this returns, try to reboot */
160 while (1); /* halt */
163 /* Needs to be here or gcc won't find it */
164 void __attribute__((naked
)) __div0(void)
168 "sub r0, r0, #4 \r\n"