Commit e27d6cbf authored by Thomas Gleixner's avatar Thomas Gleixner

Merge branch 'rt/arm' into rt/base

parents 71323cb4 91e45cb1
...@@ -11,4 +11,38 @@ extern void mcount(void); ...@@ -11,4 +11,38 @@ extern void mcount(void);
#endif #endif
#ifndef __ASSEMBLY__
#if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
/*
* return_address uses walk_stackframe to do it's work. If both
* CONFIG_FRAME_POINTER=y and CONFIG_ARM_UNWIND=y walk_stackframe uses unwind
* information. For this to work in the function tracer many functions would
* have to be marked with __notrace. So for now just depend on
* !CONFIG_ARM_UNWIND.
*/
void *return_address(unsigned int);
#else
extern inline void *return_address(unsigned int level)
{
return NULL;
}
#endif
#define HAVE_ARCH_CALLER_ADDR
#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
#define CALLER_ADDR1 ((unsigned long)return_address(1))
#define CALLER_ADDR2 ((unsigned long)return_address(2))
#define CALLER_ADDR3 ((unsigned long)return_address(3))
#define CALLER_ADDR4 ((unsigned long)return_address(4))
#define CALLER_ADDR5 ((unsigned long)return_address(5))
#define CALLER_ADDR6 ((unsigned long)return_address(6))
#endif /* ifndef __ASSEMBLY__ */
#endif /* _ASM_ARM_FTRACE */ #endif /* _ASM_ARM_FTRACE */
...@@ -8,10 +8,12 @@ ifdef CONFIG_DYNAMIC_FTRACE ...@@ -8,10 +8,12 @@ ifdef CONFIG_DYNAMIC_FTRACE
CFLAGS_REMOVE_ftrace.o = -pg CFLAGS_REMOVE_ftrace.o = -pg
endif endif
CFLAGS_REMOVE_return_address.o = -pg
# Object file lists. # Object file lists.
obj-y := compat.o elf.o entry-armv.o entry-common.o irq.o \ obj-y := compat.o elf.o entry-armv.o entry-common.o irq.o \
process.o ptrace.o setup.o signal.o \ process.o ptrace.o return_address.o setup.o signal.o \
sys_arm.o stacktrace.o time.o traps.o sys_arm.o stacktrace.o time.o traps.o
obj-$(CONFIG_ISA_DMA_API) += dma.o obj-$(CONFIG_ISA_DMA_API) += dma.o
......
...@@ -148,7 +148,7 @@ trace: ...@@ -148,7 +148,7 @@ trace:
sub r0, r0, #MCOUNT_INSN_SIZE sub r0, r0, #MCOUNT_INSN_SIZE
mov lr, pc mov lr, pc
mov pc, r2 mov pc, r2
mov lr, r1 @ restore lr ldr lr, [fp, #-4] @ restore lr
ldmia sp!, {r0-r3, pc} ldmia sp!, {r0-r3, pc}
#endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* CONFIG_DYNAMIC_FTRACE */
......
/*
* arch/arm/kernel/return_address.c
*
* Copyright (C) 2009 Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
* for Pengutronix
*
* 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.
*/
#include <linux/module.h>
#if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
#include <linux/sched.h>
#include <asm/stacktrace.h>
struct return_address_data {
unsigned int level;
void *addr;
};
static int save_return_addr(struct stackframe *frame, void *d)
{
struct return_address_data *data = d;
if (!data->level) {
data->addr = (void *)frame->lr;
return 1;
} else {
--data->level;
return 0;
}
}
void *return_address(unsigned int level)
{
struct return_address_data data;
struct stackframe frame;
register unsigned long current_sp asm ("sp");
data.level = level + 1;
frame.fp = (unsigned long)__builtin_frame_address(0);
frame.sp = current_sp;
frame.lr = (unsigned long)__builtin_return_address(0);
frame.pc = (unsigned long)return_address;
walk_stackframe(&frame, save_return_addr, &data);
if (!data.level)
return data.addr;
else
return NULL;
}
#else /* if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) */
#if defined(CONFIG_ARM_UNWIND)
#warning "TODO: return_address should use unwind tables"
#endif
void *return_address(unsigned int level)
{
return NULL;
}
#endif /* if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) / else */
EXPORT_SYMBOL_GPL(return_address);
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
* Note that with framepointer enabled, even the leaf functions have the same * Note that with framepointer enabled, even the leaf functions have the same
* prologue and epilogue, therefore we can ignore the LR value in this case. * prologue and epilogue, therefore we can ignore the LR value in this case.
*/ */
int unwind_frame(struct stackframe *frame) int notrace unwind_frame(struct stackframe *frame)
{ {
unsigned long high, low; unsigned long high, low;
unsigned long fp = frame->fp; unsigned long fp = frame->fp;
...@@ -43,7 +43,7 @@ int unwind_frame(struct stackframe *frame) ...@@ -43,7 +43,7 @@ int unwind_frame(struct stackframe *frame)
} }
#endif #endif
void walk_stackframe(struct stackframe *frame, void notrace walk_stackframe(struct stackframe *frame,
int (*fn)(struct stackframe *, void *), void *data) int (*fn)(struct stackframe *, void *), void *data)
{ {
while (1) { while (1) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment