1d2bb0762SWu Zhangjin/* 2d2bb0762SWu Zhangjin * MIPS specific _mcount support 3d2bb0762SWu Zhangjin * 4d2bb0762SWu Zhangjin * This file is subject to the terms and conditions of the GNU General Public 5d2bb0762SWu Zhangjin * License. See the file "COPYING" in the main directory of this archive for 6d2bb0762SWu Zhangjin * more details. 7d2bb0762SWu Zhangjin * 8d2bb0762SWu Zhangjin * Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University, China 9042e571dSWu Zhangjin * Copyright (C) 2010 DSLab, Lanzhou University, China 10f7a904dfSWu Zhangjin * Author: Wu Zhangjin <wuzhangjin@gmail.com> 11d2bb0762SWu Zhangjin */ 12d2bb0762SWu Zhangjin 13*9259e15bSMasahiro Yamada#include <linux/export.h> 14d2bb0762SWu Zhangjin#include <asm/regdef.h> 15d2bb0762SWu Zhangjin#include <asm/stackframe.h> 16d2bb0762SWu Zhangjin#include <asm/ftrace.h> 17d2bb0762SWu Zhangjin 18d2bb0762SWu Zhangjin .text 19d2bb0762SWu Zhangjin .set noreorder 20d2bb0762SWu Zhangjin .set noat 21d2bb0762SWu Zhangjin 22d2bb0762SWu Zhangjin .macro MCOUNT_SAVE_REGS 23d2bb0762SWu Zhangjin PTR_SUBU sp, PT_SIZE 24d2bb0762SWu Zhangjin PTR_S ra, PT_R31(sp) 25d2bb0762SWu Zhangjin PTR_S AT, PT_R1(sp) 26d2bb0762SWu Zhangjin PTR_S a0, PT_R4(sp) 27d2bb0762SWu Zhangjin PTR_S a1, PT_R5(sp) 28d2bb0762SWu Zhangjin PTR_S a2, PT_R6(sp) 29d2bb0762SWu Zhangjin PTR_S a3, PT_R7(sp) 30d2bb0762SWu Zhangjin#ifdef CONFIG_64BIT 31d2bb0762SWu Zhangjin PTR_S a4, PT_R8(sp) 32d2bb0762SWu Zhangjin PTR_S a5, PT_R9(sp) 33d2bb0762SWu Zhangjin PTR_S a6, PT_R10(sp) 34d2bb0762SWu Zhangjin PTR_S a7, PT_R11(sp) 35d2bb0762SWu Zhangjin#endif 36d2bb0762SWu Zhangjin .endm 37d2bb0762SWu Zhangjin 38d2bb0762SWu Zhangjin .macro MCOUNT_RESTORE_REGS 39d2bb0762SWu Zhangjin PTR_L ra, PT_R31(sp) 40d2bb0762SWu Zhangjin PTR_L AT, PT_R1(sp) 41d2bb0762SWu Zhangjin PTR_L a0, PT_R4(sp) 42d2bb0762SWu Zhangjin PTR_L a1, PT_R5(sp) 43d2bb0762SWu Zhangjin PTR_L a2, PT_R6(sp) 44d2bb0762SWu Zhangjin PTR_L a3, PT_R7(sp) 45d2bb0762SWu Zhangjin#ifdef CONFIG_64BIT 46d2bb0762SWu Zhangjin PTR_L a4, PT_R8(sp) 47d2bb0762SWu Zhangjin PTR_L a5, PT_R9(sp) 48d2bb0762SWu Zhangjin PTR_L a6, PT_R10(sp) 49d2bb0762SWu Zhangjin PTR_L a7, PT_R11(sp) 50d2bb0762SWu Zhangjin#endif 51ad8c3969SDavid Daney PTR_ADDIU sp, PT_SIZE 52d2bb0762SWu Zhangjin .endm 53d2bb0762SWu Zhangjin 54d2bb0762SWu Zhangjin .macro RETURN_BACK 55d2bb0762SWu Zhangjin jr ra 56d2bb0762SWu Zhangjin move ra, AT 57d2bb0762SWu Zhangjin .endm 58d2bb0762SWu Zhangjin 5956b49cd3SWu Zhangjin/* 6056b49cd3SWu Zhangjin * The -mmcount-ra-address option of gcc 4.5 uses register $12 to pass 6156b49cd3SWu Zhangjin * the location of the parent's return address. 6256b49cd3SWu Zhangjin */ 6356b49cd3SWu Zhangjin#define MCOUNT_RA_ADDRESS_REG $12 6456b49cd3SWu Zhangjin 65538f1952SWu Zhangjin#ifdef CONFIG_DYNAMIC_FTRACE 66538f1952SWu Zhangjin 67538f1952SWu ZhangjinNESTED(ftrace_caller, PT_SIZE, ra) 68538f1952SWu Zhangjin .globl _mcount 69538f1952SWu Zhangjin_mcount: 70827456e7SPaul BurtonEXPORT_SYMBOL(_mcount) 71538f1952SWu Zhangjin b ftrace_stub 72ad8c3969SDavid Daney#ifdef CONFIG_32BIT 7358b69401SAl Cooper addiu sp,sp,8 74ad8c3969SDavid Daney#else 75ad8c3969SDavid Daney nop 76ad8c3969SDavid Daney#endif 7758b69401SAl Cooper 7858b69401SAl Cooper /* When tracing is activated, it calls ftrace_caller+8 (aka here) */ 79538f1952SWu Zhangjin MCOUNT_SAVE_REGS 807326c4e5SWu Zhangjin#ifdef KBUILD_MCOUNT_RA_ADDRESS 8156b49cd3SWu Zhangjin PTR_S MCOUNT_RA_ADDRESS_REG, PT_R12(sp) 827326c4e5SWu Zhangjin#endif 83538f1952SWu Zhangjin 8405f22639SCorey Minyard PTR_SUBU a0, ra, 8 /* arg1: self address */ 85dce0e7d5SPetri Gynther PTR_LA t1, _stext 86dce0e7d5SPetri Gynther sltu t2, a0, t1 /* t2 = (a0 < _stext) */ 87dce0e7d5SPetri Gynther PTR_LA t1, _etext 88dce0e7d5SPetri Gynther sltu t3, t1, a0 /* t3 = (a0 > _etext) */ 89dce0e7d5SPetri Gynther or t1, t2, t3 90dce0e7d5SPetri Gynther beqz t1, ftrace_call 91dce0e7d5SPetri Gynther nop 92dce0e7d5SPetri Gynther#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) 93dce0e7d5SPetri Gynther PTR_SUBU a0, a0, 16 /* arg1: adjust to module's recorded callsite */ 94dce0e7d5SPetri Gynther#else 95dce0e7d5SPetri Gynther PTR_SUBU a0, a0, 12 96dce0e7d5SPetri Gynther#endif 97dce0e7d5SPetri Gynther 98538f1952SWu Zhangjin .globl ftrace_call 99538f1952SWu Zhangjinftrace_call: 100538f1952SWu Zhangjin nop /* a placeholder for the call to a real tracing function */ 101042e571dSWu Zhangjin move a1, AT /* arg2: parent's return address */ 102538f1952SWu Zhangjin 103e17ff5feSWu Zhangjin#ifdef CONFIG_FUNCTION_GRAPH_TRACER 104e17ff5feSWu Zhangjin .globl ftrace_graph_call 105e17ff5feSWu Zhangjinftrace_graph_call: 106e17ff5feSWu Zhangjin nop 107e17ff5feSWu Zhangjin nop 108e17ff5feSWu Zhangjin#endif 109e17ff5feSWu Zhangjin 110538f1952SWu Zhangjin MCOUNT_RESTORE_REGS 111538f1952SWu Zhangjin .globl ftrace_stub 112538f1952SWu Zhangjinftrace_stub: 113538f1952SWu Zhangjin RETURN_BACK 114538f1952SWu Zhangjin END(ftrace_caller) 115538f1952SWu Zhangjin 116538f1952SWu Zhangjin#else /* ! CONFIG_DYNAMIC_FTRACE */ 117538f1952SWu Zhangjin 118d2bb0762SWu ZhangjinNESTED(_mcount, PT_SIZE, ra) 119827456e7SPaul BurtonEXPORT_SYMBOL(_mcount) 120fc49a3beSWu Zhangjin PTR_LA t1, ftrace_stub 121fc49a3beSWu Zhangjin PTR_L t2, ftrace_trace_function /* Prepare t2 for (1) */ 1226fb86566SMatthias Schiffer beq t1, t2, fgraph_trace 123d2bb0762SWu Zhangjin nop 12429c5d346SWu Zhangjin 1256fb86566SMatthias Schiffer MCOUNT_SAVE_REGS 1266fb86566SMatthias Schiffer 1276fb86566SMatthias Schiffer move a0, ra /* arg1: self return address */ 1286fb86566SMatthias Schiffer jalr t2 /* (1) call *ftrace_trace_function */ 1296fb86566SMatthias Schiffer move a1, AT /* arg2: parent's return address */ 1306fb86566SMatthias Schiffer 1316fb86566SMatthias Schiffer MCOUNT_RESTORE_REGS 1326fb86566SMatthias Schiffer 1336fb86566SMatthias Schifferfgraph_trace: 13429c5d346SWu Zhangjin#ifdef CONFIG_FUNCTION_GRAPH_TRACER 1356fb86566SMatthias Schiffer PTR_LA t1, ftrace_stub 136fc49a3beSWu Zhangjin PTR_L t3, ftrace_graph_return 137fc49a3beSWu Zhangjin bne t1, t3, ftrace_graph_caller 13829c5d346SWu Zhangjin nop 139fc49a3beSWu Zhangjin PTR_LA t1, ftrace_graph_entry_stub 140fc49a3beSWu Zhangjin PTR_L t3, ftrace_graph_entry 141fc49a3beSWu Zhangjin bne t1, t3, ftrace_graph_caller 14229c5d346SWu Zhangjin nop 14329c5d346SWu Zhangjin#endif 144d2bb0762SWu Zhangjin 1458a574cfaSMarkos Chandras#ifdef CONFIG_32BIT 1468a574cfaSMarkos Chandras addiu sp, sp, 8 1478a574cfaSMarkos Chandras#endif 1486fb86566SMatthias Schiffer 149d2bb0762SWu Zhangjin .globl ftrace_stub 150d2bb0762SWu Zhangjinftrace_stub: 151d2bb0762SWu Zhangjin RETURN_BACK 152d2bb0762SWu Zhangjin END(_mcount) 153d2bb0762SWu Zhangjin 154538f1952SWu Zhangjin#endif /* ! CONFIG_DYNAMIC_FTRACE */ 155538f1952SWu Zhangjin 15629c5d346SWu Zhangjin#ifdef CONFIG_FUNCTION_GRAPH_TRACER 15729c5d346SWu Zhangjin 15829c5d346SWu ZhangjinNESTED(ftrace_graph_caller, PT_SIZE, ra) 159cbe555b0SWu Zhangjin#ifndef CONFIG_DYNAMIC_FTRACE 16029c5d346SWu Zhangjin MCOUNT_SAVE_REGS 161e17ff5feSWu Zhangjin#endif 1627326c4e5SWu Zhangjin 163cbe555b0SWu Zhangjin /* arg1: Get the location of the parent's return address */ 1647326c4e5SWu Zhangjin#ifdef KBUILD_MCOUNT_RA_ADDRESS 165cbe555b0SWu Zhangjin#ifdef CONFIG_DYNAMIC_FTRACE 166cbe555b0SWu Zhangjin PTR_L a0, PT_R12(sp) 1677326c4e5SWu Zhangjin#else 16856b49cd3SWu Zhangjin move a0, MCOUNT_RA_ADDRESS_REG 1697326c4e5SWu Zhangjin#endif 17056b49cd3SWu Zhangjin bnez a0, 1f /* non-leaf func: stored in MCOUNT_RA_ADDRESS_REG */ 171cbe555b0SWu Zhangjin nop 172cbe555b0SWu Zhangjin#endif 173cbe555b0SWu Zhangjin PTR_LA a0, PT_R1(sp) /* leaf func: the location in current stack */ 174cbe555b0SWu Zhangjin1: 175cbe555b0SWu Zhangjin 176cbe555b0SWu Zhangjin /* arg2: Get self return address */ 177cbe555b0SWu Zhangjin#ifdef CONFIG_DYNAMIC_FTRACE 178cbe555b0SWu Zhangjin PTR_L a1, PT_R31(sp) 179046199caSWu Zhangjin#else 180cbe555b0SWu Zhangjin move a1, ra 181cbe555b0SWu Zhangjin#endif 182cbe555b0SWu Zhangjin 183cbe555b0SWu Zhangjin /* arg3: Get frame pointer of current stack */ 184046199caSWu Zhangjin#ifdef CONFIG_64BIT 185046199caSWu Zhangjin PTR_LA a2, PT_SIZE(sp) 186046199caSWu Zhangjin#else 187046199caSWu Zhangjin PTR_LA a2, (PT_SIZE+8)(sp) 188046199caSWu Zhangjin#endif 18929c5d346SWu Zhangjin 190cbe555b0SWu Zhangjin jal prepare_ftrace_return 191cbe555b0SWu Zhangjin nop 19229c5d346SWu Zhangjin MCOUNT_RESTORE_REGS 1938a574cfaSMarkos Chandras#ifndef CONFIG_DYNAMIC_FTRACE 1948a574cfaSMarkos Chandras#ifdef CONFIG_32BIT 1958a574cfaSMarkos Chandras addiu sp, sp, 8 1968a574cfaSMarkos Chandras#endif 1978a574cfaSMarkos Chandras#endif 19829c5d346SWu Zhangjin RETURN_BACK 19929c5d346SWu Zhangjin END(ftrace_graph_caller) 20029c5d346SWu Zhangjin 20129c5d346SWu Zhangjin .align 2 20229c5d346SWu Zhangjin .globl return_to_handler 20329c5d346SWu Zhangjinreturn_to_handler: 20429c5d346SWu Zhangjin PTR_SUBU sp, PT_SIZE 20529c5d346SWu Zhangjin PTR_S v0, PT_R2(sp) 20629c5d346SWu Zhangjin 20729c5d346SWu Zhangjin jal ftrace_return_to_handler 20829c5d346SWu Zhangjin PTR_S v1, PT_R3(sp) 20929c5d346SWu Zhangjin 21029c5d346SWu Zhangjin /* restore the real parent address: v0 -> ra */ 21129c5d346SWu Zhangjin move ra, v0 21229c5d346SWu Zhangjin 21329c5d346SWu Zhangjin PTR_L v0, PT_R2(sp) 21429c5d346SWu Zhangjin PTR_L v1, PT_R3(sp) 21529c5d346SWu Zhangjin jr ra 21629c5d346SWu Zhangjin PTR_ADDIU sp, PT_SIZE 21729c5d346SWu Zhangjin#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 21829c5d346SWu Zhangjin 219d2bb0762SWu Zhangjin .set at 220d2bb0762SWu Zhangjin .set reorder 221