diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 27 | ||||
-rw-r--r-- | arch/powerpc/kernel/ftrace.c | 13 |
2 files changed, 37 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 9f61fd61f277..abfc32330479 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -971,6 +971,28 @@ _GLOBAL(ftrace_graph_caller) | |||
971 | 971 | ||
972 | _GLOBAL(return_to_handler) | 972 | _GLOBAL(return_to_handler) |
973 | /* need to save return values */ | 973 | /* need to save return values */ |
974 | std r4, -24(r1) | ||
975 | std r3, -16(r1) | ||
976 | std r31, -8(r1) | ||
977 | mr r31, r1 | ||
978 | stdu r1, -112(r1) | ||
979 | |||
980 | bl .ftrace_return_to_handler | ||
981 | nop | ||
982 | |||
983 | /* return value has real return address */ | ||
984 | mtlr r3 | ||
985 | |||
986 | ld r1, 0(r1) | ||
987 | ld r4, -24(r1) | ||
988 | ld r3, -16(r1) | ||
989 | ld r31, -8(r1) | ||
990 | |||
991 | /* Jump back to real return address */ | ||
992 | blr | ||
993 | |||
994 | _GLOBAL(mod_return_to_handler) | ||
995 | /* need to save return values */ | ||
974 | std r4, -32(r1) | 996 | std r4, -32(r1) |
975 | std r3, -24(r1) | 997 | std r3, -24(r1) |
976 | /* save TOC */ | 998 | /* save TOC */ |
@@ -979,7 +1001,10 @@ _GLOBAL(return_to_handler) | |||
979 | mr r31, r1 | 1001 | mr r31, r1 |
980 | stdu r1, -112(r1) | 1002 | stdu r1, -112(r1) |
981 | 1003 | ||
982 | /* update the TOC */ | 1004 | /* |
1005 | * We are in a module using the module's TOC. | ||
1006 | * Switch to our TOC to run inside the core kernel. | ||
1007 | */ | ||
983 | LOAD_REG_IMMEDIATE(r4,ftrace_return_to_handler) | 1008 | LOAD_REG_IMMEDIATE(r4,ftrace_return_to_handler) |
984 | ld r2, 8(r4) | 1009 | ld r2, 8(r4) |
985 | 1010 | ||
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c index 7538b944fa52..5c6dfa97e838 100644 --- a/arch/powerpc/kernel/ftrace.c +++ b/arch/powerpc/kernel/ftrace.c | |||
@@ -567,6 +567,10 @@ int ftrace_disable_ftrace_graph_caller(void) | |||
567 | } | 567 | } |
568 | #endif /* CONFIG_DYNAMIC_FTRACE */ | 568 | #endif /* CONFIG_DYNAMIC_FTRACE */ |
569 | 569 | ||
570 | #ifdef CONFIG_PPC64 | ||
571 | extern void mod_return_to_handler(void); | ||
572 | #endif | ||
573 | |||
570 | /* | 574 | /* |
571 | * Hook the return address and push it in the stack of return addrs | 575 | * Hook the return address and push it in the stack of return addrs |
572 | * in current thread info. | 576 | * in current thread info. |
@@ -577,12 +581,17 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) | |||
577 | unsigned long long calltime; | 581 | unsigned long long calltime; |
578 | int faulted; | 582 | int faulted; |
579 | struct ftrace_graph_ent trace; | 583 | struct ftrace_graph_ent trace; |
580 | unsigned long return_hooker = (unsigned long) | 584 | unsigned long return_hooker = (unsigned long)&return_to_handler; |
581 | &return_to_handler; | ||
582 | 585 | ||
583 | if (unlikely(atomic_read(¤t->tracing_graph_pause))) | 586 | if (unlikely(atomic_read(¤t->tracing_graph_pause))) |
584 | return; | 587 | return; |
585 | 588 | ||
589 | #if CONFIG_PPC64 | ||
590 | /* non core kernel code needs to save and restore the TOC */ | ||
591 | if (REGION_ID(self_addr) != KERNEL_REGION_ID) | ||
592 | return_hooker = (unsigned long)&mod_return_to_handler; | ||
593 | #endif | ||
594 | |||
586 | return_hooker = GET_ADDR(return_hooker); | 595 | return_hooker = GET_ADDR(return_hooker); |
587 | 596 | ||
588 | /* | 597 | /* |