[AVR32] Implement stacktrace support

Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>

+57
+3
arch/avr32/Kconfig
··· 24 24 config GENERIC_HARDIRQS 25 25 def_bool y 26 26 27 + config STACKTRACE_SUPPORT 28 + def_bool y 29 + 27 30 config HARDIRQS_SW_RESEND 28 31 def_bool y 29 32
+1
arch/avr32/kernel/Makefile
··· 11 11 obj-y += init_task.o switch_to.o cpu.o 12 12 obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o 13 13 obj-$(CONFIG_KPROBES) += kprobes.o 14 + obj-$(CONFIG_STACKTRACE) += stacktrace.o
+53
arch/avr32/kernel/stacktrace.c
··· 1 + /* 2 + * Stack trace management functions 3 + * 4 + * Copyright (C) 2007 Atmel Corporation 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + */ 10 + #include <linux/sched.h> 11 + #include <linux/stacktrace.h> 12 + #include <linux/thread_info.h> 13 + 14 + register unsigned long current_frame_pointer asm("r7"); 15 + 16 + struct stackframe { 17 + unsigned long lr; 18 + unsigned long fp; 19 + }; 20 + 21 + /* 22 + * Save stack-backtrace addresses into a stack_trace buffer. 23 + */ 24 + void save_stack_trace(struct stack_trace *trace) 25 + { 26 + unsigned long low, high; 27 + unsigned long fp; 28 + struct stackframe *frame; 29 + int skip = trace->skip; 30 + 31 + low = (unsigned long)task_stack_page(current); 32 + high = low + THREAD_SIZE; 33 + fp = current_frame_pointer; 34 + 35 + while (fp >= low && fp <= (high - 8)) { 36 + frame = (struct stackframe *)fp; 37 + 38 + if (skip) { 39 + skip--; 40 + } else { 41 + trace->entries[trace->nr_entries++] = frame->lr; 42 + if (trace->nr_entries >= trace->max_entries) 43 + break; 44 + } 45 + 46 + /* 47 + * The next frame must be at a higher address than the 48 + * current frame. 49 + */ 50 + low = fp + 8; 51 + fp = frame->fp; 52 + } 53 + }