Commit dfa60aba authored by Steven Rostedt's avatar Steven Rostedt Committed by Thomas Gleixner

ftrace: use nops instead of jmp

This patch patches the call to mcount with nops instead
of a jmp over the mcount call.
Signed-off-by: default avatarSteven Rostedt <srostedt@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent b0fc494f
...@@ -143,7 +143,7 @@ static const unsigned char *const p6_nops[ASM_NOP_MAX+1] = { ...@@ -143,7 +143,7 @@ static const unsigned char *const p6_nops[ASM_NOP_MAX+1] = {
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
extern char __vsyscall_0; extern char __vsyscall_0;
static inline const unsigned char*const * find_nop_table(void) const unsigned char *const *find_nop_table(void)
{ {
return boot_cpu_data.x86_vendor != X86_VENDOR_INTEL || return boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
boot_cpu_data.x86 < 6 ? k8_nops : p6_nops; boot_cpu_data.x86 < 6 ? k8_nops : p6_nops;
...@@ -162,7 +162,7 @@ static const struct nop { ...@@ -162,7 +162,7 @@ static const struct nop {
{ -1, NULL } { -1, NULL }
}; };
static const unsigned char*const * find_nop_table(void) const unsigned char *const *find_nop_table(void)
{ {
const unsigned char *const *noptable = intel_nops; const unsigned char *const *noptable = intel_nops;
int i; int i;
......
...@@ -16,11 +16,12 @@ ...@@ -16,11 +16,12 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/list.h> #include <linux/list.h>
#define CALL_BACK 5 #include <asm/alternative.h>
#define JMPFWD 0x03eb #define CALL_BACK 5
static unsigned short ftrace_jmp = JMPFWD; /* Long is fine, even if it is only 4 bytes ;-) */
static long *ftrace_nop;
struct ftrace_record { struct ftrace_record {
struct dyn_ftrace rec; struct dyn_ftrace rec;
...@@ -55,13 +56,13 @@ static struct ftrace_page *ftrace_pages; ...@@ -55,13 +56,13 @@ static struct ftrace_page *ftrace_pages;
notrace struct dyn_ftrace *ftrace_alloc_shutdown_node(unsigned long ip) notrace struct dyn_ftrace *ftrace_alloc_shutdown_node(unsigned long ip)
{ {
struct ftrace_record *rec; struct ftrace_record *rec;
unsigned short save; unsigned long save;
ip -= CALL_BACK; ip -= CALL_BACK;
save = *(short *)ip; save = *(long *)ip;
/* If this was already converted, skip it */ /* If this was already converted, skip it */
if (save == JMPFWD) if (save == *ftrace_nop)
return NULL; return NULL;
if (ftrace_pages->index == ENTRIES_PER_PAGE) { if (ftrace_pages->index == ENTRIES_PER_PAGE) {
...@@ -79,9 +80,10 @@ static int notrace ...@@ -79,9 +80,10 @@ static int notrace
ftrace_modify_code(unsigned long ip, unsigned char *old_code, ftrace_modify_code(unsigned long ip, unsigned char *old_code,
unsigned char *new_code) unsigned char *new_code)
{ {
unsigned short old = *(unsigned short *)old_code; unsigned replaced;
unsigned short new = *(unsigned short *)new_code; unsigned old = *(unsigned *)old_code; /* 4 bytes */
unsigned short replaced; unsigned new = *(unsigned *)new_code; /* 4 bytes */
unsigned char newch = new_code[4];
int faulted = 0; int faulted = 0;
/* /*
...@@ -94,7 +96,9 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code, ...@@ -94,7 +96,9 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,
*/ */
asm volatile ( asm volatile (
"1: lock\n" "1: lock\n"
" cmpxchg %w3, (%2)\n" " cmpxchg %3, (%2)\n"
" jnz 2f\n"
" movb %b4, 4(%2)\n"
"2:\n" "2:\n"
".section .fixup, \"ax\"\n" ".section .fixup, \"ax\"\n"
" movl $1, %0\n" " movl $1, %0\n"
...@@ -102,11 +106,12 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code, ...@@ -102,11 +106,12 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,
".previous\n" ".previous\n"
_ASM_EXTABLE(1b, 3b) _ASM_EXTABLE(1b, 3b)
: "=r"(faulted), "=a"(replaced) : "=r"(faulted), "=a"(replaced)
: "r"(ip), "r"(new), "0"(faulted), "a"(old) : "r"(ip), "r"(new), "r"(newch),
"0"(faulted), "a"(old)
: "memory"); : "memory");
sync_core(); sync_core();
if (replaced != old) if (replaced != old && replaced != new)
faulted = 2; faulted = 2;
return faulted; return faulted;
...@@ -132,7 +137,7 @@ notrace void ftrace_code_disable(struct dyn_ftrace *rec) ...@@ -132,7 +137,7 @@ notrace void ftrace_code_disable(struct dyn_ftrace *rec)
/* move the IP back to the start of the call */ /* move the IP back to the start of the call */
ip -= CALL_BACK; ip -= CALL_BACK;
r->failed = ftrace_modify_code(ip, save.code, (char *)&ftrace_jmp); r->failed = ftrace_modify_code(ip, save.code, (char *)ftrace_nop);
} }
static void notrace ftrace_replace_code(int saved) static void notrace ftrace_replace_code(int saved)
...@@ -144,9 +149,9 @@ static void notrace ftrace_replace_code(int saved) ...@@ -144,9 +149,9 @@ static void notrace ftrace_replace_code(int saved)
int i; int i;
if (saved) if (saved)
old = (char *)&ftrace_jmp; old = (char *)ftrace_nop;
else else
new = (char *)&ftrace_jmp; new = (char *)ftrace_nop;
for (pg = ftrace_pages_start; pg; pg = pg->next) { for (pg = ftrace_pages_start; pg; pg = pg->next) {
for (i = 0; i < pg->index; i++) { for (i = 0; i < pg->index; i++) {
...@@ -194,12 +199,15 @@ notrace void ftrace_shutdown_replenish(void) ...@@ -194,12 +199,15 @@ notrace void ftrace_shutdown_replenish(void)
ftrace_pages->next = (void *)get_zeroed_page(GFP_KERNEL); ftrace_pages->next = (void *)get_zeroed_page(GFP_KERNEL);
} }
notrace int ftrace_shutdown_arch_init(void) notrace int __init ftrace_shutdown_arch_init(void)
{ {
const unsigned char *const *noptable = find_nop_table();
struct ftrace_page *pg; struct ftrace_page *pg;
int cnt; int cnt;
int i; int i;
ftrace_nop = (unsigned long *)noptable[CALL_BACK];
/* allocate a few pages */ /* allocate a few pages */
ftrace_pages_start = (void *)get_zeroed_page(GFP_KERNEL); ftrace_pages_start = (void *)get_zeroed_page(GFP_KERNEL);
if (!ftrace_pages_start) if (!ftrace_pages_start)
......
...@@ -72,6 +72,8 @@ static inline void alternatives_smp_module_del(struct module *mod) {} ...@@ -72,6 +72,8 @@ static inline void alternatives_smp_module_del(struct module *mod) {}
static inline void alternatives_smp_switch(int smp) {} static inline void alternatives_smp_switch(int smp) {}
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
const unsigned char *const *find_nop_table(void);
/* /*
* Alternative instructions for different CPU types or capabilities. * Alternative instructions for different CPU types or capabilities.
* *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment