Skip to content
traps.c 60.6 KiB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 1994 - 1999, 2000, 01, 06 Ralf Baechle
Linus Torvalds's avatar
Linus Torvalds committed
 * Copyright (C) 1995, 1996 Paul M. Antoine
 * Copyright (C) 1998 Ulf Carlsson
 * Copyright (C) 1999 Silicon Graphics, Inc.
 * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
 * Copyright (C) 2002, 2003, 2004, 2005, 2007  Maciej W. Rozycki
 * Copyright (C) 2000, 2001, 2012 MIPS Technologies, Inc.  All rights reserved.
 * Copyright (C) 2014, Imagination Technologies Ltd.
Linus Torvalds's avatar
Linus Torvalds committed
 */
#include <linux/bitops.h>
#include <linux/compiler.h>
#include <linux/context_tracking.h>
#include <linux/cpu_pm.h>
Ralf Baechle's avatar
Ralf Baechle committed
#include <linux/kexec.h>
Linus Torvalds's avatar
Linus Torvalds committed
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
Linus Torvalds's avatar
Linus Torvalds committed
#include <linux/mm.h>
Linus Torvalds's avatar
Linus Torvalds committed
#include <linux/smp.h>
#include <linux/spinlock.h>
#include <linux/kallsyms.h>
#include <linux/memblock.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/kgdb.h>
#include <linux/kdebug.h>
David Daney's avatar
David Daney committed
#include <linux/kprobes.h>
#include <linux/notifier.h>
#include <linux/kdb.h>
#include <linux/irq.h>
#include <linux/perf_event.h>
Linus Torvalds's avatar
Linus Torvalds committed

#include <asm/addrspace.h>
Linus Torvalds's avatar
Linus Torvalds committed
#include <asm/bootinfo.h>
#include <asm/branch.h>
#include <asm/break.h>
#include <asm/cop2.h>
Linus Torvalds's avatar
Linus Torvalds committed
#include <asm/cpu.h>
#include <asm/cpu-type.h>
#include <asm/dsp.h>
Linus Torvalds's avatar
Linus Torvalds committed
#include <asm/fpu.h>
#include <asm/fpu_emulator.h>
#include <asm/isa-rev.h>
#include <asm/mips-cps.h>
#include <asm/mips-r2-to-r6-emul.h>
#include <asm/mipsregs.h>
#include <asm/mipsmtregs.h>
Linus Torvalds's avatar
Linus Torvalds committed
#include <asm/module.h>
#include <asm/msa.h>
Linus Torvalds's avatar
Linus Torvalds committed
#include <asm/pgtable.h>
#include <asm/ptrace.h>
#include <asm/sections.h>
Linus Torvalds's avatar
Linus Torvalds committed
#include <asm/tlbdebug.h>
#include <asm/traps.h>
#include <linux/uaccess.h>
#include <asm/watch.h>
Linus Torvalds's avatar
Linus Torvalds committed
#include <asm/mmu_context.h>
#include <asm/types.h>
#include <asm/tlbex.h>
#include <asm/uasm.h>
Linus Torvalds's avatar
Linus Torvalds committed

extern void check_wait(void);
extern asmlinkage void rollback_handle_int(void);
extern asmlinkage void handle_int(void);
Linus Torvalds's avatar
Linus Torvalds committed
extern asmlinkage void handle_adel(void);
extern asmlinkage void handle_ades(void);
extern asmlinkage void handle_ibe(void);
extern asmlinkage void handle_dbe(void);
extern asmlinkage void handle_sys(void);
extern asmlinkage void handle_bp(void);
extern asmlinkage void handle_ri(void);
extern asmlinkage void handle_ri_rdhwr_tlbp(void);
extern asmlinkage void handle_ri_rdhwr(void);
Linus Torvalds's avatar
Linus Torvalds committed
extern asmlinkage void handle_cpu(void);
extern asmlinkage void handle_ov(void);
extern asmlinkage void handle_tr(void);
extern asmlinkage void handle_msa_fpe(void);
Linus Torvalds's avatar
Linus Torvalds committed
extern asmlinkage void handle_fpe(void);
extern asmlinkage void handle_ftlb(void);
extern asmlinkage void handle_msa(void);
Linus Torvalds's avatar
Linus Torvalds committed
extern asmlinkage void handle_mdmx(void);
extern asmlinkage void handle_watch(void);
extern asmlinkage void handle_mt(void);
extern asmlinkage void handle_dsp(void);
Linus Torvalds's avatar
Linus Torvalds committed
extern asmlinkage void handle_mcheck(void);
extern asmlinkage void handle_reserved(void);
extern void tlb_do_page_fault_0(void);
Linus Torvalds's avatar
Linus Torvalds committed

