blob: 8bebb96bbca1ba60eb09ecaa737462e0a1c9ff19 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010015void
16show_registers(struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -070017{
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010018 /*
19 * It's possible to use either the USP register or current->thread.usp.
20 * USP might not correspond to the current process for all cases this
21 * function is called, and current->thread.usp isn't up to date for the
22 * current process. Experience shows that using USP is the way to go.
23 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 unsigned long usp = rdusp();
25
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010026 printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n",
27 regs->irp, regs->srp, regs->dccr, usp, regs->mof);
28
29 printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -070030 regs->r0, regs->r1, regs->r2, regs->r3);
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010031
32 printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -070033 regs->r4, regs->r5, regs->r6, regs->r7);
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010034
35 printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -070036 regs->r8, regs->r9, regs->r10, regs->r11);
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010037
38 printk("r12: %08lx r13: %08lx oR10: %08lx sp: %08lx\n",
39 regs->r12, regs->r13, regs->orig_r10, (long unsigned)regs);
40
41 printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE);
42
43 printk("Process %s (pid: %d, stackpage=%08lx)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 current->comm, current->pid, (unsigned long)current);
45
46 /*
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010047 * When in-kernel, we also print out the stack and code at the
48 * time of the fault..
49 */
50 if (!user_mode(regs)) {
51 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070052
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010053 show_stack(NULL, (unsigned long *)usp);
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010055 /*
56 * If the previous stack-dump wasn't a kernel one, dump the
57 * kernel stack now.
58 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070059 if (usp != 0)
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010060 show_stack(NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070061
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010062 printk("\nCode: ");
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010064 if (regs->irp < PAGE_OFFSET)
65 goto bad_value;
66
67 /*
68 * Quite often the value at regs->irp doesn't point to the
69 * interesting instruction, which often is the previous
70 * instruction. So dump at an offset large enough that the
71 * instruction decoding should be in sync at the interesting
72 * point, but small enough to fit on a row. The regs->irp
73 * location is pointed out in a ksymoops-friendly way by
74 * wrapping the byte for that address in parenthesises.
75 */
76 for (i = -12; i < 12; i++) {
77 unsigned char c;
78
79 if (__get_user(c, &((unsigned char *)regs->irp)[i])) {
80bad_value:
81 printk(" Bad IP value.");
82 break;
83 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070084
85 if (i == 0)
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010086 printk("(%02x) ", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -070087 else
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010088 printk("%02x ", c);
89 }
90 printk("\n");
91 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070092}
93
Linus Torvalds1da177e2005-04-16 15:20:36 -070094void
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010095arch_enable_nmi(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070096{
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +010097 asm volatile ("setf m");
Linus Torvalds1da177e2005-04-16 15:20:36 -070098}
99
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +0100100extern void (*nmi_handler)(struct pt_regs *);
101void handle_nmi(struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102{
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +0100103 if (nmi_handler)
104 nmi_handler(regs);
105
106 /* Wait until nmi is no longer active. (We enable NMI immediately after
107 returning from this function, and we don't want it happening while
108 exiting from the NMI interrupt handler.) */
109 while (*R_IRQ_MASK0_RD & IO_STATE(R_IRQ_MASK0_RD, nmi_pin, active))
110 ;
111}
112
113#ifdef CONFIG_DEBUG_BUGVERBOSE
114void
115handle_BUG(struct pt_regs *regs)
116{
117 struct bug_frame f;
118 unsigned char c;
119 unsigned long irp = regs->irp;
120
121 if (__copy_from_user(&f, (const void __user *)(irp - 8), sizeof f))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 return;
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +0100123 if (f.prefix != BUG_PREFIX || f.magic != BUG_MAGIC)
124 return;
125 if (__get_user(c, f.filename))
126 f.filename = "<bad filename>";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +0100128 printk("kernel BUG at %s:%d!\n", f.filename, f.line);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129}
Jesper Nilsson1e4cc2c2007-11-30 16:22:50 +0100130#endif