powerpc: Merge traps.c a bit more
authorPaul Mackerras <paulus@samba.org>
Thu, 6 Oct 2005 03:27:05 +0000 (13:27 +1000)
committerPaul Mackerras <paulus@samba.org>
Thu, 6 Oct 2005 03:27:05 +0000 (13:27 +1000)
This reduces the differences between ppc32 and ppc64 in
arch/powerpc/kernel/traps.c a bit further.

Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/kernel/head.S
arch/powerpc/kernel/traps.c

index 276793e05fd085797bdf021e2821e06d21fffecb..d9dbbd426744af01579f589f7aadd55f714df47a 100644 (file)
@@ -416,7 +416,7 @@ FPUnavailable:
        EXCEPTION_PROLOG
        bne     load_up_fpu             /* if from user, just load it up */
        addi    r3,r1,STACK_FRAME_OVERHEAD
-       EXC_XFER_EE_LITE(0x800, KernelFP)
+       EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception)
 
 /* Decrementer */
        EXCEPTION(0x900, Decrementer, timer_interrupt, EXC_XFER_LITE)
index 37b961f1e279d23ba0196f96bd548df79e9f2904..a2e4ad3f5a75eb26b0bd777ba0e6e80dec313d6b 100644 (file)
 #include <linux/mm.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
+#include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/prctl.h>
 #include <linux/delay.h>
 #include <linux/kprobes.h>
 #include <asm/kdebug.h>
-#ifdef CONFIG_PPC32
-#include <linux/ptrace.h>
-#include <linux/prctl.h>
-#endif
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/pmc.h>
 #endif
 
-#ifdef CONFIG_PPC64
-#define __KPROBES      __kprobes
-#else
-#define __KPROBES
-#endif
-
 #ifdef CONFIG_DEBUGGER
 int (*__debugger)(struct pt_regs *regs);
 int (*__debugger_ipi)(struct pt_regs *regs);
@@ -111,7 +103,7 @@ int die(const char *str, struct pt_regs *regs, long err)
        console_verbose();
        spin_lock_irq(&die_lock);
        bust_spinlocks(1);
-#if defined(CONFIG_PPC32) && defined(CONFIG_PMAC_BACKLIGHT)
+#ifdef CONFIG_PMAC_BACKLIGHT
        if (_machine == _MACH_Pmac) {
                set_backlight_enable(1);
                set_backlight_level(BACKLIGHT_MAX);
@@ -175,11 +167,7 @@ int die(const char *str, struct pt_regs *regs, long err)
 #endif
                panic("Fatal exception");
        }
-#ifdef CONFIG_PPC32
        do_exit(err);
-#else
-       do_exit(SIGSEGV);
-#endif
 
        return 0;
 }
@@ -199,7 +187,6 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
        info.si_addr = (void __user *) addr;
        force_sig_info(signr, &info, current);
 
-#ifdef CONFIG_PPC32
        /*
         * Init gets no signals that it doesn't have a handler for.
         * That's all very well, but if it has caused a synchronous
@@ -221,7 +208,6 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
                        do_exit(signr);
                }
        }
-#endif
 }
 
 #ifdef CONFIG_PPC64
@@ -231,7 +217,7 @@ void system_reset_exception(struct pt_regs *regs)
        if (ppc_md.system_reset_exception)
                ppc_md.system_reset_exception(regs);
 
-       die("System Reset", regs, 0);
+       die("System Reset", regs, SIGABRT);
 
        /* Must die if the interrupt is not recoverable */
        if (!(regs->msr & MSR_RI))
@@ -241,7 +227,6 @@ void system_reset_exception(struct pt_regs *regs)
 }
 #endif
 
-#ifdef CONFIG_PPC32
 /*
  * I/O accesses can cause machine checks on powermacs.
  * Check if the NIP corresponds to the address of a sync
@@ -290,7 +275,6 @@ static inline int check_io_access(struct pt_regs *regs)
 #endif /* CONFIG_PPC_PMAC */
        return 0;
 }
-#endif /* CONFIG_PPC32 */
 
 #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
 
@@ -326,7 +310,6 @@ static inline int check_io_access(struct pt_regs *regs)
 #define clear_single_step(regs)        ((regs)->msr &= ~MSR_SE)
 #endif
 
-#ifdef CONFIG_PPC32
 /*
  * This is "fall-back" implementation for configurations
  * which don't provide platform-specific machine check info
@@ -335,7 +318,6 @@ void __attribute__ ((weak))
 platform_machine_check(struct pt_regs *regs)
 {
 }
-#endif
 
 void machine_check_exception(struct pt_regs *regs)
 {
@@ -497,13 +479,7 @@ void machine_check_exception(struct pt_regs *regs)
 
        if (debugger_fault_handler(regs))
                return;
-       die("Machine check", regs,
-#ifdef CONFIG_PPC32
-               SIGBUS
-#else
-               0
-#endif
-       );
+       die("Machine check", regs, SIGBUS);
 
        /* Must die if the interrupt is not recoverable */
        if (!(regs->msr & MSR_RI))
@@ -542,13 +518,9 @@ void RunModeException(struct pt_regs *regs)
 }
 #endif
 
-void __KPROBES single_step_exception(struct pt_regs *regs)
+void __kprobes single_step_exception(struct pt_regs *regs)
 {
-#ifdef CONFIG_PPC32
        regs->msr &= ~(MSR_SE | MSR_BE);  /* Turn off 'trace' bits */
-#else
-       regs->msr &= ~MSR_SE;  /* Turn off 'trace' bit */
-#endif
 
        if (notify_die(DIE_SSTEP, "single_step", regs, 5,
                                        5, SIGTRAP) == NOTIFY_STOP)
@@ -565,15 +537,12 @@ void __KPROBES single_step_exception(struct pt_regs *regs)
  * pretend we got a single-step exception.  This was pointed out
  * by Kumar Gala.  -- paulus
  */
-static inline void emulate_single_step(struct pt_regs *regs)
+static void emulate_single_step(struct pt_regs *regs)
 {
        if (single_stepping(regs)) {
-#ifdef CONFIG_PPC32
                clear_single_step(regs);
                _exception(SIGTRAP, regs, TRAP_TRACE, 0);
-#else
                single_step_exception(regs);
-#endif
        }
 }
 
@@ -582,17 +551,7 @@ static void parse_fpe(struct pt_regs *regs)
        int code = 0;
        unsigned long fpscr;
 
-#ifdef CONFIG_PPC32
-       /* We must make sure the FP state is consistent with
-        * our MSR_FP in regs
-        */
-       preempt_disable();
-       if (regs->msr & MSR_FP)
-               giveup_fpu(current);
-       preempt_enable();
-#else
        flush_fp_to_thread(current);
-#endif
 
        fpscr = current->thread.fpscr;
 
@@ -737,19 +696,8 @@ static int emulate_instruction(struct pt_regs *regs)
        }
 
        /* Emulating the dcba insn is just a no-op.  */
