Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 297597
b: refs/heads/master
c: d82227c
h: refs/heads/master
i:
  297595: 1911e88
v: v3
  • Loading branch information
Rabin Vincent authored and Russell King committed Mar 24, 2012
1 parent db3e433 commit 395d58c
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 60 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4394e2824c8d97d81a336edb469b13c8806604e4
refs/heads/master: d82227cf8f0b42ff42c21ed47025fdf54cb1698d
5 changes: 3 additions & 2 deletions trunk/arch/arm/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)

ifdef CONFIG_FUNCTION_TRACER
CFLAGS_REMOVE_ftrace.o = -pg
CFLAGS_REMOVE_insn.o = -pg
endif

CFLAGS_REMOVE_return_address.o = -pg
Expand Down Expand Up @@ -34,8 +35,8 @@ obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o
obj-$(CONFIG_SMP) += smp.o smp_tlb.o
obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_KPROBES) += kprobes.o kprobes-common.o
ifdef CONFIG_THUMB2_KERNEL
Expand Down
61 changes: 4 additions & 57 deletions trunk/arch/arm/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include <asm/opcodes.h>
#include <asm/ftrace.h>

#include "insn.h"

#ifdef CONFIG_THUMB2_KERNEL
#define NOP 0xf85deb04 /* pop.w {lr} */
#else
Expand Down Expand Up @@ -61,64 +63,9 @@ static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)
}
#endif

#ifdef CONFIG_THUMB2_KERNEL
static unsigned long ftrace_gen_branch(unsigned long pc, unsigned long addr,
bool link)
{
unsigned long s, j1, j2, i1, i2, imm10, imm11;
unsigned long first, second;
long offset;

offset = (long)addr - (long)(pc + 4);
if (offset < -16777216 || offset > 16777214) {
WARN_ON_ONCE(1);
return 0;
}

s = (offset >> 24) & 0x1;
i1 = (offset >> 23) & 0x1;
i2 = (offset >> 22) & 0x1;
imm10 = (offset >> 12) & 0x3ff;
imm11 = (offset >> 1) & 0x7ff;

j1 = (!i1) ^ s;
j2 = (!i2) ^ s;

first = 0xf000 | (s << 10) | imm10;
second = 0x9000 | (j1 << 13) | (j2 << 11) | imm11;
if (link)
second |= 1 << 14;

return __opcode_thumb32_compose(first, second);
}
#else
static unsigned long ftrace_gen_branch(unsigned long pc, unsigned long addr,
bool link)
{
unsigned long opcode = 0xea000000;
long offset;

if (link)
opcode |= 1 << 24;

offset = (long)addr - (long)(pc + 8);
if (unlikely(offset < -33554432 || offset > 33554428)) {
/* Can't generate branches that far (from ARM ARM). Ftrace
* doesn't generate branches outside of kernel text.
*/
WARN_ON_ONCE(1);
return 0;
}

offset = (offset >> 2) & 0x00ffffff;

return opcode | offset;
}
#endif

static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
{
return ftrace_gen_branch(pc, addr, true);
return arm_gen_branch_link(pc, addr);
}

static int ftrace_modify_code(unsigned long pc, unsigned long old,
Expand Down Expand Up @@ -258,7 +205,7 @@ static int __ftrace_modify_caller(unsigned long *callsite,
{
unsigned long caller_fn = (unsigned long) func;
unsigned long pc = (unsigned long) callsite;
unsigned long branch = ftrace_gen_branch(pc, caller_fn, false);
unsigned long branch = arm_gen_branch(pc, caller_fn);
unsigned long nop = 0xe1a00000; /* mov r0, r0 */
unsigned long old = enable ? nop : branch;
unsigned long new = enable ? branch : nop;
Expand Down
61 changes: 61 additions & 0 deletions trunk/arch/arm/kernel/insn.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include <linux/kernel.h>
#include <asm/opcodes.h>

static unsigned long
__arm_gen_branch_thumb2(unsigned long pc, unsigned long addr, bool link)
{
unsigned long s, j1, j2, i1, i2, imm10, imm11;
unsigned long first, second;
long offset;

offset = (long)addr - (long)(pc + 4);
if (offset < -16777216 || offset > 16777214) {
WARN_ON_ONCE(1);
return 0;
}

s = (offset >> 24) & 0x1;
i1 = (offset >> 23) & 0x1;
i2 = (offset >> 22) & 0x1;
imm10 = (offset >> 12) & 0x3ff;
imm11 = (offset >> 1) & 0x7ff;

j1 = (!i1) ^ s;
j2 = (!i2) ^ s;

first = 0xf000 | (s << 10) | imm10;
second = 0x9000 | (j1 << 13) | (j2 << 11) | imm11;
if (link)
second |= 1 << 14;

return __opcode_thumb32_compose(first, second);
}

static unsigned long
__arm_gen_branch_arm(unsigned long pc, unsigned long addr, bool link)
{
unsigned long opcode = 0xea000000;
long offset;

if (link)
opcode |= 1 << 24;

offset = (long)addr - (long)(pc + 8);
if (unlikely(offset < -33554432 || offset > 33554428)) {
WARN_ON_ONCE(1);
return 0;
}

offset = (offset >> 2) & 0x00ffffff;

return opcode | offset;
}

unsigned long
__arm_gen_branch(unsigned long pc, unsigned long addr, bool link)
{
if (IS_ENABLED(CONFIG_THUMB2_KERNEL))
return __arm_gen_branch_thumb2(pc, addr, link);
else
return __arm_gen_branch_arm(pc, addr, link);
}
19 changes: 19 additions & 0 deletions trunk/arch/arm/kernel/insn.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef __ASM_ARM_INSN_H
#define __ASM_ARM_INSN_H

unsigned long
__arm_gen_branch(unsigned long pc, unsigned long addr, bool link);

static inline unsigned long
arm_gen_branch(unsigned long pc, unsigned long addr)
{
return __arm_gen_branch(pc, addr, false);
}

static inline unsigned long
arm_gen_branch_link(unsigned long pc, unsigned long addr)
{
return __arm_gen_branch(pc, addr, true);
}

#endif

0 comments on commit 395d58c

Please sign in to comment.