traps.c 3.8 KB
Newer Older
M
Mikael Starvik 已提交
1
/* $Id: traps.c,v 1.4 2005/04/24 18:47:55 starvik Exp $
L
Linus Torvalds 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 *  linux/arch/cris/arch-v10/traps.c
 *
 *  Heler functions for trap handlers
 * 
 *  Copyright (C) 2000-2002 Axis Communications AB
 *
 *  Authors:   Bjorn Wesen
 *  	       Hans-Peter Nilsson
 *
 */

#include <linux/ptrace.h>
#include <asm/uaccess.h>
#include <asm/arch/sv_addr_ag.h>

M
Mikael Starvik 已提交
18 19
extern int raw_printk(const char *fmt, ...);

L
Linus Torvalds 已提交
20 21 22 23 24 25 26 27 28 29
void 
show_registers(struct pt_regs * regs)
{
	/* We either use rdusp() - the USP register, which might not
	   correspond to the current process for all cases we're called,
	   or we use the current->thread.usp, which is not up to date for
	   the current process.  Experience shows we want the USP
	   register.  */
	unsigned long usp = rdusp();

M
Mikael Starvik 已提交
30
	raw_printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n",
L
Linus Torvalds 已提交
31
	       regs->irp, regs->srp, regs->dccr, usp, regs->mof );
M
Mikael Starvik 已提交
32
	raw_printk(" r0: %08lx  r1: %08lx   r2: %08lx  r3: %08lx\n",
L
Linus Torvalds 已提交
33
	       regs->r0, regs->r1, regs->r2, regs->r3);
M
Mikael Starvik 已提交
34
	raw_printk(" r4: %08lx  r5: %08lx   r6: %08lx  r7: %08lx\n",
L
Linus Torvalds 已提交
35
	       regs->r4, regs->r5, regs->r6, regs->r7);
M
Mikael Starvik 已提交
36
	raw_printk(" r8: %08lx  r9: %08lx  r10: %08lx r11: %08lx\n",
L
Linus Torvalds 已提交
37
	       regs->r8, regs->r9, regs->r10, regs->r11);
M
Mikael Starvik 已提交
38 39 40 41
	raw_printk("r12: %08lx r13: %08lx oR10: %08lx  sp: %08lx\n",
	       regs->r12, regs->r13, regs->orig_r10, regs);
	raw_printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE);
	raw_printk("Process %s (pid: %d, stackpage=%08lx)\n",
L
Linus Torvalds 已提交
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
	       current->comm, current->pid, (unsigned long)current);

	/*
         * When in-kernel, we also print out the stack and code at the
         * time of the fault..
         */
        if (! user_mode(regs)) {
	  	int i;

                show_stack(NULL, (unsigned long*)usp);

		/* Dump kernel stack if the previous dump wasn't one.  */
		if (usp != 0)
			show_stack (NULL, NULL);

M
Mikael Starvik 已提交
57
                raw_printk("\nCode: ");
L
Linus Torvalds 已提交
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
                if(regs->irp < PAGE_OFFSET)
                        goto bad;

		/* Often enough the value at regs->irp does not point to
		   the interesting instruction, which is most often the
		   _previous_ instruction.  So we dump at an offset large
		   enough that instruction decoding should be in sync at
		   the interesting point, but small enough to fit on a row
		   (sort of).  We point out the regs->irp location in a
		   ksymoops-friendly way by wrapping the byte for that
		   address in parentheses.  */
                for(i = -12; i < 12; i++)
                {
                        unsigned char c;
                        if(__get_user(c, &((unsigned char*)regs->irp)[i])) {
bad:
M
Mikael Starvik 已提交
74
                                raw_printk(" Bad IP value.");
L
Linus Torvalds 已提交
75 76 77 78
                                break;
                        }

			if (i == 0)
M
Mikael Starvik 已提交
79
			  raw_printk("(%02x) ", c);
L
Linus Torvalds 已提交
80
			else
M
Mikael Starvik 已提交
81
			  raw_printk("%02x ", c);
L
Linus Torvalds 已提交
82
                }
M
Mikael Starvik 已提交
83
		raw_printk("\n");
L
Linus Torvalds 已提交
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
        }
}

/* Called from entry.S when the watchdog has bitten
 * We print out something resembling an oops dump, and if
 * we have the nice doggy development flag set, we halt here
 * instead of rebooting.
 */

extern void reset_watchdog(void);
extern void stop_watchdog(void);


void
watchdog_bite_hook(struct pt_regs *regs)
{
#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
	local_irq_disable();
	stop_watchdog();
	show_registers(regs);
	while(1) /* nothing */;
#else
	show_registers(regs);
#endif	
}

/* This is normally the 'Oops' routine */
void 
die_if_kernel(const char * str, struct pt_regs * regs, long err)
{
	if(user_mode(regs))
		return;

#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
	/* This printout might take too long and trigger the 
	 * watchdog normally. If we're in the nice doggy
	 * development mode, stop the watchdog during printout.
	 */
	stop_watchdog();
#endif

M
Mikael Starvik 已提交
125
	raw_printk("%s: %04lx\n", str, err & 0xffff);
L
Linus Torvalds 已提交
126 127 128 129 130 131 132 133

	show_registers(regs);

#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
	reset_watchdog();
#endif
	do_exit(SIGSEGV);
}
M
Mikael Starvik 已提交
134 135 136 137 138

void arch_enable_nmi(void)
{
  asm volatile("setf m");
}