aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/parisc')
-rw-r--r--arch/parisc/include/asm/ftrace.h14
-rw-r--r--arch/parisc/kernel/unwind.c27
2 files changed, 41 insertions, 0 deletions
diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h
index 2fa05dd6aeee..72c0fafaa039 100644
--- a/arch/parisc/include/asm/ftrace.h
+++ b/arch/parisc/include/asm/ftrace.h
@@ -20,6 +20,20 @@ struct ftrace_ret_stack {
20 * Defined in entry.S 20 * Defined in entry.S
21 */ 21 */
22extern void return_to_handler(void); 22extern void return_to_handler(void);
23
24
25extern unsigned long return_address(unsigned int);
26
27#define HAVE_ARCH_CALLER_ADDR
28
29#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
30#define CALLER_ADDR1 return_address(1)
31#define CALLER_ADDR2 return_address(2)
32#define CALLER_ADDR3 return_address(3)
33#define CALLER_ADDR4 return_address(4)
34#define CALLER_ADDR5 return_address(5)
35#define CALLER_ADDR6 return_address(6)
36
23#endif /* __ASSEMBLY__ */ 37#endif /* __ASSEMBLY__ */
24 38
25#endif /* _ASM_PARISC_FTRACE_H */ 39#endif /* _ASM_PARISC_FTRACE_H */
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
index a36799e85693..f03f6fb0ec83 100644
--- a/arch/parisc/kernel/unwind.c
+++ b/arch/parisc/kernel/unwind.c
@@ -417,3 +417,30 @@ int unwind_to_user(struct unwind_frame_info *info)
417 417
418 return ret; 418 return ret;
419} 419}
420
421unsigned long return_address(unsigned int level)
422{
423 struct unwind_frame_info info;
424 struct pt_regs r;
425 unsigned long sp;
426
427 /* initialize unwind info */
428 asm volatile ("copy %%r30, %0" : "=r"(sp));
429 memset(&r, 0, sizeof(struct pt_regs));
430 r.iaoq[0] = (unsigned long) current_text_addr();
431 r.gr[2] = (unsigned long) __builtin_return_address(0);
432 r.gr[30] = sp;
433 unwind_frame_init(&info, current, &r);
434
435 /* unwind stack */
436 ++level;
437 do {
438 if (unwind_once(&info) < 0 || info.ip == 0)
439 return 0;
440 if (!__kernel_text_address(info.ip)) {
441 return 0;
442 }
443 } while (info.ip && level--);
444
445 return info.ip;
446}