sh: hwblk support for sh7723
[safe/jmp/linux-2.6] / arch / sh / kernel / traps_32.c
index f249758..2b77277 100644 (file)
@@ -13,6 +13,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
+#include <linux/hardirq.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/module.h>
 #include <asm/fpu.h>
 #include <asm/kprobes.h>
 
-#ifdef CONFIG_SH_KGDB
-#include <asm/kgdb.h>
-#define CHK_REMOTE_DEBUG(regs)                 \
-{                                              \
-       if (kgdb_debug_hook && !user_mode(regs))\
-               (*kgdb_debug_hook)(regs);       \
-}
-#else
-#define CHK_REMOTE_DEBUG(regs)
-#endif
-
 #ifdef CONFIG_CPU_SH2
 # define TRAP_RESERVED_INST    4
 # define TRAP_ILLEGAL_SLOT_INST        6
 # define TRAP_ADDRESS_ERROR    9
 # ifdef CONFIG_CPU_SH2A
+#  define TRAP_UBC             12
 #  define TRAP_FPU_ERROR       13
 #  define TRAP_DIVZERO_ERROR   17
 #  define TRAP_DIVOVF_ERROR    18
@@ -94,7 +85,6 @@ void die(const char * str, struct pt_regs * regs, long err)
 
        printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
 
-       CHK_REMOTE_DEBUG(regs);
        print_modules();
        show_regs(regs);
 
@@ -136,20 +126,18 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs,
  * - userspace errors just cause EFAULT to be returned, resulting in SEGV
  * - kernel/userspace interfaces cause a jump to an appropriate handler
  * - other kernel errors are bad
- * - return 0 if fixed-up, -EFAULT if non-fatal (to the kernel) fault
  */
-static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
+static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
 {
        if (!user_mode(regs)) {
                const struct exception_table_entry *fixup;
                fixup = search_exception_tables(regs->pc);
                if (fixup) {
                        regs->pc = fixup->fixup;
-                       return 0;
+                       return;
                }
                die(str, regs, err);
        }
-       return -EFAULT;
 }
 
 static inline void sign_extend(unsigned int count, unsigned char *dst)
@@ -189,7 +177,7 @@ static struct mem_access user_mem_access = {
  *   (if that instruction is in a branch delay slot)
  * - return 0 if emulation okay, -EFAULT on existential error
  */
-static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs,
+static int handle_unaligned_ins(insn_size_t instruction, struct pt_regs *regs,
                                struct mem_access *ma)
 {
        int ret, index, count;
@@ -325,7 +313,8 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs,
        /* Argh. Address not only misaligned but also non-existent.
         * Raise an EFAULT and see if it's trapped
         */
-       return die_if_no_fixup("Fault in unaligned fixup", regs, 0);
+       die_if_no_fixup("Fault in unaligned fixup", regs, 0);
+       return -EFAULT;
 }
 
 /*
@@ -333,10 +322,10 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs,
  * - fetches the instruction from PC+2
  */
 static inline int handle_delayslot(struct pt_regs *regs,
-                                  opcode_t old_instruction,
+                                  insn_size_t old_instruction,
                                   struct mem_access *ma)
 {
-       opcode_t instruction;
+       insn_size_t instruction;
        void __user *addr = (void __user *)(regs->pc +
                instruction_size(old_instruction));
 
@@ -376,7 +365,7 @@ static inline int handle_delayslot(struct pt_regs *regs,
 
 static int handle_unaligned_notify_count = 10;
 
-int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs,
+int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
                            struct mem_access *ma)
 {
        u_int rm;
@@ -534,7 +523,7 @@ asmlinkage void do_address_error(struct pt_regs *regs,
        unsigned long error_code = 0;
        mm_segment_t oldfs;
        siginfo_t info;
-       opcode_t instruction;
+       insn_size_t instruction;
        int tmp;
 
        /* Intentional ifdef */
@@ -676,6 +665,8 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
        if (is_dsp_inst(regs)) {
                /* Enable DSP mode, and restart instruction. */
                regs->sr |= SR_DSP;
+               /* Save DSP mode */
+               tsk->thread.dsp_status.status |= SR_DSP;
                return;
        }
 #endif
@@ -683,7 +674,6 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
        error_code = lookup_exception_vector();
 
        local_irq_enable();
-       CHK_REMOTE_DEBUG(regs);
        force_sig(SIGILL, tsk);
        die_if_no_fixup("reserved instruction", regs, error_code);
 }
@@ -761,7 +751,6 @@ asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
        inst = lookup_exception_vector();
 
        local_irq_enable();
-       CHK_REMOTE_DEBUG(regs);
        force_sig(SIGILL, tsk);
        die_if_no_fixup("illegal slot instruction", regs, inst);
 }
@@ -861,6 +850,10 @@ void __init trap_init(void)
 #endif
 #endif
 
+#ifdef TRAP_UBC
+       set_exception_table_vec(TRAP_UBC, break_point_trap);
+#endif
+
        /* Setup VBR for boot cpu */
        per_cpu_trap_init();
 }
@@ -873,10 +866,7 @@ void show_trace(struct task_struct *tsk, unsigned long *sp,
        if (regs && user_mode(regs))
                return;
 
-       printk("\nCall trace: ");
-#ifdef CONFIG_KALLSYMS
-       printk("\n");
-#endif
+       printk("\nCall trace:\n");
 
        while (!kstack_end(sp)) {
                addr = *sp++;