cregit-Linux how code gets into the kernel

Release 4.11 arch/arm/kernel/traps.c

Directory: arch/arm/kernel
/*
 *  linux/arch/arm/kernel/traps.c
 *
 *  Copyright (C) 1995-2009 Russell King
 *  Fragments that appear the same as linux/arch/i386/kernel/traps.c (C) Linus Torvalds
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 *  'traps.c' handles hardware exceptions after we have saved some state in
 *  'linux/arch/arm/lib/traps.S'.  Mostly a debugging aid, but will probably
 *  kill the offending process.
 */
#include <linux/signal.h>
#include <linux/personality.h>
#include <linux/kallsyms.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/hardirq.h>
#include <linux/kdebug.h>
#include <linux/module.h>
#include <linux/kexec.h>
#include <linux/bug.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/sched/signal.h>
#include <linux/sched/debug.h>
#include <linux/sched/task_stack.h>
#include <linux/irq.h>

#include <linux/atomic.h>
#include <asm/cacheflush.h>
#include <asm/exception.h>
#include <asm/unistd.h>
#include <asm/traps.h>
#include <asm/ptrace.h>
#include <asm/unwind.h>
#include <asm/tls.h>
#include <asm/system_misc.h>
#include <asm/opcodes.h>



static const char *handler[]= {
	"prefetch abort",
	"data abort",
	"address exception",
	"interrupt",
	"undefined instruction",
};


void *vectors_page;

#ifdef CONFIG_DEBUG_USER

unsigned int user_debug;


static int __init user_debug_setup(char *str) { get_option(&str, &user_debug); return 1; }

Contributors

PersonTokensPropCommitsCommitProp
Russell King23100.00%1100.00%
Total23100.00%1100.00%

__setup("user_debug=", user_debug_setup); #endif static void dump_mem(const char *, const char *, unsigned long, unsigned long);
void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame) { #ifdef CONFIG_KALLSYMS printk("[<%08lx>] (%ps) from [<%08lx>] (%pS)\n", where, (void *)where, from, (void *)from); #else printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from); #endif if (in_exception_text(where)) dump_mem("", "Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs)); }

Contributors

PersonTokensPropCommitsCommitProp
Russell King7287.80%787.50%
Joe Perches1012.20%112.50%
Total82100.00%8100.00%


void dump_backtrace_stm(u32 *stack, u32 instruction) { char str[80], *p; unsigned int x; int reg; for (reg = 10, x = 0, p = str; reg >= 0; reg--) { if (instruction & BIT(reg)) { p += sprintf(p, " r%d:%08x", reg, *stack--); if (++x == 6) { x = 0; p = str; printk("%s\n", str); } } } if (p != str) printk("%s\n", str); }

Contributors

PersonTokensPropCommitsCommitProp
Russell King114100.00%1100.00%
Total114100.00%1100.00%

#ifndef CONFIG_ARM_UNWIND /* * Stack pointers should always be within the kernels view of * physical memory. If it is not there, then we can't dump * out any information relating to the stack. */
static int verify_stack(unsigned long sp) { if (sp < PAGE_OFFSET || (sp > (unsigned long)high_memory && high_memory != NULL)) return -EFAULT; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)3183.78%360.00%
Linus Torvalds513.51%120.00%
Russell King12.70%120.00%
Total37100.00%5100.00%

#endif /* * Dump out the contents of some memory nicely... */
static void dump_mem(const char *lvl, const char *str, unsigned long bottom, unsigned long top) { unsigned long first; mm_segment_t fs; int i; /* * We need to switch to kernel mode so that we can use __get_user * to safely read from kernel space. Note that we now dump the * code first, just in case the backtrace kills us. */ fs = get_fs(); set_fs(KERNEL_DS); printk("%s%s(0x%08lx to 0x%08lx)\n", lvl, str, bottom, top); for (first = bottom & ~31; first < top; first += 32) { unsigned long p; char str[sizeof(" 12345678") * 8 + 1]; memset(str, ' ', sizeof(str)); str[sizeof(str) - 1] = '\0'; for (p = first, i = 0; i < 8 && p < top; i++, p += 4) { if (p >= bottom && p < top) { unsigned long val; if (__get_user(val, (unsigned long *)p) == 0) sprintf(str + i * 9, " %08lx", val); else sprintf(str + i * 9, " ????????"); } } printk("%s%04lx:%s\n", lvl, first & 0xffff, str); } set_fs(fs); }

Contributors

PersonTokensPropCommitsCommitProp
Russell King11954.09%342.86%
Linus Torvalds (pre-git)8538.64%342.86%
Linus Torvalds167.27%114.29%
Total220100.00%7100.00%


static void dump_instr(const char *lvl, struct pt_regs *regs) { unsigned long addr = instruction_pointer(regs); const int thumb = thumb_mode(regs); const int width = thumb ? 4 : 8; mm_segment_t fs; char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str; int i; /* * We need to switch to kernel mode so that we can use __get_user * to safely read from kernel space. Note that we now dump the * code first, just in case the backtrace kills us. */ fs = get_fs(); set_fs(KERNEL_DS); for (i = -4; i < 1 + !!thumb; i++) { unsigned int val, bad; if (thumb) bad = __get_user(val, &((u16 *)addr)[i]); else bad = __get_user(val, &((u32 *)addr)[i]); if (!bad) p += sprintf(p, i == 0 ? "(%0*x) " : "%0*x ", width, val); else { p += sprintf(p, "bad PC value"); break; } } printk("%sCode: %s\n", lvl, str); set_fs(fs); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)13466.67%333.33%
Russell King6632.84%555.56%
Linus Torvalds10.50%111.11%
Total201100.00%9100.00%

#ifdef CONFIG_ARM_UNWIND
static inline void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) { unwind_backtrace(regs, tsk); }

