Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rkuo/linux...
[cascardo/linux.git] / arch / hexagon / kernel / traps.c
index cc2171b..7858663 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Kernel traps/events for Hexagon processor
  *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -65,6 +65,10 @@ static const char *ex_name(int ex)
                return "Write protection fault";
        case HVM_GE_C_XMAL:
                return "Misaligned instruction";
+       case HVM_GE_C_WREG:
+               return "Multiple writes to same register in packet";
+       case HVM_GE_C_PCAL:
+               return "Program counter values that are not properly aligned";
        case HVM_GE_C_RMAL:
                return "Misaligned data load";
        case HVM_GE_C_WMAL:
@@ -316,6 +320,12 @@ void do_genex(struct pt_regs *regs)
        case HVM_GE_C_XMAL:
                misaligned_instruction(regs);
                break;
+       case HVM_GE_C_WREG:
+               illegal_instruction(regs);
+               break;
+       case HVM_GE_C_PCAL:
+               misaligned_instruction(regs);
+               break;
        case HVM_GE_C_RMAL:
                misaligned_data_load(regs);
                break;
@@ -348,7 +358,6 @@ long sys_syscall(void)
 
 void do_trap0(struct pt_regs *regs)
 {
-       unsigned long syscallret = 0;
        syscall_fn syscall;
 
        switch (pt_cause(regs)) {
@@ -388,21 +397,11 @@ void do_trap0(struct pt_regs *regs)
                } else {
                        syscall = (syscall_fn)
                                  (sys_call_table[regs->syscall_nr]);
-                       syscallret = syscall(regs->r00, regs->r01,
+                       regs->r00 = syscall(regs->r00, regs->r01,
                                   regs->r02, regs->r03,
                                   regs->r04, regs->r05);
                }
 
-               /*
-                * If it was a sigreturn system call, don't overwrite
-                * r0 value in stack frame with return value.
-                *
-                * __NR_sigreturn doesn't seem to exist in new unistd.h
-                */
-
-               if (regs->syscall_nr != __NR_rt_sigreturn)
-                       regs->r00 = syscallret;
-
                /* allow strace to get the syscall return state  */
                if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE)))
                        tracehook_report_syscall_exit(regs, 0);
@@ -444,3 +443,14 @@ void do_machcheck(struct pt_regs *regs)
        /* Halt and catch fire */
        __vmstop();
 }
+
+/*
+ * Treat this like the old 0xdb trap.
+ */
+
+void do_debug_exception(struct pt_regs *regs)
+{
+       regs->hvmer.vmest &= ~HVM_VMEST_CAUSE_MSK;
+       regs->hvmer.vmest |= (TRAP_DEBUG << HVM_VMEST_CAUSE_SFT);
+       do_trap0(regs);
+}