PageRenderTime 1ms CodeModel.GetById 20ms app.highlight 2ms RepoModel.GetById 0ms app.codeStats 1ms

/arch/arm/kernel/ftrace.c

https://bitbucket.org/thekraven/iscream_thunderc-2.6.35
C | 103 lines | 68 code | 18 blank | 17 comment | 5 complexity | 90f09d30e8caa34991e6f9e4cd7e826f MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1/*
  2 * Dynamic function tracing support.
  3 *
  4 * Copyright (C) 2008 Abhishek Sagar <sagar.abhishek@gmail.com>
  5 *
  6 * For licencing details, see COPYING.
  7 *
  8 * Defines low-level handling of mcount calls when the kernel
  9 * is compiled with the -pg flag. When using dynamic ftrace, the
 10 * mcount call-sites get patched lazily with NOP till they are
 11 * enabled. All code mutation routines here take effect atomically.
 12 */
 13
 14#include <linux/ftrace.h>
 15
 16#include <asm/cacheflush.h>
 17#include <asm/ftrace.h>
 18
 19#define PC_OFFSET      8
 20#define BL_OPCODE      0xeb000000
 21#define BL_OFFSET_MASK 0x00ffffff
 22
 23static unsigned long bl_insn;
 24static const unsigned long NOP = 0xe1a00000; /* mov r0, r0 */
 25
 26unsigned char *ftrace_nop_replace(void)
 27{
 28	return (char *)&NOP;
 29}
 30
 31/* construct a branch (BL) instruction to addr */
 32unsigned char *ftrace_call_replace(unsigned long pc, unsigned long addr)
 33{
 34	long offset;
 35
 36	offset = (long)addr - (long)(pc + PC_OFFSET);
 37	if (unlikely(offset < -33554432 || offset > 33554428)) {
 38		/* Can't generate branches that far (from ARM ARM). Ftrace
 39		 * doesn't generate branches outside of kernel text.
 40		 */
 41		WARN_ON_ONCE(1);
 42		return NULL;
 43	}
 44	offset = (offset >> 2) & BL_OFFSET_MASK;
 45	bl_insn = BL_OPCODE | offset;
 46	return (unsigned char *)&bl_insn;
 47}
 48
 49int ftrace_modify_code(unsigned long pc, unsigned char *old_code,
 50		       unsigned char *new_code)
 51{
 52	unsigned long err = 0, replaced = 0, old, new;
 53
 54	old = *(unsigned long *)old_code;
 55	new = *(unsigned long *)new_code;
 56
 57	__asm__ __volatile__ (
 58		"1:  ldr    %1, [%2]  \n"
 59		"    cmp    %1, %4    \n"
 60		"2:  streq  %3, [%2]  \n"
 61		"    cmpne  %1, %3    \n"
 62		"    movne  %0, #2    \n"
 63		"3:\n"
 64
 65		".pushsection .fixup, \"ax\"\n"
 66		"4:  mov  %0, #1  \n"
 67		"    b    3b      \n"
 68		".popsection\n"
 69
 70		".pushsection __ex_table, \"a\"\n"
 71		"    .long 1b, 4b \n"
 72		"    .long 2b, 4b \n"
 73		".popsection\n"
 74
 75		: "=r"(err), "=r"(replaced)
 76		: "r"(pc), "r"(new), "r"(old), "0"(err), "1"(replaced)
 77		: "memory");
 78
 79	if (!err && (replaced == old))
 80		flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
 81
 82	return err;
 83}
 84
 85int ftrace_update_ftrace_func(ftrace_func_t func)
 86{
 87	int ret;
 88	unsigned long pc, old;
 89	unsigned char *new;
 90
 91	pc = (unsigned long)&ftrace_call;
 92	memcpy(&old, &ftrace_call, MCOUNT_INSN_SIZE);
 93	new = ftrace_call_replace(pc, (unsigned long)func);
 94	ret = ftrace_modify_code(pc, (unsigned char *)&old, new);
 95	return ret;
 96}
 97
 98/* run from ftrace_init with irqs disabled */
 99int __init ftrace_dyn_arch_init(void *data)
100{
101	ftrace_mcount_set(data);
102	return 0;
103}