Contributors

PersonTokensPropCommitsCommitProp
Catalin Marinas24100.00%1100.00%
Total24100.00%1100.00%

#else
static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) { unsigned int fp, mode; int ok = 1; printk("Backtrace: "); if (!tsk) tsk = current; if (regs) { fp = frame_pointer(regs); mode = processor_mode(regs); } else if (tsk != current) { fp = thread_saved_fp(tsk); mode = 0x10; } else { asm("mov %0, fp" : "=r" (fp) : : "cc"); mode = 0x10; } if (!fp) { pr_cont("no frame pointer"); ok = 0; } else if (verify_stack(fp)) { pr_cont("invalid frame pointer 0x%08x", fp); ok = 0; } else if (fp < (unsigned long)end_of_stack(tsk)) pr_cont("frame pointer underflow"); pr_cont("\n"); if (ok) c_backtrace(fp, mode); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)9559.01%333.33%
Catalin Marinas5332.92%111.11%
Russell King63.73%222.22%
Al Viro31.86%111.11%
Nikolay Borisov31.86%111.11%
Linus Torvalds10.62%111.11%
Total161100.00%9100.00%

#endif
void show_stack(struct task_struct *tsk, unsigned long *sp) { dump_backtrace(NULL, tsk); barrier(); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds1352.00%125.00%
Russell King624.00%125.00%
Marc Singer312.00%125.00%
Catalin Marinas312.00%125.00%
Total25100.00%4100.00%

#ifdef CONFIG_PREEMPT #define S_PREEMPT " PREEMPT" #else #define S_PREEMPT "" #endif #ifdef CONFIG_SMP #define S_SMP " SMP" #else #define S_SMP "" #endif #ifdef CONFIG_THUMB2_KERNEL #define S_ISA " THUMB2" #else #define S_ISA " ARM" #endif
static int __die(const char *str, int err, struct pt_regs *regs) { struct task_struct *tsk = current; static int die_counter; int ret; pr_emerg("Internal error: %s: %x [#%d]" S_PREEMPT S_SMP S_ISA "\n", str, err, ++die_counter); /* trap and error numbers are mostly meaningless on ARM */ ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV); if (ret == NOTIFY_STOP) return 1; print_modules(); __show_regs(regs); pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n", TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), end_of_stack(tsk)); if (!user_mode(regs) || in_interrupt()) { dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp, THREAD_SIZE + (unsigned long)task_stack_page(tsk)); dump_backtrace(regs, tsk); dump_instr(KERN_EMERG, regs); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Russell King7748.73%1050.00%
Linus Torvalds (pre-git)5534.81%420.00%
Linus Torvalds85.06%210.00%
Rabin Vincent74.43%15.00%
Andrew Morton53.16%15.00%
Alexey Dobriyan31.90%15.00%
Al Viro31.90%15.00%
Total158100.00%20100.00%

static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED; static int die_owner = -1; static unsigned int die_nest_count;
static unsigned long oops_begin(void) { int cpu; unsigned long flags; oops_enter(); /* racy, but better than risking deadlock. */ raw_local_irq_save(flags); cpu = smp_processor_id(); if (!arch_spin_trylock(&die_lock)) { if (cpu == die_owner) /* nested oops. should stop eventually */; else arch_spin_lock(&die_lock); } die_nest_count++; die_owner = cpu; console_verbose(); bust_spinlocks(1); return flags; }

Contributors

PersonTokensPropCommitsCommitProp
Rabin Vincent4662.16%114.29%
Russell King1722.97%457.14%
Simon Glass68.11%114.29%
Stephen Boyd56.76%114.29%
Total74100.00%7100.00%


static void oops_end(unsigned long flags, struct pt_regs *regs, int signr) { if (regs && kexec_should_crash(current)) crash_kexec(regs); bust_spinlocks(0); die_owner = -1; add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); die_nest_count--; if (!die_nest_count) /* Nest count reaches zero, release the lock. */ arch_spin_unlock(&die_lock); raw_local_irq_restore(flags); oops_exit(); if (in_interrupt()) panic("Fatal exception in interrupt"); if (panic_on_oops) panic("Fatal exception"); if (signr) do_exit(signr); }

