--- /dev/null
+/*
+ * arch/sh/kernel/debugtraps.S
+ *
+ * Debug trap jump tables for SuperH
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/sys.h>
+#include <linux/linkage.h>
+
+#if !defined(CONFIG_SH_KGDB)
+#define kgdb_handle_exception debug_trap_handler
+#endif
+
+#if !defined(CONFIG_SH_STANDARD_BIOS)
+#define sh_bios_handler debug_trap_handler
+#endif
+
+ .data
+
+ENTRY(debug_trap_table)
+ .long debug_trap_handler /* 0x30 */
+ .long debug_trap_handler /* 0x31 */
+ .long debug_trap_handler /* 0x32 */
+ .long debug_trap_handler /* 0x33 */
+ .long debug_trap_handler /* 0x34 */
+ .long debug_trap_handler /* 0x35 */
+ .long debug_trap_handler /* 0x36 */
+ .long debug_trap_handler /* 0x37 */
+ .long debug_trap_handler /* 0x38 */
+ .long debug_trap_handler /* 0x39 */
+ .long debug_trap_handler /* 0x3a */
+ .long debug_trap_handler /* 0x3b */
+ .long kgdb_handle_exception /* 0x3c */
+ .long debug_trap_handler /* 0x3d */
+ .long bug_trap_handler /* 0x3e */
+ .long sh_bios_handler /* 0x3f */
# define resume_kernel __restore_all
#endif
-#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
-! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
-! If both are configured, handle the debug traps (breakpoints) in SW,
-! but still allow BIOS traps to FW.
-
- .align 2
-debug_kernel:
-#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
- /* Force BIOS call to FW (debug_trap put TRA in r8) */
- mov r8,r0
- shlr2 r0
- cmp/eq #0x3f,r0
- bt debug_kernel_fw
-#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
-
-debug_enter:
-#if defined(CONFIG_SH_KGDB)
- /* Jump to kgdb, pass stacked regs as arg */
-debug_kernel_sw:
- mov.l 3f, r0
- jmp @r0
- mov r15, r4
- .align 2
-3: .long kgdb_handle_exception
-#endif /* CONFIG_SH_KGDB */
-#ifdef CONFIG_SH_STANDARD_BIOS
- bra debug_kernel_fw
- nop
-#endif
-#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
-
- .align 2
-debug_trap:
-#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
- mov r8, r0
- shlr2 r0
- cmp/eq #0x3f, r0 ! sh_bios() trap
- bf 1f
-#ifdef CONFIG_SH_KGDB
- cmp/eq #0xff, r0 ! XXX: KGDB trap, fix for SH-2.
- bf 1f
-#endif
- mov #OFF_SR, r0
- mov.l @(r0,r15), r0 ! get status register
- shll r0
- shll r0 ! kernel space?
- bt/s debug_kernel
-1:
-#endif
- mov.l @r15, r0 ! Restore R0 value
- mov.l 1f, r8
- jmp @r8
- nop
.align 2
ENTRY(exception_error)
!
#ifdef CONFIG_TRACE_IRQFLAGS
- mov.l 3f, r0
+ mov.l 2f, r0
jsr @r0
nop
#endif
sti
- mov.l 2f, r0
+ mov.l 1f, r0
jmp @r0
nop
-!
.align 2
-1: .long break_point_trap_software
-2: .long do_exception_error
+1: .long do_exception_error
#ifdef CONFIG_TRACE_IRQFLAGS
-3: .long trace_hardirqs_on
+2: .long trace_hardirqs_on
#endif
.align 2
.align 2
1: .long restore_all
- .align 2
-not_syscall_tra:
- bra debug_trap
- nop
-
.align 2
syscall_badsys: ! Bad syscall number
mov #-ENOSYS, r0
bra resume_userspace
mov.l r0, @(OFF_R0,r15) ! Return value
-
+
+/*
+ * The main debug trap handler.
+ *
+ * r8=TRA (not the trap number!)
+ *
+ * Note: This assumes that the trapa value is left in its original
+ * form (without the shlr2 shift) so the calculation for the jump
+ * call table offset remains a simple in place mask.
+ */
+debug_trap:
+ mov r8, r0
+ and #(0xf << 2), r0
+ mov.l 1f, r8
+ add r0, r8
+ mov.l @r8, r8
+ jmp @r8
+ nop
+
+ .align 2
+1: .long debug_trap_table
/*
* Syscall interface:
* Syscall #: R3
* Arguments #0 to #3: R4--R7
* Arguments #4 to #6: R0, R1, R2
- * TRA: (number of arguments + 0x10) x 4
+ * TRA: (number of arguments + ABI revision) x 4
*
* This code also handles delegating other traps to the BIOS/gdb stub
* according to:
*
* Trap number
- * (TRA>>2) Purpose
- * -------- -------
- * 0x0-0xf old syscall ABI
- * 0x10-0x1f new syscall ABI
- * 0x20-0xff delegated through debug_trap to BIOS/gdb stub.
+ * (TRA>>2) Purpose
+ * -------- -------
+ * 0x00-0x0f original SH-3/4 syscall ABI (not in general use).
+ * 0x10-0x1f general SH-3/4 syscall ABI.
+ * 0x20-0x2f syscall ABI for SH-2 parts.
+ * 0x30-0x3f debug traps used by the kernel.
+ * 0x40-0xff Not supported by all parts, so left unhandled.
*
* Note: When we're first called, the TRA value must be shifted
* right 2 bits in order to get the value that was used as the "trapa"
nop
.align 2
1: .long schedule_tail
- !
+
+/*
+ * The poorly named main trapa decode and dispatch routine, for
+ * system calls and debug traps through their respective jump tables.
+ */
ENTRY(system_call)
#if !defined(CONFIG_CPU_SH2)
mov.l 1f, r9
mov.l @r9, r8 ! Read from TRA (Trap Address) Register
#endif
- !
- ! Is the trap argument >= 0x20? (TRA will be >= 0x80)
- mov #0x7f, r9
+ /*
+ * Check the trap type
+ */
+ mov #((0x20 << 2) - 1), r9
cmp/hi r9, r8
- bt/s not_syscall_tra
+ bt/s debug_trap ! it's a debug trap..
mov #OFF_TRA, r9
add r15, r9
mov.l r8, @r9 ! set TRA value to tra
force_sig(SIGTRAP, current);
}
-asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7,
- struct pt_regs __regs)
+/*
+ * Generic trap handler.
+ */
+asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs __regs)
+{
+ struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+
+ /* Rewind */
+ regs->pc -= 2;
+
+ force_sig(SIGTRAP, current);
+}
+
+/*
+ * Special handler for BUG() traps.
+ */
+asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs __regs)
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);