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