void (*board_be_init)(void);
int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
void (*board_nmi_handler_setup)(void);
void (*board_ejtag_handler_setup)(void);
void (*board_bind_eic_interrupt)(int irq, int regset);
void (*board_ebase_setup)(void);
void(*board_cache_error_setup)(void);
Linus Torvalds's avatar
Linus Torvalds committed

static void show_raw_backtrace(unsigned long reg29)
	unsigned long *sp = (unsigned long *)(reg29 & ~3);
	unsigned long addr;

	printk("Call Trace:");
#ifdef CONFIG_KALLSYMS
	printk("\n");
#endif
	while (!kstack_end(sp)) {
		unsigned long __user *p =
			(unsigned long __user *)(unsigned long)sp++;
		if (__get_user(addr, p)) {
			printk(" (Bad stack address)");
			break;
		if (__kernel_text_address(addr))
			print_ip_sym(addr);
#ifdef CONFIG_KALLSYMS
static int __init set_raw_show_trace(char *str)
{
	raw_show_trace = 1;
	return 1;
}
__setup("raw_show_trace", set_raw_show_trace);
Ralf Baechle's avatar
Ralf Baechle committed
static void show_backtrace(struct task_struct *task, const struct pt_regs *regs)
	unsigned long sp = regs->regs[29];
	unsigned long ra = regs->regs[31];
	unsigned long pc = regs->cp0_epc;

	if (!task)
		task = current;

	if (raw_show_trace || user_mode(regs) || !__kernel_text_address(pc)) {
		show_raw_backtrace(sp);
		return;
	}
	printk("Call Trace:\n");
		pc = unwind_stack(task, &sp, pc, &ra);
	} while (pc);
	pr_cont("\n");
Linus Torvalds's avatar
Linus Torvalds committed
/*
 * This routine abuses get_user()/put_user() to reference pointers
 * with at least a bit of error checking ...
 */
Ralf Baechle's avatar
Ralf Baechle committed
static void show_stacktrace(struct task_struct *task,
	const struct pt_regs *regs)
Linus Torvalds's avatar
Linus Torvalds committed
{
	const int field = 2 * sizeof(unsigned long);
	long stackdata;
	int i;
	unsigned long __user *sp = (unsigned long __user *)regs->regs[29];
Linus Torvalds's avatar
Linus Torvalds committed

	printk("Stack :");
	i = 0;
	while ((unsigned long) sp & (PAGE_SIZE - 1)) {
		if (i && ((i % (64 / field)) == 0)) {
			pr_cont("\n");
			printk("       ");
		}
Linus Torvalds's avatar
Linus Torvalds committed
		if (i > 39) {
			pr_cont(" ...");
Linus Torvalds's avatar
Linus Torvalds committed
			break;
		}

		if (__get_user(stackdata, sp++)) {
			pr_cont(" (Bad stack address)");
Linus Torvalds's avatar
Linus Torvalds committed
			break;
		}

		pr_cont(" %0*lx", field, stackdata);
Linus Torvalds's avatar
Linus Torvalds committed
		i++;
	}
	show_backtrace(task, regs);
}

void show_stack(struct task_struct *task, unsigned long *sp)
{
	struct pt_regs regs;
Loading
Loading full blame...