diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-09 21:01:11 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-09 21:01:11 -0700 |
commit | 0fc2f137226eff4c9dd90864dda5c237474c3ec5 (patch) | |
tree | 50ec67f1f9d144a3ceb5ccff45a37bc5005f6c3d /arch/blackfin/kernel/ftrace.c | |
parent | dcded10f6dce10411b16134ce9cc87bfdf75c13f (diff) | |
parent | aab2393e2ec52c74b419af7c26a12e21584e483b (diff) | |
download | op-kernel-dev-0fc2f137226eff4c9dd90864dda5c237474c3ec5.zip op-kernel-dev-0fc2f137226eff4c9dd90864dda5c237474c3ec5.tar.gz |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier/blackfin
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier/blackfin: (32 commits)
Blackfin: gpio: add a debounce stub
Blackfin: update defconfigs
Blackfin: remove CONFIG_MEM_GENERIC_BOARD
Blackfin: dpmc: punt unnecessary RTC_ISTAT clearing
Blackfin: unify rotary encoder bitmasks
Blackfin: unify SDH/RSI bitmasks
Blackfin: BF54x: tweak DMAC MMR naming to match other ports
Blackfin: TWI: clean up the MMR names
Blackfin: add EVT_OVERRIDE/IPRIO core MMR helpers
Blackfin: add support for dynamic ftrace
Blackfin: add support for LZO compressed kernels
Blackfin: portmux: fix peripheral map overflow when requesting pins
Blackfin: document SPI CS limitations with CPHA=0
Blackfin: remove useless and outdated documentation
Blackfin: BF51x/BF52x: support GPIO Hysteresis/Schmitt Trigger options
Blackfin: gpio/portmux: clean up whitespace corruption
Blackfin: make sure mmiowb inserts a write barrier with SSYNC
Blackfin: fix DMA/cache bug when resuming from suspend to RAM
Blackfin: BF51x: fix handling of PH8 (the "internal" SPI0SEL4 pin)
Blackfin: add a GPIO_DEFAULT_BOOT_SPI_CS
...
Diffstat (limited to 'arch/blackfin/kernel/ftrace.c')
-rw-r--r-- | arch/blackfin/kernel/ftrace.c | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/arch/blackfin/kernel/ftrace.c b/arch/blackfin/kernel/ftrace.c index a61d948..48808a1 100644 --- a/arch/blackfin/kernel/ftrace.c +++ b/arch/blackfin/kernel/ftrace.c @@ -1,17 +1,101 @@ /* * ftrace graph code * - * Copyright (C) 2009 Analog Devices Inc. + * Copyright (C) 2009-2010 Analog Devices Inc. * Licensed under the GPL-2 or later. */ #include <linux/ftrace.h> #include <linux/kernel.h> #include <linux/sched.h> +#include <linux/uaccess.h> #include <asm/atomic.h> +#include <asm/cacheflush.h> + +#ifdef CONFIG_DYNAMIC_FTRACE + +static const unsigned char mnop[] = { + 0x03, 0xc0, 0x00, 0x18, /* MNOP; */ + 0x03, 0xc0, 0x00, 0x18, /* MNOP; */ +}; + +static void bfin_make_pcrel24(unsigned char *insn, unsigned long src, + unsigned long dst) +{ + uint32_t pcrel = (dst - src) >> 1; + insn[0] = pcrel >> 16; + insn[1] = 0xe3; + insn[2] = pcrel; + insn[3] = pcrel >> 8; +} +#define bfin_make_pcrel24(insn, src, dst) bfin_make_pcrel24(insn, src, (unsigned long)(dst)) + +static int ftrace_modify_code(unsigned long ip, const unsigned char *code, + unsigned long len) +{ + int ret = probe_kernel_write((void *)ip, (void *)code, len); + flush_icache_range(ip, ip + len); + return ret; +} + +int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, + unsigned long addr) +{ + /* Turn the mcount call site into two MNOPs as those are 32bit insns */ + return ftrace_modify_code(rec->ip, mnop, sizeof(mnop)); +} + +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) +{ + /* Restore the mcount call site */ + unsigned char call[8]; + call[0] = 0x67; /* [--SP] = RETS; */ + call[1] = 0x01; + bfin_make_pcrel24(&call[2], rec->ip + 2, addr); + call[6] = 0x27; /* RETS = [SP++]; */ + call[7] = 0x01; + return ftrace_modify_code(rec->ip, call, sizeof(call)); +} + +int ftrace_update_ftrace_func(ftrace_func_t func) +{ + unsigned char call[4]; + unsigned long ip = (unsigned long)&ftrace_call; + bfin_make_pcrel24(call, ip, func); + return ftrace_modify_code(ip, call, sizeof(call)); +} + +int __init ftrace_dyn_arch_init(void *data) +{ + /* return value is done indirectly via data */ + *(unsigned long *)data = 0; + + return 0; +} + +#endif #ifdef CONFIG_FUNCTION_GRAPH_TRACER +# ifdef CONFIG_DYNAMIC_FTRACE + +extern void ftrace_graph_call(void); + +int ftrace_enable_ftrace_graph_caller(void) +{ + unsigned long ip = (unsigned long)&ftrace_graph_call; + uint16_t jump_pcrel12 = ((unsigned long)&ftrace_graph_caller - ip) >> 1; + jump_pcrel12 |= 0x2000; + return ftrace_modify_code(ip, (void *)&jump_pcrel12, sizeof(jump_pcrel12)); +} + +int ftrace_disable_ftrace_graph_caller(void) +{ + return ftrace_modify_code((unsigned long)&ftrace_graph_call, empty_zero_page, 2); +} + +# endif + /* * Hook the return address and push it in the stack of return addrs * in current thread info. |