linux/arch/arm64/kernel/traps.c
<<
>>
Prefs
   1/*
   2 * Based on arch/arm/kernel/traps.c
   3 *
   4 * Copyright (C) 1995-2009 Russell King
   5 * Copyright (C) 2012 ARM Ltd.
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#include <linux/signal.h>
  21#include <linux/personality.h>
  22#include <linux/kallsyms.h>
  23#include <linux/spinlock.h>
  24#include <linux/uaccess.h>
  25#include <linux/hardirq.h>
  26#include <linux/kdebug.h>
  27#include <linux/module.h>
  28#include <linux/kexec.h>
  29#include <linux/delay.h>
  30#include <linux/init.h>
  31#include <linux/sched.h>
  32#include <linux/syscalls.h>
  33
  34#include <asm/atomic.h>
  35#include <asm/debug-monitors.h>
  36#include <asm/traps.h>
  37#include <asm/stacktrace.h>
  38#include <asm/exception.h>
  39#include <asm/system_misc.h>
  40
  41static const char *handler[]= {
  42        "Synchronous Abort",
  43        "IRQ",
  44        "FIQ",
  45        "Error"
  46};
  47
  48int show_unhandled_signals = 1;
  49
  50/*
  51 * Dump out the contents of some memory nicely...
  52 */
  53static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
  54                     unsigned long top)
  55{
  56        unsigned long first;
  57        mm_segment_t fs;
  58        int i;
  59
  60        /*
  61         * We need to switch to kernel mode so that we can use __get_user
  62         * to safely read from kernel space.  Note that we now dump the
  63         * code first, just in case the backtrace kills us.
  64         */
  65        fs = get_fs();
  66        set_fs(KERNEL_DS);
  67
  68        printk("%s%s(0x%016lx to 0x%016lx)\n", lvl, str, bottom, top);
  69
  70        for (first = bottom & ~31; first < top; first += 32) {
  71                unsigned long p;
  72                char str[sizeof(" 12345678") * 8 + 1];
  73
  74                memset(str, ' ', sizeof(str));
  75                str[sizeof(str) - 1] = '\0';
  76
  77                for (p = first, i = 0; i < 8 && p < top; i++, p += 4) {
  78                        if (p >= bottom && p < top) {
  79                                unsigned int val;
  80                                if (__get_user(val, (unsigned int *)p) == 0)
  81                                        sprintf(str + i * 9, " %08x", val);
  82                                else
  83                                        sprintf(str + i * 9, " ????????");
  84                        }
  85                }
  86                printk("%s%04lx:%s\n", lvl, first & 0xffff, str);
  87        }
  88
  89        set_fs(fs);
  90}
  91
  92static void dump_backtrace_entry(unsigned long where, unsigned long stack)
  93{
  94        print_ip_sym(where);
  95        if (in_exception_text(where))
  96                dump_mem("", "Exception stack", stack,
  97                         stack + sizeof(struct pt_regs));
  98}
  99
 100static void dump_instr(const char *lvl, struct pt_regs *regs)
 101{
 102        unsigned long addr = instruction_pointer(regs);
 103        mm_segment_t fs;
 104        char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str;
 105        int i;
 106
 107        /*
 108         * We need to switch to kernel mode so that we can use __get_user
 109         * to safely read from kernel space.  Note that we now dump the
 110         * code first, just in case the backtrace kills us.
 111         */
 112        fs = get_fs();
 113        set_fs(KERNEL_DS);
 114
 115        for (i = -4; i < 1; i++) {
 116                unsigned int val, bad;
 117
 118                bad = __get_user(val, &((u32 *)addr)[i]);
 119
 120                if (!bad)
 121                        p += sprintf(p, i == 0 ? "(%08x) " : "%08x ", val);
 122                else {
 123                        p += sprintf(p, "bad PC value");
 124                        break;
 125                }
 126        }
 127        printk("%sCode: %s\n", lvl, str);
 128
 129        set_fs(fs);
 130}
 131
 132static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
 133{
 134        struct stackframe frame;
 135        const register unsigned long current_sp asm ("sp");
 136
 137        pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);
 138
 139        if (!tsk)
 140                tsk = current;
 141
 142        if (regs) {
 143                frame.fp = regs->regs[29];
 144                frame.sp = regs->sp;
 145                frame.pc = regs->pc;
 146        } else if (tsk == current) {
 147                frame.fp = (unsigned long)__builtin_frame_address(0);
 148                frame.sp = current_sp;
 149                frame.pc = (unsigned long)dump_backtrace;
 150        } else {
 151                /*
 152                 * task blocked in __switch_to
 153                 */
 154                frame.fp = thread_saved_fp(tsk);
 155                frame.sp = thread_saved_sp(tsk);
 156                frame.pc = thread_saved_pc(tsk);
 157        }
 158
 159        printk("Call trace:\n");
 160        while (1) {
 161                unsigned long where = frame.pc;
 162                int ret;
 163
 164                ret = unwind_frame(&frame);
 165                if (ret < 0)
 166                        break;
 167                dump_backtrace_entry(where, frame.sp);
 168        }
 169}
 170
 171void show_stack(struct task_struct *tsk, unsigned long *sp)
 172{
 173        dump_backtrace(NULL, tsk);
 174        barrier();
 175}
 176
 177#ifdef CONFIG_PREEMPT
 178#define S_PREEMPT " PREEMPT"
 179#else
 180#define S_PREEMPT ""
 181#endif
 182#ifdef CONFIG_SMP
 183#define S_SMP " SMP"
 184#else
 185#define S_SMP ""
 186#endif
 187
 188static int __die(const char *str, int err, struct thread_info *thread,
 189                 struct pt_regs *regs)
 190{
 191        struct task_struct *tsk = thread->task;
 192        static int die_counter;
 193        int ret;
 194
 195        pr_emerg("Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",
 196                 str, err, ++die_counter);
 197
 198        /* trap and error numbers are mostly meaningless on ARM */
 199        ret = notify_die(DIE_OOPS, str, regs, err, 0, SIGSEGV);
 200        if (ret == NOTIFY_STOP)
 201                return ret;
 202
 203        print_modules();
 204        __show_regs(regs);
 205        pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n",
 206                 TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1);
 207
 208        if (!user_mode(regs) || in_interrupt()) {
 209                dump_mem(KERN_EMERG, "Stack: ", regs->sp,
 210                         THREAD_SIZE + (unsigned long)task_stack_page(tsk));
 211                dump_backtrace(regs, tsk);
 212                dump_instr(KERN_EMERG, regs);
 213        }
 214
 215        return ret;
 216}
 217
 218static DEFINE_RAW_SPINLOCK(die_lock);
 219
 220/*
 221 * This function is protected against re-entrancy.
 222 */
 223void die(const char *str, struct pt_regs *regs, int err)
 224{
 225        struct thread_info *thread = current_thread_info();
 226        int ret;
 227
 228        oops_enter();
 229
 230        raw_spin_lock_irq(&die_lock);
 231        console_verbose();
 232        bust_spinlocks(1);
 233        ret = __die(str, err, thread, regs);
 234
 235        if (regs && kexec_should_crash(thread->task))
 236                crash_kexec(regs);
 237
 238        bust_spinlocks(0);
 239        add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
 240        raw_spin_unlock_irq(&die_lock);
 241        oops_exit();
 242
 243        if (in_interrupt())
 244                panic("Fatal exception in interrupt");
 245        if (panic_on_oops)
 246                panic("Fatal exception");
 247        if (ret != NOTIFY_STOP)
 248                do_exit(SIGSEGV);
 249}
 250
 251void arm64_notify_die(const char *str, struct pt_regs *regs,
 252                      struct siginfo *info, int err)
 253{
 254        if (user_mode(regs))
 255                force_sig_info(info->si_signo, info, current);
 256        else
 257                die(str, regs, err);
 258}
 259
 260asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
 261{
 262        siginfo_t info;
 263        void __user *pc = (void __user *)instruction_pointer(regs);
 264
 265        /* check for AArch32 breakpoint instructions */
 266        if (!aarch32_break_handler(regs))
 267                return;
 268
 269        if (show_unhandled_signals && unhandled_signal(current, SIGILL) &&
 270            printk_ratelimit()) {
 271                pr_info("%s[%d]: undefined instruction: pc=%p\n",
 272                        current->comm, task_pid_nr(current), pc);
 273                dump_instr(KERN_INFO, regs);
 274        }
 275
 276        info.si_signo = SIGILL;
 277        info.si_errno = 0;
 278        info.si_code  = ILL_ILLOPC;
 279        info.si_addr  = pc;
 280
 281        arm64_notify_die("Oops - undefined instruction", regs, &info, 0);
 282}
 283
 284long compat_arm_syscall(struct pt_regs *regs);
 285
 286asmlinkage long do_ni_syscall(struct pt_regs *regs)
 287{
 288#ifdef CONFIG_COMPAT
 289        long ret;
 290        if (is_compat_task()) {
 291                ret = compat_arm_syscall(regs);
 292                if (ret != -ENOSYS)
 293                        return ret;
 294        }
 295#endif
 296
 297        if (show_unhandled_signals && printk_ratelimit()) {
 298                pr_info("%s[%d]: syscall %d\n", current->comm,
 299                        task_pid_nr(current), (int)regs->syscallno);
 300                dump_instr("", regs);
 301                if (user_mode(regs))
 302                        __show_regs(regs);
 303        }
 304
 305        return sys_ni_syscall();
 306}
 307
 308/*
 309 * bad_mode handles the impossible case in the exception vector.
 310 */
 311asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
 312{
 313        siginfo_t info;
 314        void __user *pc = (void __user *)instruction_pointer(regs);
 315        console_verbose();
 316
 317        pr_crit("Bad mode in %s handler detected, code 0x%08x\n",
 318                handler[reason], esr);
 319        __show_regs(regs);
 320
 321        info.si_signo = SIGILL;
 322        info.si_errno = 0;
 323        info.si_code  = ILL_ILLOPC;
 324        info.si_addr  = pc;
 325
 326        arm64_notify_die("Oops - bad mode", regs, &info, 0);
 327}
 328
 329void __pte_error(const char *file, int line, unsigned long val)
 330{
 331        printk("%s:%d: bad pte %016lx.\n", file, line, val);
 332}
 333
 334void __pmd_error(const char *file, int line, unsigned long val)
 335{
 336        printk("%s:%d: bad pmd %016lx.\n", file, line, val);
 337}
 338
 339void __pgd_error(const char *file, int line, unsigned long val)
 340{
 341        printk("%s:%d: bad pgd %016lx.\n", file, line, val);
 342}
 343
 344void __init trap_init(void)
 345{
 346        return;
 347}
 348