#include <linux/export.h>
#include <linux/magic.h>
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
#include <asm/ftrace.h>
#include <asm/ppc-opcode.h>
#include <asm/thread_info.h>
#include <asm/bug.h>
#include <asm/ptrace.h>
.macro ftrace_regs_entry allregs
PPC_STLU r1, -STACK_FRAME_MIN_SIZE(r1)
PPC_STLU r1,-SWITCH_FRAME_SIZE(r1)
.if \allregs == 1
SAVE_GPRS(11, 12, r1)
.endif
mflr r11
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
PPC_LL r12, -(MCOUNT_INSN_SIZE*2 + SZL)(r11)
PPC_LL r12, FTRACE_OPS_DIRECT_CALL(r12)
PPC_LCMPI r12, 0
.if \allregs == 1
bne .Lftrace_direct_call_regs
.else
bne .Lftrace_direct_call
.endif
#endif
PPC_STL r0, _LINK(r1)
PPC_STL r0, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE+LRSAVE(r1)
SAVE_GPR(0, r1)
SAVE_GPRS(3, 10, r1)
#ifdef CONFIG_PPC64
lbz r3, PACA_FTRACE_ENABLED(r13)
cmpdi r3, 0
beq ftrace_no_trace
#endif
.if \allregs == 1
SAVE_GPR(2, r1)
SAVE_GPRS(13, 31, r1)
.else
#if defined(CONFIG_LIVEPATCH_64) || defined(CONFIG_PPC_FTRACE_OUT_OF_LINE)
SAVE_GPR(14, r1)
#endif
.endif
addi r8, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
PPC_STL r8, GPR1(r1)
.if \allregs == 1
mfcr r7
mfmsr r8
mfctr r9
mfxer r10
.else
li r8, 0
.endif
#ifdef CONFIG_PPC64
std r2, STK_GOT(r1)
LOAD_PACA_TOC()
#endif
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
PPC_LL r5, -(MCOUNT_INSN_SIZE*2 + SZL)(r11)
PPC_LL r12, FTRACE_OPS_FUNC(r5)
mtctr r12
#else
#ifdef CONFIG_PPC64
LOAD_REG_ADDR(r3, function_trace_op)
ld r5,0(r3)
#else
lis r3,function_trace_op@ha
lwz r5,function_trace_op@l(r3)
#endif
#endif
PPC_STL r8, _MSR(r1)
.if \allregs == 1
PPC_STL r7, _CCR(r1)
PPC_STL r9, _CTR(r1)
PPC_STL r10, _XER(r1)
.endif
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
li r7, 0
PPC_STL r7, ORIG_GPR3(r1)
#endif
#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
.if \allregs == 0
SAVE_GPR(15, r1)
.endif
mr r15, r11
lwz r8, MCOUNT_INSN_SIZE(r11)
slwi r8, r8, 6
srawi r8, r8, 6
add r3, r11, r8
addi r11, r3, MCOUNT_INSN_SIZE
#else
subi r3, r11, MCOUNT_INSN_SIZE
#endif
PPC_STL r11, _NIP(r1)
PPC_STL r11, LRSAVE+SWITCH_FRAME_SIZE(r1)
#if defined(CONFIG_LIVEPATCH_64) || defined(CONFIG_PPC_FTRACE_OUT_OF_LINE)
mr r14, r11
#endif
mr r4, r0
addi r6, r1, STACK_INT_FRAME_REGS
.endm
.macro ftrace_regs_exit allregs
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
PPC_LL r3, ORIG_GPR3(r1)
PPC_LCMPI cr1, r3, 0
mtctr r3
#endif
PPC_LL r0, _LINK(r1)
#ifndef CONFIG_PPC_FTRACE_OUT_OF_LINE
PPC_LL r3, _NIP(r1)
#ifdef CONFIG_LIVEPATCH_64
cmpd r14, r3
#endif
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
beq cr1,2f
mtlr r3
b 3f
#endif
2: mtctr r3
mtlr r0
3:
#else
PPC_LL r3, _NIP(r1)
cmpd r14, r3
bne- 1f
mr r3, r15
1: mtlr r3
.if \allregs == 0
REST_GPR(15, r1)
.endif
#endif
.if \allregs == 1
REST_GPRS(2, 31, r1)
.else
REST_GPRS(3, 10, r1)
#if defined(CONFIG_LIVEPATCH_64) || defined(CONFIG_PPC_FTRACE_OUT_OF_LINE)
REST_GPR(14, r1)
#endif
.endif
#ifdef CONFIG_PPC64
ld r2, STK_GOT(r1)
#endif
addi r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
#ifdef CONFIG_LIVEPATCH_64
bne- livepatch_handler
#endif
#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
bnectr cr1
#endif
blr
#else
bctr
#endif
.endm
.macro ftrace_regs_func allregs
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
bctrl
#else
.if \allregs == 1
.globl ftrace_regs_call
ftrace_regs_call:
.else
.globl ftrace_call
ftrace_call:
.endif
bl ftrace_stub
#endif
.endm
_GLOBAL(ftrace_regs_caller)
ftrace_regs_entry 1
ftrace_regs_func 1
ftrace_regs_exit 1
_GLOBAL(ftrace_caller)
ftrace_regs_entry 0
ftrace_regs_func 0
ftrace_regs_exit 0
_GLOBAL(ftrace_stub)
blr
#ifdef CONFIG_PPC64
ftrace_no_trace:
#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
REST_GPR(3, r1)
addi r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
blr
#else
mflr r3
mtctr r3
REST_GPR(3, r1)
addi r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
mtlr r0
bctr
#endif
#endif
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
.Lftrace_direct_call_regs:
mtctr r12
REST_GPRS(11, 12, r1)
addi r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
bctr
.Lftrace_direct_call:
mtctr r12
addi r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
bctr
SYM_FUNC_START(ftrace_stub_direct_tramp)
blr
SYM_FUNC_END(ftrace_stub_direct_tramp)
#endif
#ifdef CONFIG_LIVEPATCH_64
livepatch_handler:
ld r12, PACA_THREAD_INFO(r13)
ld r11, TI_livepatch_sp(r12)
addi r11, r11, 24
std r11, TI_livepatch_sp(r12)
lis r12, STACK_END_MAGIC@h
ori r12, r12, STACK_END_MAGIC@l
std r12, -8(r11)
std r2, -24(r11)
#ifndef CONFIG_PPC_FTRACE_OUT_OF_LINE
mflr r12
std r12, -16(r11)
mfctr r12
#else
std r0, -16(r11)
mflr r12
mtctr r12
#endif
bctrl
ld r12, PACA_THREAD_INFO(r13)
ld r11, TI_livepatch_sp(r12)
lis r2, STACK_END_MAGIC@h
ori r2, r2, STACK_END_MAGIC@l
ld r12, -8(r11)
1: tdne r12, r2
EMIT_BUG_ENTRY 1b, __FILE__, __LINE__ - 1, 0
ld r12, -16(r11)
mtlr r12
ld r2, -24(r11)
ld r12, PACA_THREAD_INFO(r13)
subi r11, r11, 24
std r11, TI_livepatch_sp(r12)
blr
#endif
#ifndef CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY
_GLOBAL(mcount)
_GLOBAL(_mcount)
EXPORT_SYMBOL(_mcount)
mflr r12
mtctr r12
mtlr r0
bctr
#endif
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
_GLOBAL(return_to_handler)
#ifdef CONFIG_PPC64
stdu r1, -SWITCH_FRAME_SIZE(r1)
std r4, GPR4(r1)
std r3, GPR3(r1)
addi r3, r1, SWITCH_FRAME_SIZE
std r3, GPR1(r1)
std r2, 24(r1)
std r31, 32(r1)
mr r31, r1
addi r3, r1, STACK_INT_FRAME_REGS
LOAD_PACA_TOC()
#else
stwu r1, -SWITCH_FRAME_SIZE(r1)
stw r4, GPR4(r1)
stw r3, GPR3(r1)
addi r3, r1, SWITCH_FRAME_SIZE
stw r3, GPR1(r1)
addi r3, r1, STACK_INT_FRAME_REGS
#endif
bl ftrace_return_to_handler
nop
mtlr r3
#ifdef CONFIG_PPC64
ld r4, GPR4(r1)
ld r3, GPR3(r1)
ld r2, 24(r1)
ld r31, 32(r1)
ld r1, 0(r1)
#else
lwz r3, GPR3(r1)
lwz r4, GPR4(r1)
addi r1, r1, SWITCH_FRAME_SIZE
#endif
blr
#endif
#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
SYM_DATA(ftrace_ool_stub_text_count, .long CONFIG_PPC_FTRACE_OUT_OF_LINE_NUM_RESERVE)
SYM_START(ftrace_ool_stub_text, SYM_L_GLOBAL, .balign SZL)
.space CONFIG_PPC_FTRACE_OUT_OF_LINE_NUM_RESERVE * FTRACE_OOL_STUB_SIZE
SYM_CODE_END(ftrace_ool_stub_text)
#endif
.pushsection ".tramp.ftrace.text","aw",@progbits;
.globl ftrace_tramp_text
ftrace_tramp_text:
.space 32
.popsection
.pushsection ".tramp.ftrace.init","aw",@progbits;
.globl ftrace_tramp_init
ftrace_tramp_init:
.space 32
.popsection