-       if ((instword & INST_DCBA_MASK) == INST_DCBA) {
-#ifdef CONFIG_PPC64
-               static int warned;
-
-               if (!warned) {
-                       printk(KERN_WARNING
-                              "process %d (%s) uses obsolete 'dcba' insn\n",
-                              current->pid, current->comm);
-                       warned = 1;
-               }
-#endif /* CONFIG_PPC64 */
+       if ((instword & INST_DCBA_MASK) == INST_DCBA)
                return 0;
-       }
 
        /* Emulate the mcrxr insn.  */
        if ((instword & INST_MCRXR_MASK) == INST_MCRXR) {
@@ -817,7 +765,7 @@ static int check_bug_trap(struct pt_regs *regs)
                return 0;
        if (bug->line & BUG_WARNING_TRAP) {
                /* this is a WARN_ON rather than BUG/BUG_ON */
-#if defined(CONFIG_PPC32) && defined(CONFIG_XMON)
+#ifdef CONFIG_XMON
                xmon_printf(KERN_ERR "Badness in %s at %s:%d\n",
                       bug->function, bug->file,
                       bug->line & ~BUG_WARNING_TRAP);
@@ -843,12 +791,12 @@ static int check_bug_trap(struct pt_regs *regs)
        return 0;
 }
 
-void __KPROBES program_check_exception(struct pt_regs *regs)
+void __kprobes program_check_exception(struct pt_regs *regs)
 {
        unsigned int reason = get_reason(regs);
-#if defined(CONFIG_PPC32) && defined(CONFIG_MATH_EMULATION)
        extern int do_mathemu(struct pt_regs *regs);
 
+#ifdef CONFIG_MATH_EMULATION
        /* (reason & REASON_ILLEGAL) would be the obvious thing here,
         * but there seems to be a hardware bug on the 405GP (RevD)
         * that means ESR is sometimes set incorrectly - either to
@@ -860,58 +808,45 @@ void __KPROBES program_check_exception(struct pt_regs *regs)
                emulate_single_step(regs);
                return;
        }
-#endif
-
-#ifdef CONFIG_PPC64
-       if (debugger_fault_handler(regs))
-               return;
-#endif
+#endif /* CONFIG_MATH_EMULATION */
 
        if (reason & REASON_FP) {
                /* IEEE FP exception */
                parse_fpe(regs);
-       } else if (reason & REASON_TRAP) {
+               return;
+       }
+       if (reason & REASON_TRAP) {
                /* trap exception */
-#ifdef CONFIG_PPC64
                if (notify_die(DIE_BPT, "breakpoint", regs, 5, 5, SIGTRAP)
                                == NOTIFY_STOP)
                        return;
-#endif
                if (debugger_bpt(regs))
                        return;
                if (check_bug_trap(regs)) {
                        regs->nip += 4;
                        return;
                }
-               _exception(SIGTRAP, regs, TRAP_BRKPT,
-#ifdef CONFIG_PPC32
-                       0
-#else
-                       regs->nip
-#endif
-               );
-       } else
-#ifdef CONFIG_PPC32
-       if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED))
-#endif
-       {
-               /* Privileged or illegal instruction; try to emulate it. */
+               _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
+               return;
+       }
+
+       /* Try to emulate it if we should. */
+       if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) {
                switch (emulate_instruction(regs)) {
                case 0:
                        regs->nip += 4;
                        emulate_single_step(regs);
-                       break;
+                       return;
                case -EFAULT:
                        _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
-                       break;
-               default:
-                       if (reason & REASON_PRIVILEGED)
-                               _exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
-                       else
-                               _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
-                       break;
+                       return;
                }
        }
+
+       if (reason & REASON_PRIVILEGED)
+               _exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
+       else
+               _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
 }
 
 void alignment_exception(struct pt_regs *regs)
@@ -929,25 +864,13 @@ void alignment_exception(struct pt_regs *regs)
        /* Operand address was bad */
        if (fixed == -EFAULT) {
                if (user_mode(regs))
-                       _exception(SIGSEGV, regs,
-#ifdef CONFIG_PPC32
-                               SEGV_ACCERR,
-#else
-                               SEGV_MAPERR,
-#endif
-                       regs->dar);
+                       _exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar);
                else
                        /* Search exception table */
                        bad_page_fault(regs, regs->dar, SIGSEGV);
                return;
        }
-       _exception(SIGBUS, regs, BUS_ADRALN,
-#ifdef CONFIG_PPC32
-               regs->dar
-#else
-               regs->nip
-#endif
-       );
+       _exception(SIGBUS, regs, BUS_ADRALN, regs->dar);
 }
 
 #ifdef CONFIG_PPC32
@@ -976,18 +899,16 @@ void trace_syscall(struct pt_regs *regs)
 }
 #endif /* CONFIG_PPC32 */
 
-#ifdef CONFIG_PPC64
 void kernel_fp_unavailable_exception(struct pt_regs *regs)
 {
        printk(KERN_EMERG "Unrecoverable FP Unavailable Exception "
                          "%lx at %lx\n", regs->trap, regs->nip);
        die("Unrecoverable FP Unavailable Exception", regs, SIGABRT);
 }
-#endif
 
 void altivec_unavailable_exception(struct pt_regs *regs)
 {
-#if !defined(CONFIG_ALTIVEC) || defined(CONFIG_PPC64)
+#if !defined(CONFIG_ALTIVEC)
        if (user_mode(regs)) {
                /* A user program has executed an altivec instruction,
                   but this kernel doesn't support altivec. */
@@ -995,22 +916,9 @@ void altivec_unavailable_exception(struct pt_regs *regs)
                return;
        }
 #endif
-#ifdef CONFIG_PPC32
-       {
-       static int kernel_altivec_count;
-
-       /* The kernel has executed an altivec instruction without
-          first enabling altivec.  Whinge but let it do it. */
-       if (++kernel_altivec_count < 10)
-               printk(KERN_ERR "AltiVec used in kernel (task=%p, pc=%lx)\n",
-                      current, regs->nip);
-       regs->msr |= MSR_VEC;
-       }
-#else
        printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception "
                        "%lx at %lx\n", regs->trap, regs->nip);
        die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);
