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

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

Version: ~ [ linux-6.4-rc3 ] ~ [ linux-6.3.4 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.30 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.113 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.180 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.243 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.283 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.315 ] ~ [ 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 #include <linux/bug.h>
  2 #include <linux/io.h>
  3 #include <linux/types.h>
  4 #include <linux/kdebug.h>
  5 #include <linux/signal.h>
  6 #include <linux/sched.h>
  7 #include <linux/uaccess.h>
  8 #include <linux/hardirq.h>
  9 #include <linux/kernel.h>
 10 #include <linux/kexec.h>
 11 #include <linux/module.h>
 12 #include <asm/unwinder.h>
 13 #include <asm/traps.h>
 14 
 15 static DEFINE_SPINLOCK(die_lock);
 16 
 17 void die(const char *str, struct pt_regs *regs, long err)
 18 {
 19         static int die_counter;
 20 
 21         oops_enter();
 22 
 23         spin_lock_irq(&die_lock);
 24         console_verbose();
 25         bust_spinlocks(1);
 26 
 27         printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
 28         print_modules();
 29         show_regs(regs);
 30 
 31         printk("Process: %s (pid: %d, stack limit = %p)\n", current->comm,
 32                         task_pid_nr(current), task_stack_page(current) + 1);
 33 
 34         if (!user_mode(regs) || in_interrupt())
 35                 dump_mem("Stack: ", regs->regs[15], THREAD_SIZE +
 36                          (unsigned long)task_stack_page(current));
 37 
 38         notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV);
 39 
 40         bust_spinlocks(0);
 41         add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
 42         spin_unlock_irq(&die_lock);
 43         oops_exit();
 44 
 45         if (kexec_should_crash(current))
 46                 crash_kexec(regs);
 47 
 48         if (in_interrupt())
 49                 panic("Fatal exception in interrupt");
 50 
 51         if (panic_on_oops)
 52                 panic("Fatal exception");
 53 
 54         do_exit(SIGSEGV);
 55 }
 56 
 57 void die_if_kernel(const char *str, struct pt_regs *regs, long err)
 58 {
 59         if (!user_mode(regs))
 60                 die(str, regs, err);
 61 }
 62 
 63 /*
 64  * try and fix up kernelspace address errors
 65  * - userspace errors just cause EFAULT to be returned, resulting in SEGV
 66  * - kernel/userspace interfaces cause a jump to an appropriate handler
 67  * - other kernel errors are bad
 68  */
 69 void die_if_no_fixup(const char *str, struct pt_regs *regs, long err)
 70 {
 71         if (!user_mode(regs)) {
 72                 const struct exception_table_entry *fixup;
 73                 fixup = search_exception_tables(regs->pc);
 74                 if (fixup) {
 75                         regs->pc = fixup->fixup;
 76                         return;
 77                 }
 78 
 79                 die(str, regs, err);
 80         }
 81 }
 82 
 83 #ifdef CONFIG_GENERIC_BUG
 84 static void handle_BUG(struct pt_regs *regs)
 85 {
 86         const struct bug_entry *bug;
 87         unsigned long bugaddr = regs->pc;
 88         enum bug_trap_type tt;
 89 
 90         if (!is_valid_bugaddr(bugaddr))
 91                 goto invalid;
 92 
 93         bug = find_bug(bugaddr);
 94 
 95         /* Switch unwinders when unwind_stack() is called */
 96         if (bug->flags & BUGFLAG_UNWINDER)
 97                 unwinder_faulted = 1;
 98 
 99         tt = report_bug(bugaddr, regs);
100         if (tt == BUG_TRAP_TYPE_WARN) {
101                 regs->pc += instruction_size(bugaddr);
102                 return;
103         }
104 
105 invalid:
106         die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff);
107 }
108 
109 int is_valid_bugaddr(unsigned long addr)
110 {
111         insn_size_t opcode;
112 
113         if (addr < PAGE_OFFSET)
114                 return 0;
115         if (probe_kernel_address((insn_size_t *)addr, opcode))
116                 return 0;
117         if (opcode == TRAPA_BUG_OPCODE)
118                 return 1;
119 
120         return 0;
121 }
122 #endif
123 
124 /*
125  * Generic trap handler.
126  */
127 BUILD_TRAP_HANDLER(debug)
128 {
129         TRAP_HANDLER_DECL;
130 
131         /* Rewind */
132         regs->pc -= instruction_size(__raw_readw(regs->pc - 4));
133 
134         if (notify_die(DIE_TRAP, "debug trap", regs, 0, vec & 0xff,
135                        SIGTRAP) == NOTIFY_STOP)
136                 return;
137 
138         force_sig(SIGTRAP, current);
139 }
140 
141 /*
142  * Special handler for BUG() traps.
143  */
144 BUILD_TRAP_HANDLER(bug)
145 {
146         TRAP_HANDLER_DECL;
147 
148         /* Rewind */
149         regs->pc -= instruction_size(__raw_readw(regs->pc - 4));
150 
151         if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff,
152                        SIGTRAP) == NOTIFY_STOP)
153                 return;
154 
155 #ifdef CONFIG_GENERIC_BUG
156         if (__kernel_text_address(instruction_pointer(regs))) {
157                 insn_size_t insn = *(insn_size_t *)instruction_pointer(regs);
158                 if (insn == TRAPA_BUG_OPCODE)
159                         handle_BUG(regs);
160                 return;
161         }
162 #endif
163 
164         force_sig(SIGTRAP, current);
165 }
166 
167 BUILD_TRAP_HANDLER(nmi)
168 {
169         unsigned int cpu = smp_processor_id();
170         TRAP_HANDLER_DECL;
171 
172         nmi_enter();
173         nmi_count(cpu)++;
174 
175         switch (notify_die(DIE_NMI, "NMI", regs, 0, vec & 0xff, SIGINT)) {
176         case NOTIFY_OK:
177         case NOTIFY_STOP:
178                 break;
179         case NOTIFY_BAD:
180                 die("Fatal Non-Maskable Interrupt", regs, SIGINT);
181         default:
182                 printk(KERN_ALERT "Got NMI, but nobody cared. Ignoring...\n");
183                 break;
184         }
185 
186         nmi_exit();
187 }
188 

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp