Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f21efd45 authored by Paul Mundt's avatar Paul Mundt
Browse files

Merge branch 'sh/multi-unwinders' into sh-latest

parents 380622e9 3a898c0f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ config SUPERH32

config SUPERH64
	def_bool ARCH = "sh64"
	select KALLSYMS

config ARCH_DEFCONFIG
	string
+2 −0
Original line number Diff line number Diff line
@@ -10,6 +10,8 @@ enum die_val {
	DIE_SSTEP,
};

/* arch/sh/kernel/dumpstack.c */
extern void printk_address(unsigned long address, int reliable);
extern void dump_mem(const char *str, unsigned long bottom, unsigned long top);

#endif /* __ASM_SH_KDEBUG_H */
+41 −22
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@
#include <asm/ptrace.h>
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/unwinder.h>
#include <asm/stacktrace.h>

static u8 regcache[63];

@@ -199,8 +201,11 @@ static int lookup_prev_stack_frame(unsigned long fp, unsigned long pc,
	return 0;
}

/* Don't put this on the stack since we'll want to call sh64_unwind
 * when we're close to underflowing the stack anyway. */
/*
 * Don't put this on the stack since we'll want to call in to
 * sh64_unwinder_dump() when we're close to underflowing the stack
 * anyway.
 */
static struct pt_regs here_regs;

extern const char syscall_ret;
@@ -208,17 +213,19 @@ extern const char ret_from_syscall;
extern const char ret_from_exception;
extern const char ret_from_irq;

static void sh64_unwind_inner(struct pt_regs *regs);
static void sh64_unwind_inner(const struct stacktrace_ops *ops,
			      void *data, struct pt_regs *regs);

static void unwind_nested (unsigned long pc, unsigned long fp)
static inline void unwind_nested(const struct stacktrace_ops *ops, void *data,
				 unsigned long pc, unsigned long fp)
{
	if ((fp >= __MEMORY_START) &&
	    ((fp & 7) == 0)) {
		sh64_unwind_inner((struct pt_regs *) fp);
	}
	    ((fp & 7) == 0))
		sh64_unwind_inner(ops, data, (struct pt_regs *)fp);
}

