~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/nios2/kernel/traps.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Hardware exception handling
  3  *
  4  * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
  5  * Copyright (C) 2004 Microtronix Datacom Ltd.
  6  * Copyright (C) 2001 Vic Phillips
  7  *
  8  * This file is subject to the terms and conditions of the GNU General
  9  * Public License.  See the file COPYING in the main directory of this
 10  * archive for more details.
 11  */
 12 
 13 #include <linux/sched.h>
 14 #include <linux/sched/debug.h>
 15 #include <linux/kernel.h>
 16 #include <linux/signal.h>
 17 #include <linux/export.h>
 18 #include <linux/mm.h>
 19 #include <linux/ptrace.h>
 20 
 21 #include <asm/traps.h>
 22 #include <asm/sections.h>
 23 #include <linux/uaccess.h>
 24 
 25 static DEFINE_SPINLOCK(die_lock);
 26 
 27 static void _send_sig(int signo, int code, unsigned long addr)
 28 {
 29         force_sig_fault(signo, code, (void __user *) addr);
 30 }
 31 
 32 void die(const char *str, struct pt_regs *regs, long err)
 33 {
 34         console_verbose();
 35         spin_lock_irq(&die_lock);
 36         pr_warn("Oops: %s, sig: %ld\n", str, err);
 37         show_regs(regs);
 38         spin_unlock_irq(&die_lock);
 39         /*
 40          * make_task_dead() should take care of panic'ing from an interrupt
 41          * context so we don't handle it here
 42          */
 43         make_task_dead(err);
 44 }
 45 
 46 void _exception(int signo, struct pt_regs *regs, int code, unsigned long addr)
 47 {
 48         if (!user_mode(regs))
 49                 die("Exception in kernel mode", regs, signo);
 50 
 51         _send_sig(signo, code, addr);
 52 }
 53 
 54 /*
 55  * The show_stack() is external API which we do not use ourselves.
 56  */
 57 
 58 int kstack_depth_to_print = 48;
 59 
 60 void show_stack(struct task_struct *task, unsigned long *stack,
 61                 const char *loglvl)
 62 {
 63         unsigned long *endstack, addr;
 64         int i;
 65 
 66         if (!stack) {
 67                 if (task)
 68                         stack = (unsigned long *)task->thread.ksp;
 69                 else
 70                         stack = (unsigned long *)&stack;
 71         }
 72 
 73         addr = (unsigned long) stack;
 74         endstack = (unsigned long *) PAGE_ALIGN(addr);
 75 
 76         printk("%sStack from %08lx:", loglvl, (unsigned long)stack);
 77         for (i = 0; i < kstack_depth_to_print; i++) {
 78                 if (stack + 1 > endstack)
 79                         break;
 80                 if (i % 8 == 0)
 81                         printk("%s\n       ", loglvl);
 82                 printk("%s %08lx", loglvl, *stack++);
 83         }
 84 
 85         printk("%s\nCall Trace:", loglvl);
 86         i = 0;
 87         while (stack + 1 <= endstack) {
 88                 addr = *stack++;
 89                 /*
 90                  * If the address is either in the text segment of the
 91                  * kernel, or in the region which contains vmalloc'ed
 92                  * memory, it *may* be the address of a calling
 93                  * routine; if so, print it so that someone tracing
 94                  * down the cause of the crash will be able to figure
 95                  * out the call path that was taken.
 96                  */
 97                 if (((addr >= (unsigned long) _stext) &&
 98                      (addr <= (unsigned long) _etext))) {
 99                         if (i % 4 == 0)
100                                 pr_emerg("\n       ");
101                         printk("%s [<%08lx>]", loglvl, addr);
102                         i++;
103                 }
104         }
105         printk("%s\n", loglvl);
106 }
107 
108 /* Breakpoint handler */
109 asmlinkage void breakpoint_c(struct pt_regs *fp)
110 {
111         /*
112          * The breakpoint entry code has moved the PC on by 4 bytes, so we must
113          * move it back. This could be done on the host but we do it here
114          * because monitor.S of JTAG gdbserver does it too.
115          */
116         fp->ea -= 4;
117         _exception(SIGTRAP, fp, TRAP_BRKPT, fp->ea);
118 }
119 
120 #ifndef CONFIG_NIOS2_ALIGNMENT_TRAP
121 /* Alignment exception handler */
122 asmlinkage void handle_unaligned_c(struct pt_regs *fp, int cause)
123 {
124         unsigned long addr = RDCTL(CTL_BADADDR);
125 
126         cause >>= 2;
127         fp->ea -= 4;
128 
129         if (fixup_exception(fp))
130                 return;
131 
132         if (!user_mode(fp)) {
133                 pr_alert("Unaligned access from kernel mode, this might be a hardware\n");
134                 pr_alert("problem, dump registers and restart the instruction\n");
135                 pr_alert("  BADADDR 0x%08lx\n", addr);
136                 pr_alert("  cause   %d\n", cause);
137                 pr_alert("  op-code 0x%08lx\n", *(unsigned long *)(fp->ea));
138                 show_regs(fp);
139                 return;
140         }
141 
142         _exception(SIGBUS, fp, BUS_ADRALN, addr);
143 }
144 #endif /* CONFIG_NIOS2_ALIGNMENT_TRAP */
145 
146 /* Illegal instruction handler */
147 asmlinkage void handle_illegal_c(struct pt_regs *fp)
148 {
149         fp->ea -= 4;
150         _exception(SIGILL, fp, ILL_ILLOPC, fp->ea);
151 }
152 
153 /* Supervisor instruction handler */
154 asmlinkage void handle_supervisor_instr(struct pt_regs *fp)
155 {
156         fp->ea -= 4;
157         _exception(SIGILL, fp, ILL_PRVOPC, fp->ea);
158 }
159 
160 /* Division error handler */
161 asmlinkage void handle_diverror_c(struct pt_regs *fp)
162 {
163         fp->ea -= 4;
164         _exception(SIGFPE, fp, FPE_INTDIV, fp->ea);
165 }
166 
167 /* Unhandled exception handler */
168 asmlinkage void unhandled_exception(struct pt_regs *regs, int cause)
169 {
170         unsigned long addr = RDCTL(CTL_BADADDR);
171 
172         cause /= 4;
173 
174         pr_emerg("Unhandled exception #%d in %s mode (badaddr=0x%08lx)\n",
175                         cause, user_mode(regs) ? "user" : "kernel", addr);
176 
177         regs->ea -= 4;
178         show_regs(regs);
179 
180         pr_emerg("opcode: 0x%08lx\n", *(unsigned long *)(regs->ea));
181 }
182 
183 asmlinkage void handle_trap_1_c(struct pt_regs *fp)
184 {
185         _send_sig(SIGUSR1, 0, fp->ea);
186 }
187 
188 asmlinkage void handle_trap_2_c(struct pt_regs *fp)
189 {
190         _send_sig(SIGUSR2, 0, fp->ea);
191 }
192 
193 asmlinkage void handle_trap_3_c(struct pt_regs *fp)
194 {
195         _send_sig(SIGILL, ILL_ILLTRP, fp->ea);
196 }
197 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php