blob: 7001beda716c2c86077df3dc224d470244152965 [file] [log] [blame]
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +01001/*
2 * Helper functions for trap handlers
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +01004 * Copyright (C) 2000-2007, Axis Communications AB.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +01006 * Authors: Bjorn Wesen
7 * Hans-Peter Nilsson
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 *
9 */
10
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <linux/ptrace.h>
12#include <asm/uaccess.h>
Jesper Nilsson556dcee2008-10-21 17:45:58 +020013#include <arch/sv_addr_ag.h>
David Howellsb1a154d2012-03-28 18:30:02 +010014#include <arch/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010016void
17show_registers(struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -070018{
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010019 /*
20 * It's possible to use either the USP register or current->thread.usp.
21 * USP might not correspond to the current process for all cases this
22 * function is called, and current->thread.usp isn't up to date for the
23 * current process. Experience shows that using USP is the way to go.
24 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070025 unsigned long usp = rdusp();
26
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010027 printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n",
28 regs->irp, regs->srp, regs->dccr, usp, regs->mof);
29
30 printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -070031 regs->r0, regs->r1, regs->r2, regs->r3);
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010032
33 printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -070034 regs->r4, regs->r5, regs->r6, regs->r7);
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010035
36 printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -070037 regs->r8, regs->r9, regs->r10, regs->r11);
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010038
39 printk("r12: %08lx r13: %08lx oR10: %08lx sp: %08lx\n",
40 regs->r12, regs->r13, regs->orig_r10, (long unsigned)regs);
41
42 printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE);
43
44 printk("Process %s (pid: %d, stackpage=%08lx)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -070045 current->comm, current->pid, (unsigned long)current);
46
47 /*
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010048 * When in-kernel, we also print out the stack and code at the
49 * time of the fault..
50 */
51 if (!user_mode(regs)) {
52 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010054 show_stack(NULL, (unsigned long *)usp);
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010056 /*
57 * If the previous stack-dump wasn't a kernel one, dump the
58 * kernel stack now.
59 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070060 if (usp != 0)
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010061 show_stack(NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010063 printk("\nCode: ");
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010065 if (regs->irp < PAGE_OFFSET)
66 goto bad_value;
67
68 /*
69 * Quite often the value at regs->irp doesn't point to the
70 * interesting instruction, which often is the previous
71 * instruction. So dump at an offset large enough that the
72 * instruction decoding should be in sync at the interesting
73 * point, but small enough to fit on a row. The regs->irp
74 * location is pointed out in a ksymoops-friendly way by
75 * wrapping the byte for that address in parenthesises.
76 */
77 for (i = -12; i < 12; i++) {
78 unsigned char c;
79
80 if (__get_user(c, &((unsigned char *)regs->irp)[i])) {
81bad_value:
82 printk(" Bad IP value.");
83 break;
84 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
86 if (i == 0)
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010087 printk("(%02x) ", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 else
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010089 printk("%02x ", c);
90 }
91 printk("\n");
92 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070093}
94
Linus Torvalds1da177e2005-04-16 15:20:36 -070095void
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010096arch_enable_nmi(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070097{
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010098 asm volatile ("setf m");
Linus Torvalds1da177e2005-04-16 15:20:36 -070099}
100
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +0100101extern void (*nmi_handler)(struct pt_regs *);
102void handle_nmi(struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103{
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +0100104 if (nmi_handler)
105 nmi_handler(regs);
106
107 /* Wait until nmi is no longer active. (We enable NMI immediately after
108 returning from this function, and we don't want it happening while
109 exiting from the NMI interrupt handler.) */
110 while (*R_IRQ_MASK0_RD & IO_STATE(R_IRQ_MASK0_RD, nmi_pin, active))
111 ;
112}
113
114#ifdef CONFIG_DEBUG_BUGVERBOSE
115void
116handle_BUG(struct pt_regs *regs)
117{
118 struct bug_frame f;
119 unsigned char c;
120 unsigned long irp = regs->irp;
121
122 if (__copy_from_user(&f, (const void __user *)(irp - 8), sizeof f))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 return;
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +0100124 if (f.prefix != BUG_PREFIX || f.magic != BUG_MAGIC)
125 return;
126 if (__get_user(c, f.filename))
127 f.filename = "<bad filename>";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +0100129 printk("kernel BUG at %s:%d!\n", f.filename, f.line);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130}
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +0100131#endif