Contributors

PersonTokensPropCommitsCommitProp
Rabin Vincent4343.00%18.33%
Russell King4242.00%541.67%
Linus Torvalds (pre-git)77.00%325.00%
Pavel Emelyanov55.00%18.33%
Rusty Russell22.00%18.33%
Simon Horman11.00%18.33%
Total100100.00%12100.00%

/* * This function is protected against re-entrancy. */
void die(const char *str, struct pt_regs *regs, int err) { enum bug_trap_type bug_type = BUG_TRAP_TYPE_NONE; unsigned long flags = oops_begin(); int sig = SIGSEGV; if (!user_mode(regs)) bug_type = report_bug(regs->ARM_pc, regs); if (bug_type != BUG_TRAP_TYPE_NONE) str = "Oops - BUG"; if (__die(str, err, regs)) sig = 0; oops_end(flags, regs, sig); }

Contributors

PersonTokensPropCommitsCommitProp
Rabin Vincent8595.51%133.33%
Linus Torvalds (pre-git)44.49%266.67%
Total89100.00%3100.00%


void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info, unsigned long err, unsigned long trap) { if (user_mode(regs)) { current->thread.error_code = err; current->thread.trap_no = trap; force_sig_info(info->si_signo, info, current); } else { die(str, regs, err); } }

Contributors

PersonTokensPropCommitsCommitProp
Russell King7598.68%266.67%
Christoph Hellwig11.32%133.33%
Total76100.00%3100.00%