-#endif
 }
 
 #ifdef CONFIG_PPC64
@@ -1024,8 +932,7 @@ void performance_monitor_exception(struct pt_regs *regs)
 }
 #endif
 
-
-#if defined(CONFIG_PPC32) && defined(CONFIG_8xx)
+#ifdef CONFIG_8xx
 void SoftwareEmulation(struct pt_regs *regs)
 {
        extern int do_mathemu(struct pt_regs *);
@@ -1054,7 +961,7 @@ void SoftwareEmulation(struct pt_regs *regs)
        } else
                emulate_single_step(regs);
 }
-#endif /* defined(CONFIG_PPC32) && defined(CONFIG_8xx) */
+#endif /* CONFIG_8xx */
 
 #ifdef CONFIG_PPC32
 #if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
@@ -1091,29 +998,14 @@ void TAUException(struct pt_regs *regs)
 void altivec_assist_exception(struct pt_regs *regs)
 {
        int err;
-#ifdef CONFIG_PPC64
-       siginfo_t info;
-#endif
 
-#ifdef CONFIG_PPC32
-       preempt_disable();
-       if (regs->msr & MSR_VEC)
-               giveup_altivec(current);
-       preempt_enable();
-#endif
        if (!user_mode(regs)) {
                printk(KERN_EMERG "VMX/Altivec assist exception in kernel mode"
                       " at %lx\n", regs->nip);
-               die("Kernel "
-#ifdef CONFIG_PPC64
-                       "VMX/"
-#endif
-                       "Altivec assist exception", regs, SIGILL);
+               die("Kernel VMX/Altivec assist exception", regs, SIGILL);
        }
 
-#ifdef CONFIG_PPC64
        flush_altivec_to_thread(current);
-#endif /* CONFIG_PPC64 */
 
        err = emulate_altivec(regs);
        if (err == 0) {
@@ -1124,15 +1016,7 @@ void altivec_assist_exception(struct pt_regs *regs)
 
        if (err == -EFAULT) {
                /* got an error reading the instruction */
-#ifdef CONFIG_PPC32
                _exception(SIGSEGV, regs, SEGV_ACCERR, regs->nip);
-#else
-               info.si_signo = SIGSEGV;
-               info.si_errno = 0;
-               info.si_code = SEGV_MAPERR;
-               info.si_addr = (void __user *) regs->nip;
-               force_sig_info(SIGSEGV, &info, current);
-#endif
        } else {
                /* didn't recognize the instruction */
                /* XXX quick hack for now: set the non-Java bit in the VSCR */
@@ -1144,7 +1028,6 @@ void altivec_assist_exception(struct pt_regs *regs)
 }
 #endif /* CONFIG_ALTIVEC */
 
-#ifdef CONFIG_PPC32
 #ifdef CONFIG_FSL_BOOKE
 void CacheLockingException(struct pt_regs *regs, unsigned long address,
                           unsigned long error_code)
@@ -1194,9 +1077,7 @@ void SPEFloatingPointException(struct pt_regs *regs)
        return;
 }
 #endif
-#endif /* CONFIG_PPC32 */
 
-#ifdef CONFIG_PPC64
 /*
  * We enter here if we get an unrecoverable exception, that is, one
  * that happened at a point where the RI (recoverable interrupt) bit
@@ -1209,9 +1090,7 @@ void unrecoverable_exception(struct pt_regs *regs)
               regs->trap, regs->nip);
        die("Unrecoverable exception", regs, SIGABRT);
 }
-#endif /* CONFIG_PPC64 */
 
-#ifdef CONFIG_PPC32
 #ifdef CONFIG_BOOKE_WDT
 /*
  * Default handler for a Watchdog exception,
@@ -1230,9 +1109,7 @@ void WatchdogException(struct pt_regs *regs)
        WatchdogHandler(regs);
 }
 #endif
-#endif /* CONFIG_PPC32 */
 
-#ifdef CONFIG_PPC64
 /*
  * We enter here if we discover during exception entry that we are
  * running in supervisor mode with a userspace value in the stack pointer.
@@ -1243,7 +1120,6 @@ void kernel_bad_stack(struct pt_regs *regs)
               regs->gpr[1], regs->nip);
        die("Bad kernel stack pointer", regs, SIGABRT);
 }
-#endif
 
 void __init trap_init(void)
 {