Skip to content

Commit

Permalink
MIPS: Tracing: Reduce the overhead of dynamic Function Tracer
Browse files Browse the repository at this point in the history
With the help of uasm this patch encodes the instructions of the dynamic
function tracer in ftrace_dyn_arch_init() when initializing it.

As a result we can remove the dynamic encoding of instructions in
ftrace_make_nop()/call(), ftrace_enable_ftrace_graph_caller() and remove
the macro jump_insn_encode() and at last this reduce the overhead of
dynamic Function Tracer.  This also is cleaner.

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
Cc: linux-mips <linux-mips@linux-mips.org>
Cc: David Daney <david.s.daney@gmail.com>
Patchwork: http://patchwork.linux-mips.org/patch/1230/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Wu Zhangjin authored and Ralf Baechle committed Jul 5, 2010
1 parent 4d6829f commit e424054
Showing 1 changed file with 49 additions and 44 deletions.
93 changes: 49 additions & 44 deletions arch/mips/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Code for replacing ftrace calls with jumps.
*
* Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
* Copyright (C) 2009 DSLab, Lanzhou University, China
* Copyright (C) 2009, 2010 DSLab, Lanzhou University, China
* Author: Wu Zhangjin <wuzhangjin@gmail.com>
*
* Thanks goes to Steven Rostedt for writing the original x86 version.
Expand All @@ -12,21 +12,46 @@
#include <linux/init.h>
#include <linux/ftrace.h>

#include <asm/cacheflush.h>
#include <asm/asm.h>
#include <asm/asm-offsets.h>
#include <asm/cacheflush.h>
#include <asm/uasm.h>

#ifdef CONFIG_DYNAMIC_FTRACE

#define JAL 0x0c000000 /* jump & link: ip --> ra, jump to target */
#define ADDR_MASK 0x03ffffff /* op_code|addr : 31...26|25 ....0 */
#define jump_insn_encode(op_code, addr) \
((unsigned int)((op_code) | (((addr) >> 2) & ADDR_MASK)))

#define INSN_B_1F_4 0x10000004 /* b 1f; offset = 4 */
#define INSN_B_1F_5 0x10000005 /* b 1f; offset = 5 */
#define INSN_NOP 0x00000000 /* nop */
#define INSN_JAL(addr) jump_insn_encode(JAL, addr)
#define INSN_JAL(addr) \
((unsigned int)(JAL | (((addr) >> 2) & ADDR_MASK)))

static unsigned int insn_jal_ftrace_caller __read_mostly;
static unsigned int insn_lui_v1_hi16_mcount __read_mostly;
static unsigned int insn_j_ftrace_graph_caller __maybe_unused __read_mostly;

static inline void ftrace_dyn_arch_init_insns(void)
{
u32 *buf;
unsigned int v1;

/* lui v1, hi16_mcount */
v1 = 3;
buf = (u32 *)&insn_lui_v1_hi16_mcount;
UASM_i_LA_mostly(&buf, v1, MCOUNT_ADDR);

/* jal (ftrace_caller + 8), jump over the first two instruction */
buf = (u32 *)&insn_jal_ftrace_caller;
uasm_i_jal(&buf, (FTRACE_ADDR + 8));

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
/* j ftrace_graph_caller */
buf = (u32 *)&insn_j_ftrace_graph_caller;
uasm_i_j(&buf, (unsigned long)ftrace_graph_caller);
#endif
}

static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
{
Expand All @@ -43,30 +68,20 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
return 0;
}

static int lui_v1;
static int jal_mcount;

int ftrace_make_nop(struct module *mod,
struct dyn_ftrace *rec, unsigned long addr)
{
unsigned int new;
int faulted;
unsigned long ip = rec->ip;

/* We have compiled module with -mlong-calls, but compiled the kernel
* without it, we need to cope with them respectively. */
/*
* We have compiled module with -mlong-calls, but compiled the kernel
* without it, we need to cope with them respectively.
*/
if (ip & 0x40000000) {
/* record it for ftrace_make_call */
if (lui_v1 == 0) {
/* lui_v1 = *(unsigned int *)ip; */
safe_load_code(lui_v1, ip, faulted);

if (unlikely(faulted))
return -EFAULT;
}

#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT)
/* lui v1, hi_16bit_of_mcount --> b 1f (0x10000005)
/*
* lui v1, hi_16bit_of_mcount --> b 1f (0x10000005)
* addiu v1, v1, low_16bit_of_mcount
* move at, ra
* move $12, ra_address
Expand All @@ -76,7 +91,8 @@ int ftrace_make_nop(struct module *mod,
*/
new = INSN_B_1F_5;
#else
/* lui v1, hi_16bit_of_mcount --> b 1f (0x10000004)
/*
* lui v1, hi_16bit_of_mcount --> b 1f (0x10000004)
* addiu v1, v1, low_16bit_of_mcount
* move at, ra
* jalr v1
Expand All @@ -86,36 +102,22 @@ int ftrace_make_nop(struct module *mod,
new = INSN_B_1F_4;
#endif
} else {
/* record/calculate it for ftrace_make_call */
if (jal_mcount == 0) {
/* We can record it directly like this:
* jal_mcount = *(unsigned int *)ip;
* Herein, jump over the first two nop instructions */
jal_mcount = INSN_JAL(MCOUNT_ADDR + 8);
}

/* move at, ra
* jalr v1 --> nop
/*
* move at, ra
* jal _mcount --> nop
*/
new = INSN_NOP;
}
return ftrace_modify_code(ip, new);
}

static int modified; /* initialized as 0 by default */

int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
{
unsigned int new;
unsigned long ip = rec->ip;

/* We just need to remove the "b ftrace_stub" at the fist time! */
if (modified == 0) {
modified = 1;
ftrace_modify_code(addr, INSN_NOP);
}
/* ip, module: 0xc0000000, kernel: 0x80000000 */
new = (ip & 0x40000000) ? lui_v1 : jal_mcount;
new = (ip & 0x40000000) ? insn_lui_v1_hi16_mcount : insn_jal_ftrace_caller;

return ftrace_modify_code(ip, new);
}
Expand All @@ -133,6 +135,12 @@ int ftrace_update_ftrace_func(ftrace_func_t func)

int __init ftrace_dyn_arch_init(void *data)
{
/* Encode the instructions when booting */
ftrace_dyn_arch_init_insns();

/* Remove "b ftrace_stub" to ensure ftrace_caller() is executed */
ftrace_modify_code(MCOUNT_ADDR, INSN_NOP);

/* The return code is retured via data */
*(unsigned long *)data = 0;

Expand All @@ -145,15 +153,12 @@ int __init ftrace_dyn_arch_init(void *data)
#ifdef CONFIG_DYNAMIC_FTRACE

extern void ftrace_graph_call(void);
#define JMP 0x08000000 /* jump to target directly */
#define CALL_FTRACE_GRAPH_CALLER \
jump_insn_encode(JMP, (unsigned long)(&ftrace_graph_caller))
#define FTRACE_GRAPH_CALL_IP ((unsigned long)(&ftrace_graph_call))

int ftrace_enable_ftrace_graph_caller(void)
{
return ftrace_modify_code(FTRACE_GRAPH_CALL_IP,
CALL_FTRACE_GRAPH_CALLER);
insn_j_ftrace_graph_caller);
}

int ftrace_disable_ftrace_graph_caller(void)
Expand Down

0 comments on commit e424054

Please sign in to comment.