static void sh64_unwind_inner(struct pt_regs *regs)
static void sh64_unwind_inner(const struct stacktrace_ops *ops,
			      void *data, struct pt_regs *regs)
{
	unsigned long pc, fp;
	int ofs = 0;
@@ -234,13 +241,13 @@ static void sh64_unwind_inner(struct pt_regs *regs)

		if (pc == ((unsigned long)&syscall_ret & ~1)) {
			printk("SYSCALL\n");
			unwind_nested(pc,fp);
			unwind_nested(ops, data, pc, fp);
			return;
		}

		if (pc == ((unsigned long)&ret_from_syscall & ~1)) {
			printk("SYSCALL (PREEMPTED)\n");
			unwind_nested(pc,fp);
			unwind_nested(ops, data, pc, fp);
			return;
		}

@@ -248,13 +255,13 @@ static void sh64_unwind_inner(struct pt_regs *regs)
		   it has 4 taken off it to look like the 'caller' */
		if (pc == ((unsigned long)&ret_from_exception & ~1)) {
			printk("EXCEPTION\n");
			unwind_nested(pc,fp);
			unwind_nested(ops, data, pc, fp);
			return;
		}

		if (pc == ((unsigned long)&ret_from_irq & ~1)) {
			printk("IRQ\n");
			unwind_nested(pc,fp);
			unwind_nested(ops, data, pc, fp);
			return;
		}

@@ -263,8 +270,7 @@ static void sh64_unwind_inner(struct pt_regs *regs)

		pc -= ofs;

		printk("[<%08lx>] ", pc);
		print_symbol("%s\n", pc);
		ops->address(data, pc, 1);

		if (first_pass) {
			/* If the innermost frame is a leaf function, it's
@@ -287,10 +293,13 @@ static void sh64_unwind_inner(struct pt_regs *regs)
	}

	printk("\n");

}

void sh64_unwind(struct pt_regs *regs)
static void sh64_unwinder_dump(struct task_struct *task,
			       struct pt_regs *regs,
			       unsigned long *sp,
			       const struct stacktrace_ops *ops,
			       void *data)
{
	if (!regs) {
		/*
@@ -320,7 +329,17 @@ void sh64_unwind(struct pt_regs *regs)
		);
	}

	printk("\nCall Trace:\n");
	sh64_unwind_inner(regs);
	sh64_unwind_inner(ops, data, regs);
}

static struct unwinder sh64_unwinder = {
	.name	= "sh64-unwinder",
	.dump	= sh64_unwinder_dump,
	.rating	= 150,
};

static int __init sh64_unwinder_init(void)
{
	return unwinder_register(&sh64_unwinder);
}
early_initcall(sh64_unwinder_init);
+58 −0
Original line number Diff line number Diff line
@@ -2,13 +2,48 @@
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
 *  Copyright (C) 2009  Matt Fleming
 *  Copyright (C) 2002 - 2012  Paul Mundt
 *
 * 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.
 */
#include <linux/kallsyms.h>
#include <linux/ftrace.h>
#include <linux/debug_locks.h>
#include <linux/kdebug.h>
#include <linux/export.h>
#include <linux/uaccess.h>
#include <asm/unwinder.h>
#include <asm/stacktrace.h>

void dump_mem(const char *str, unsigned long bottom, unsigned long top)
{
	unsigned long p;
	int i;

	printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);

	for (p = bottom & ~31; p < top; ) {
		printk("%04lx: ", p & 0xffff);

		for (i = 0; i < 8; i++, p += 4) {
			unsigned int val;

			if (p < bottom || p >= top)
				printk("         ");
			else {
				if (__get_user(val, (unsigned int __user *)p)) {
					printk("\n");
					return;
				}
				printk("%08x ", val);
			}
		}
		printk("\n");
	}
}

void printk_address(unsigned long address, int reliable)
{
	printk(" [<%p>] %s%pS\n", (void *) address,
@@ -106,3 +141,26 @@ void show_trace(struct task_struct *tsk, unsigned long *sp,

	debug_show_held_locks(tsk);
}

void show_stack(struct task_struct *tsk, unsigned long *sp)
{
	unsigned long stack;

	if (!tsk)
		tsk = current;
	if (tsk == current)
		sp = (unsigned long *)current_stack_pointer;
	else
		sp = (unsigned long *)tsk->thread.sp;

	stack = (unsigned long)sp;
	dump_mem("Stack: ", stack, THREAD_SIZE +
		 (unsigned long)task_stack_page(tsk));
	show_trace(tsk, sp, NULL);
}

void dump_stack(void)
{
	show_stack(NULL, NULL);
}
EXPORT_SYMBOL(dump_stack);
+0 −50
Original line number Diff line number Diff line
@@ -48,33 +48,6 @@
#define TRAP_ILLEGAL_SLOT_INST	13
#endif

static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
{
	unsigned long p;
	int i;

	printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);

	for (p = bottom & ~31; p < top; ) {
		printk("%04lx: ", p & 0xffff);

		for (i = 0; i < 8; i++, p += 4) {
			unsigned int val;

			if (p < bottom || p >= top)
				printk("         ");
			else {
				if (__get_user(val, (unsigned int __user *)p)) {
					printk("\n");
					return;
				}
				printk("%08x ", val);
			}
		}
		printk("\n");
	}
}

static DEFINE_SPINLOCK(die_lock);

void die(const char * str, struct pt_regs * regs, long err)
@@ -900,26 +873,3 @@ void __init trap_init(void)
	set_exception_table_vec(TRAP_UBC, breakpoint_trap_handler);
#endif
}

void show_stack(struct task_struct *tsk, unsigned long *sp)
{
	unsigned long stack;

	if (!tsk)
		tsk = current;
	if (tsk == current)
		sp = (unsigned long *)current_stack_pointer;
	else
		sp = (unsigned long *)tsk->thread.sp;

	stack = (unsigned long)sp;
	dump_mem("Stack: ", stack, THREAD_SIZE +
		 (unsigned long)task_stack_page(tsk));
	show_trace(tsk, sp, NULL);
}

void dump_stack(void)
{
	show_stack(NULL, NULL);
}
EXPORT_SYMBOL(dump_stack);
Loading