Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 310395
b: refs/heads/master
c: 8a4d0a6
h: refs/heads/master
i:
  310393: 1c2d13e
  310391: b16584e
v: v3
  • Loading branch information
Steven Rostedt authored and Steven Rostedt committed Jun 1, 2012
1 parent e81f95a commit 17c367b
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 17 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: a192cd0413b71c2a3e4e48dd365af704be72b748
refs/heads/master: 8a4d0a687a599f39b7df3fe15f2d51d2157caf44
88 changes: 72 additions & 16 deletions trunk/arch/x86/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ static const unsigned char *ftrace_nop_replace(void)
}

static int
ftrace_modify_code(unsigned long ip, unsigned const char *old_code,
ftrace_modify_code_direct(unsigned long ip, unsigned const char *old_code,
unsigned const char *new_code)
{
unsigned char replaced[MCOUNT_INSN_SIZE];
Expand Down Expand Up @@ -141,7 +141,20 @@ int ftrace_make_nop(struct module *mod,
old = ftrace_call_replace(ip, addr);
new = ftrace_nop_replace();

return ftrace_modify_code(rec->ip, old, new);
/*
* On boot up, and when modules are loaded, the MCOUNT_ADDR
* is converted to a nop, and will never become MCOUNT_ADDR
* again. This code is either running before SMP (on boot up)
* or before the code will ever be executed (module load).
* We do not want to use the breakpoint version in this case,
* just modify the code directly.
*/
if (addr == MCOUNT_ADDR)
return ftrace_modify_code_direct(rec->ip, old, new);

/* Normal cases use add_brk_on_nop */
WARN_ONCE(1, "invalid use of ftrace_make_nop");
return -EINVAL;
}

int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
Expand All @@ -152,20 +165,8 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
old = ftrace_nop_replace();
new = ftrace_call_replace(ip, addr);

return ftrace_modify_code(rec->ip, old, new);
}

int ftrace_update_ftrace_func(ftrace_func_t func)
{
unsigned long ip = (unsigned long)(&ftrace_call);
unsigned char old[MCOUNT_INSN_SIZE], *new;
int ret;

memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
new = ftrace_call_replace(ip, (unsigned long)func);
ret = ftrace_modify_code(ip, old, new);

return ret;
/* Should only be called when module is loaded */
return ftrace_modify_code_direct(rec->ip, old, new);
}

/*
Expand Down Expand Up @@ -201,6 +202,29 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
*/
atomic_t modifying_ftrace_code __read_mostly;

static int
ftrace_modify_code(unsigned long ip, unsigned const char *old_code,
unsigned const char *new_code);

int ftrace_update_ftrace_func(ftrace_func_t func)
{
unsigned long ip = (unsigned long)(&ftrace_call);
unsigned char old[MCOUNT_INSN_SIZE], *new;
int ret;

memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
new = ftrace_call_replace(ip, (unsigned long)func);

/* See comment above by declaration of modifying_ftrace_code */
atomic_inc(&modifying_ftrace_code);

ret = ftrace_modify_code(ip, old, new);

atomic_dec(&modifying_ftrace_code);

return ret;
}

/*
* A breakpoint was added to the code address we are about to
* modify, and this is the handle that will just skip over it.
Expand Down Expand Up @@ -520,6 +544,38 @@ void ftrace_replace_code(int enable)
}
}

static int
ftrace_modify_code(unsigned long ip, unsigned const char *old_code,
unsigned const char *new_code)
{
int ret;

ret = add_break(ip, old_code);
if (ret)
goto out;

run_sync();

ret = add_update_code(ip, new_code);
if (ret)
goto fail_update;

run_sync();

ret = ftrace_write(ip, new_code, 1);
if (ret) {
ret = -EPERM;
goto out;
}
run_sync();
out:
return ret;

fail_update:
probe_kernel_write((void *)ip, &old_code[0], 1);
goto out;
}

void arch_ftrace_update_code(int command)
{
/* See comment above by declaration of modifying_ftrace_code */
Expand Down

0 comments on commit 17c367b

Please sign in to comment.