#ifdef CONFIG_GENERIC_BUG
int is_valid_bugaddr(unsigned long pc) { #ifdef CONFIG_THUMB2_KERNEL u16 bkpt; u16 insn = __opcode_to_mem_thumb16(BUG_INSTR_VALUE); #else u32 bkpt; u32 insn = __opcode_to_mem_arm(BUG_INSTR_VALUE); #endif if (probe_kernel_address((unsigned *)pc, bkpt)) return 0; return bkpt == insn; }

Contributors

PersonTokensPropCommitsCommitProp
Simon Glass4067.80%150.00%
Ben Dooks1932.20%150.00%
Total59100.00%2100.00%

#endif static LIST_HEAD(undef_hook); static DEFINE_RAW_SPINLOCK(undef_lock);
void register_undef_hook(struct undef_hook *hook) { unsigned long flags; raw_spin_lock_irqsave(&undef_lock, flags); list_add(&hook->node, &undef_hook); raw_spin_unlock_irqrestore(&undef_lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Russell King3995.12%266.67%
Thomas Gleixner24.88%133.33%
Total41100.00%3100.00%


void unregister_undef_hook(struct undef_hook *hook) { unsigned long flags; raw_spin_lock_irqsave(&undef_lock, flags); list_del(&hook->node); raw_spin_unlock_irqrestore(&undef_lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Russell King3694.74%266.67%
Thomas Gleixner25.26%133.33%
Total38100.00%3100.00%


static int call_undef_hook(struct pt_regs *regs, unsigned int instr) { struct undef_hook *hook; unsigned long flags; int (*fn)(struct pt_regs *regs, unsigned int instr) = NULL; raw_spin_lock_irqsave(&undef_lock, flags); list_for_each_entry(hook, &undef_hook, node) if ((instr & hook->instr_mask) == hook->instr_val && (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) fn = hook->fn; raw_spin_unlock_irqrestore(&undef_lock, flags); return fn ? fn(regs, instr) : 1; }

Contributors

PersonTokensPropCommitsCommitProp
Russell King11098.21%150.00%
Thomas Gleixner21.79%150.00%
Total112100.00%2100.00%


asmlinkage void __exception do_undefinstr(struct pt_regs *regs) { unsigned int instr; siginfo_t info; void __user *pc; pc = (void __user *)instruction_pointer(regs); if (processor_mode(regs) == SVC_MODE) { #ifdef CONFIG_THUMB2_KERNEL if (thumb_mode(regs)) { instr = __mem_to_opcode_thumb16(((u16 *)pc)[0]); if (is_wide_instruction(instr)) { u16 inst2; inst2 = __mem_to_opcode_thumb16(((u16 *)pc)[1]); instr = __opcode_thumb32_compose(instr, inst2); } } else #endif instr = __mem_to_opcode_arm(*(u32 *) pc); } else if (thumb_mode(regs)) { if (get_user(instr, (u16 __user *)pc)) goto die_sig; instr = __mem_to_opcode_thumb16(instr); if (is_wide_instruction(instr)) { unsigned int instr2; if (get_user(instr2, (u16 __user *)pc+1)) goto die_sig; instr2 = __mem_to_opcode_thumb16(instr2); instr = __opcode_thumb32_compose(instr, instr2); } } else { if (get_user(instr, (u32 __user *)pc)) goto die_sig; instr = __mem_to_opcode_arm(instr); } if (call_undef_hook(regs, instr) == 0) return; die_sig: #ifdef CONFIG_DEBUG_USER if (user_debug & UDBG_UNDEFINED) { pr_info("%s (%d): undefined instruction: pc=%p\n", current->comm, task_pid_nr(current), pc); __show_regs(regs); dump_instr(KERN_INFO, regs); } #endif info.si_signo = SIGILL; info.si_errno = 0; info.si_code = ILL_ILLOPC; info.si_addr = pc; arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6); }

Contributors

PersonTokensPropCommitsCommitProp
Jon Medhurst (Tixy)7823.71%14.35%
Russell King7322.19%939.13%
Linus Torvalds (pre-git)6519.76%417.39%
Ben Dooks4914.89%14.35%
Dan J Williams216.38%14.35%
Will Deacon175.17%14.35%
Linus Torvalds133.95%28.70%
Taras Kondratiuk51.52%14.35%
Al Viro41.22%14.35%
Alexey Dobriyan30.91%14.35%
Christoph Hellwig10.30%14.35%
Total329100.00%23100.00%

/* * Handle FIQ similarly to NMI on x86 systems. * * The runtime environment for NMIs is extremely restrictive * (NMIs can pre-empt critical sections meaning almost all locking is * forbidden) meaning this default FIQ handling must only be used in * circumstances where non-maskability improves robustness, such as * watchdog or debug logic. * * This handler is not appropriate for general purpose use in drivers * platform code and can be overrideen using set_fiq_handler. */
asmlinkage void __exception_irq_entry handle_fiq_as_nmi(struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); nmi_enter(); /* nop. FIQ handlers for special arch/arm features can be added here. */ nmi_exit(); set_irq_regs(old_regs); }

Contributors

PersonTokensPropCommitsCommitProp
Daniel R Thompson34100.00%1100.00%
Total34100.00%1100.00%

/* * bad_mode handles the impossible case in the vectors. If you see one of * these, then it's extremely serious, and could mean you have buggy hardware. * It never returns, and never tries to sync. We hope that we can at least * dump out some state information... */
asmlinkage void bad_mode(struct pt_regs *regs, int reason) { console_verbose(); pr_crit("Bad mode in %s handler detected\n", handler[reason]); die("Oops - bad mode", regs, 0); local_irq_disable(); panic("bad mode"); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)4090.91%342.86%
Russell King49.09%457.14%
Total44100.00%7100.00%


static int bad_syscall(int n, struct pt_regs *regs) { siginfo_t info; if ((current->personality & PER_MASK) != PER_LINUX) { send_sig(SIGSEGV, current, 1); return regs->ARM_r0; } #ifdef CONFIG_DEBUG_USER if (user_debug & UDBG_SYSCALL) { pr_err("[%d] %s: obsolete system call %08x.\n", task_pid_nr(current), current->comm, n); dump_instr(KERN_ERR, regs); } #endif info.si_signo = SIGILL; info.si_errno = 0; info.si_code = ILL_ILLTRP; info.si_addr = (void __user *)instruction_pointer(regs) - (thumb_mode(regs) ? 2 : 4); arm_notify_die("Oops - bad syscall", regs, &info, n, 0); return regs->ARM_r0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds11278.32%19.09%
Russell King1711.89%545.45%
Richard Weinberger53.50%19.09%
Nico Pitre42.80%19.09%
Alexey Dobriyan32.10%19.09%
Al Viro10.70%19.09%
Christoph Hellwig10.70%19.09%
Total143100.00%11100.00%


static inline int __do_cache_op(unsigned long start, unsigned long end) { int ret; do { unsigned long chunk = min(PAGE_SIZE, end - start); if (fatal_signal_pending(current)) return 0; ret = flush_cache_user_range(start, start + chunk); if (ret) return ret; cond_resched(); start += chunk; } while (start < end); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Will Deacon4050.63%233.33%
Russell King2835.44%233.33%
Jon Medhurst (Tixy)911.39%116.67%
Vladimir Murzin22.53%116.67%
Total79100.00%6100.00%


static inline int do_cache_op(unsigned long start, unsigned long end, int flags) { if (end < start || flags) return -EINVAL; if (!access_ok(VERIFY_READ, start, end - start)) return -EFAULT; return __do_cache_op(start, end); }

Contributors

PersonTokensPropCommitsCommitProp
Russell King3460.71%350.00%
Will Deacon2239.29%350.00%
Total56100.00%6100.00%

/* * Handle all unrecognised system calls. * 0x9f0000 - 0x9fffff are some more esoteric system calls */ #define NR(x) ((__ARM_NR_##x) - __ARM_NR_BASE)
asmlinkage int arm_syscall(int no, struct pt_regs *regs) { siginfo_t info; if ((no >> 16) != (__ARM_NR_BASE>> 16)) return bad_syscall(no, regs); switch (no & 0xffff) { case 0: /* branch through 0 */ info.si_signo = SIGSEGV; info.si_errno = 0; info.si_code = SEGV_MAPERR; info.si_addr = NULL; arm_notify_die("branch through zero", regs, &info, 0, 0); return 0; case NR(breakpoint): /* SWI BREAK_POINT */ regs->ARM_pc -= thumb_mode(regs) ? 2 : 4; ptrace_break(current, regs); return regs->ARM_r0; /* * Flush a region from virtual address 'r0' to virtual address 'r1' * _exclusive_. There is no alignment requirement on either address; * user space does not need to know the hardware cache layout. * * r2 contains flags. It should ALWAYS be passed as ZERO until it * is defined to be something else. For now we ignore it, but may * the fires of hell burn in your belly if you break this rule. ;) * * (at a later date, we may want to allow this call to not flush * various aspects of the cache. Passing '0' will guarantee that * everything necessary gets flushed to maintain consistency in * the specified region). */ case NR(cacheflush): return do_cache_op(regs->ARM_r0, regs->ARM_r1, regs->ARM_r2); case NR(usr26): if (!(elf_hwcap & HWCAP_26BIT)) break; regs->ARM_cpsr &= ~MODE32_BIT; return regs->ARM_r0; case NR(usr32): if (!(elf_hwcap & HWCAP_26BIT)) break; regs->ARM_cpsr |= MODE32_BIT; return regs->ARM_r0; case NR(set_tls): set_tls(regs->ARM_r0); return 0; default: /* Calls 9f00xx..9f07ff are defined to return -ENOSYS if not implemented, rather than raising SIGILL. This way the calling program can gracefully determine whether a feature is supported. */ if ((no & 0xffff) <= 0x7ff) return -ENOSYS; break; } #ifdef CONFIG_DEBUG_USER /* * experience shows that these seem to indicate that * something catastrophic has happened */ if (user_debug & UDBG_SYSCALL) { pr_err("[%d] %s: arm syscall %d\n", task_pid_nr(current), current->comm, no); dump_instr("", regs); if (user_mode(regs)) { __show_regs(regs); c_backtrace(frame_pointer(regs), processor_mode(regs)); } } #endif info.si_signo = SIGILL; info.si_errno = 0; info.si_code = ILL_ILLTRP; info.si_addr = (void __user *)instruction_pointer(regs) - (thumb_mode(regs) ? 2 : 4); arm_notify_die("Oops - bad syscall(2)", regs, &info, no, 0); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)15944.29%518.52%
Linus Torvalds12133.70%13.70%
Russell King4713.09%1140.74%
Nico Pitre195.29%414.81%
Alexey Dobriyan30.84%13.70%
Nikolay Borisov30.84%13.70%
Nathan Lynch30.84%13.70%
Christoph Hellwig20.56%13.70%
Will Deacon10.28%13.70%
Al Viro10.28%13.70%
Total359100.00%27100.00%

#ifdef CONFIG_TLS_REG_EMUL /* * We might be running on an ARMv6+ processor which should have the TLS * register but for some reason we can't use it, or maybe an SMP system * using a pre-ARMv6 processor (there are apparently a few prototypes like * that in existence) and therefore access to that register must be * emulated. */
static int get_tp_trap(struct pt_regs *regs, unsigned int instr) { int reg = (instr >> 12) & 15; if (reg == 15) return 1; regs->uregs[reg] = current_thread_info()->tp_value[0]; regs->ARM_pc += 4; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Nico Pitre5694.92%150.00%
André Hentschel35.08%150.00%
Total59100.00%2100.00%

static struct undef_hook arm_mrc_hook = { .instr_mask = 0x0fff0fff, .instr_val = 0x0e1d0f70, .cpsr_mask = PSR_T_BIT, .cpsr_val = 0, .fn = get_tp_trap, };
static int __init arm_mrc_hook_init(void) { register_undef_hook(&arm_mrc_hook); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Nico Pitre18100.00%1100.00%
Total18100.00%1100.00%

late_initcall(arm_mrc_hook_init); #endif /* * A data abort trap was taken, but we did not handle the instruction. * Try to abort the user program, or panic if it was the kernel. */
asmlinkage void baddataabort(int code, unsigned long instr, struct pt_regs *regs) { unsigned long addr = instruction_pointer(regs); siginfo_t info; #ifdef CONFIG_DEBUG_USER if (user_debug & UDBG_BADABORT) { pr_err("[%d] %s: bad data abort: code %d instr 0x%08lx\n", task_pid_nr(current), current->comm, code, instr); dump_instr(KERN_ERR, regs); show_pte(current->mm, addr); } #endif info.si_signo = SIGILL; info.si_errno = 0; info.si_code = ILL_ILLOPC; info.si_addr = (void __user *)addr; arm_notify_die("unknown data abort code", regs, &info, instr, 0); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)9982.50%436.36%
Russell King1613.33%436.36%
Alexey Dobriyan32.50%19.09%
Christoph Hellwig10.83%19.09%
Al Viro10.83%19.09%
Total120100.00%11100.00%


void __readwrite_bug(const char *fn) { pr_err("%s called, but not implemented\n", fn); BUG(); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)1890.00%250.00%
Russell King210.00%250.00%
Total20100.00%4100.00%

EXPORT_SYMBOL(__readwrite_bug);
void __pte_error(const char *file, int line, pte_t pte) { pr_err("%s:%d: bad pte %08llx.\n", file, line, (long long)pte_val(pte)); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2264.71%125.00%
Russell King720.59%250.00%
Will Deacon514.71%125.00%
Total34100.00%4100.00%


void __pmd_error(const char *file, int line, pmd_t pmd) { pr_err("%s:%d: bad pmd %08llx.\n", file, line, (long long)pmd_val(pmd)); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2264.71%125.00%
Russell King720.59%250.00%
Will Deacon514.71%125.00%
Total34100.00%4100.00%


void __pgd_error(const char *file, int line, pgd_t pgd) { pr_err("%s:%d: bad pgd %08llx.\n", file, line, (long long)pgd_val(pgd)); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2264.71%125.00%
Russell King720.59%250.00%
Will Deacon514.71%125.00%
Total34100.00%4100.00%


asmlinkage void __div0(void) { pr_err("Division by zero in kernel.\n"); dump_stack(); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)1487.50%250.00%
Russell King212.50%250.00%
Total16100.00%4100.00%

EXPORT_SYMBOL(__div0);
void abort(void) { BUG(); /* if that doesn't kill us, halt */ panic("Oops failed to kill thread"); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)16100.00%2100.00%
Total16100.00%2100.00%

EXPORT_SYMBOL(abort);
void __init trap_init(void) { return; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)666.67%150.00%
Jason Wessel333.33%150.00%
Total9100.00%2100.00%

#ifdef CONFIG_KUSER_HELPERS
static void __init kuser_init(void *vectors) { extern char __kuser_helper_start[], __kuser_helper_end[]; int kuser_sz = __kuser_helper_end - __kuser_helper_start; memcpy(vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz); /* * vectors + 0xfe0 = __kuser_get_tls * vectors + 0xfe8 = hardware TLS instruction at 0xffff0fe8 */ if (tls_emu || has_tls_reg) memcpy(vectors + 0xfe0, vectors + 0xfe8, 4); }

Contributors

PersonTokensPropCommitsCommitProp
Russell King3152.54%150.00%
Tony Lindgren2847.46%150.00%
Total59100.00%2100.00%

#else
static inline void __init kuser_init(void *vectors) { }

Contributors

PersonTokensPropCommitsCommitProp
Russell King1090.91%150.00%
Olof Johansson19.09%150.00%
Total11100.00%2100.00%

#endif
void __init early_trap_init(void *vectors_base) { #ifndef CONFIG_CPU_V7M unsigned long vectors = (unsigned long)vectors_base; extern char __stubs_start[], __stubs_end[]; extern char __vectors_start[], __vectors_end[]; unsigned i; vectors_page = vectors_base; /* * Poison the vectors page with an undefined instruction. This * instruction is chosen to be undefined for both ARM and Thumb * ISAs. The Thumb version is an undefined instruction with a * branch back to the undefined instruction. */ for (i = 0; i < PAGE_SIZE / sizeof(u32); i++) ((u32 *)vectors_base)[i] = 0xe7fddef1; /* * Copy the vectors, stubs and kuser helpers (in entry-armv.S) * into the vector page, mapped at 0xffff0000, and ensure these * are visible to the instruction stream. */ memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); memcpy((void *)vectors + 0x1000, __stubs_start, __stubs_end - __stubs_start); kuser_init(vectors_base); flush_icache_range(vectors, vectors + PAGE_SIZE * 2); #else /* ifndef CONFIG_CPU_V7M */ /* * on V7-M there is no need to copy the vector table to a dedicated * memory area. The address is configurable and so a table in the kernel * image can be used. */ #endif }

Contributors

PersonTokensPropCommitsCommitProp
Russell King9269.17%746.67%
Catalin Marinas1813.53%213.33%
Jason Wessel64.51%16.67%
Linus Torvalds (pre-git)64.51%16.67%
Hyok S. Choi53.76%16.67%
Tony Lindgren32.26%16.67%
Linus Torvalds21.50%16.67%
Nico Pitre10.75%16.67%
Total133100.00%15100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Russell King132137.22%5843.94%
Linus Torvalds (pre-git)93526.35%139.85%
Linus Torvalds3058.59%64.55%
Rabin Vincent1985.58%10.76%
Nico Pitre1413.97%64.55%
Catalin Marinas1173.30%43.03%
Will Deacon972.73%64.55%
Jon Medhurst (Tixy)872.45%21.52%
Ben Dooks712.00%21.52%
Simon Glass541.52%10.76%
Daniel R Thompson381.07%10.76%
Tony Lindgren340.96%10.76%
Dan J Williams210.59%10.76%
Alexey Dobriyan150.42%10.76%
Al Viro130.37%32.27%
Joe Perches100.28%10.76%
Thomas Gleixner100.28%21.52%
Jason Wessel90.25%10.76%
Nikolay Borisov90.25%10.76%
Ingo Molnar70.20%32.27%
Christoph Hellwig60.17%10.76%
Richard Weinberger50.14%10.76%
Stephen Boyd50.14%10.76%
Hyok S. Choi50.14%10.76%
Taras Kondratiuk50.14%10.76%
Andrew Morton50.14%10.76%
Pavel Emelyanov50.14%10.76%
Jamie Iles30.08%10.76%
André Hentschel30.08%10.76%
Marc Singer30.08%10.76%
Nathan Lynch30.08%10.76%
Rusty Russell20.06%10.76%
Vladimir Murzin20.06%10.76%
Simon Horman10.03%10.76%
Arun Sharma10.03%10.76%
Olof Johansson10.03%10.76%
Geert Uytterhoeven10.03%10.76%
David Howells10.03%10.76%
Total3549100.00%132100.00%
Directory: arch/arm/kernel
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.