13d083395SSteven Rostedt /* 23d083395SSteven Rostedt * Code for replacing ftrace calls with jumps. 33d083395SSteven Rostedt * 43d083395SSteven Rostedt * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com> 53d083395SSteven Rostedt * 63d083395SSteven Rostedt * Thanks goes to Ingo Molnar, for suggesting the idea. 73d083395SSteven Rostedt * Mathieu Desnoyers, for suggesting postponing the modifications. 83d083395SSteven Rostedt * Arjan van de Ven, for keeping me straight, and explaining to me 93d083395SSteven Rostedt * the dangers of modifying code on the run. 103d083395SSteven Rostedt */ 113d083395SSteven Rostedt 123d083395SSteven Rostedt #include <linux/spinlock.h> 133d083395SSteven Rostedt #include <linux/hardirq.h> 146f93fc07SSteven Rostedt #include <linux/uaccess.h> 153d083395SSteven Rostedt #include <linux/ftrace.h> 163d083395SSteven Rostedt #include <linux/percpu.h> 1719b3e967SIngo Molnar #include <linux/sched.h> 183d083395SSteven Rostedt #include <linux/init.h> 193d083395SSteven Rostedt #include <linux/list.h> 203d083395SSteven Rostedt 2116239630SSteven Rostedt #include <asm/cacheflush.h> 22395a59d0SAbhishek Sagar #include <asm/ftrace.h> 23caf4b323SFrederic Weisbecker #include <linux/ftrace.h> 24732f3ca7SSteven Rostedt #include <asm/nops.h> 25caf4b323SFrederic Weisbecker #include <asm/nmi.h> 26dfa60abaSSteven Rostedt 273d083395SSteven Rostedt 28caf4b323SFrederic Weisbecker #ifdef CONFIG_DYNAMIC_FTRACE 293d083395SSteven Rostedt 3016239630SSteven Rostedt int ftrace_arch_code_modify_prepare(void) 3116239630SSteven Rostedt { 3216239630SSteven Rostedt set_kernel_text_rw(); 3316239630SSteven Rostedt return 0; 3416239630SSteven Rostedt } 3516239630SSteven Rostedt 3616239630SSteven Rostedt int ftrace_arch_code_modify_post_process(void) 3716239630SSteven Rostedt { 3816239630SSteven Rostedt set_kernel_text_ro(); 3916239630SSteven Rostedt return 0; 4016239630SSteven Rostedt } 4116239630SSteven Rostedt 423d083395SSteven Rostedt union ftrace_code_union { 43395a59d0SAbhishek Sagar char code[MCOUNT_INSN_SIZE]; 443d083395SSteven Rostedt struct { 453d083395SSteven Rostedt char e8; 463d083395SSteven Rostedt int offset; 473d083395SSteven Rostedt } __attribute__((packed)); 483d083395SSteven Rostedt }; 493d083395SSteven Rostedt 5015adc048SSteven Rostedt static int ftrace_calc_offset(long ip, long addr) 513c1720f0SSteven Rostedt { 523c1720f0SSteven Rostedt return (int)(addr - ip); 533d083395SSteven Rostedt } 543d083395SSteven Rostedt 5531e88909SSteven Rostedt static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) 563c1720f0SSteven Rostedt { 573c1720f0SSteven Rostedt static union ftrace_code_union calc; 583c1720f0SSteven Rostedt 593c1720f0SSteven Rostedt calc.e8 = 0xe8; 60395a59d0SAbhishek Sagar calc.offset = ftrace_calc_offset(ip + MCOUNT_INSN_SIZE, addr); 613c1720f0SSteven Rostedt 623c1720f0SSteven Rostedt /* 633c1720f0SSteven Rostedt * No locking needed, this must be called via kstop_machine 643c1720f0SSteven Rostedt * which in essence is like running on a uniprocessor machine. 653c1720f0SSteven Rostedt */ 663c1720f0SSteven Rostedt return calc.code; 673c1720f0SSteven Rostedt } 683c1720f0SSteven Rostedt 6917666f02SSteven Rostedt /* 7017666f02SSteven Rostedt * Modifying code must take extra care. On an SMP machine, if 7117666f02SSteven Rostedt * the code being modified is also being executed on another CPU 7217666f02SSteven Rostedt * that CPU will have undefined results and possibly take a GPF. 7317666f02SSteven Rostedt * We use kstop_machine to stop other CPUS from exectuing code. 7417666f02SSteven Rostedt * But this does not stop NMIs from happening. We still need 7517666f02SSteven Rostedt * to protect against that. We separate out the modification of 7617666f02SSteven Rostedt * the code to take care of this. 7717666f02SSteven Rostedt * 7817666f02SSteven Rostedt * Two buffers are added: An IP buffer and a "code" buffer. 7917666f02SSteven Rostedt * 80a26a2a27SSteven Rostedt * 1) Put the instruction pointer into the IP buffer 8117666f02SSteven Rostedt * and the new code into the "code" buffer. 8217666f02SSteven Rostedt * 2) Set a flag that says we are modifying code 8317666f02SSteven Rostedt * 3) Wait for any running NMIs to finish. 8417666f02SSteven Rostedt * 4) Write the code 8517666f02SSteven Rostedt * 5) clear the flag. 8617666f02SSteven Rostedt * 6) Wait for any running NMIs to finish. 8717666f02SSteven Rostedt * 8817666f02SSteven Rostedt * If an NMI is executed, the first thing it does is to call 8917666f02SSteven Rostedt * "ftrace_nmi_enter". This will check if the flag is set to write 9017666f02SSteven Rostedt * and if it is, it will write what is in the IP and "code" buffers. 9117666f02SSteven Rostedt * 9217666f02SSteven Rostedt * The trick is, it does not matter if everyone is writing the same 9317666f02SSteven Rostedt * content to the code location. Also, if a CPU is executing code 9417666f02SSteven Rostedt * it is OK to write to that code location if the contents being written 9517666f02SSteven Rostedt * are the same as what exists. 9617666f02SSteven Rostedt */ 9717666f02SSteven Rostedt 98a26a2a27SSteven Rostedt static atomic_t in_nmi = ATOMIC_INIT(0); 99a26a2a27SSteven Rostedt static int mod_code_status; /* holds return value of text write */ 100a26a2a27SSteven Rostedt static int mod_code_write; /* set when NMI should do the write */ 101a26a2a27SSteven Rostedt static void *mod_code_ip; /* holds the IP to write to */ 102a26a2a27SSteven Rostedt static void *mod_code_newcode; /* holds the text to write to the IP */ 10317666f02SSteven Rostedt 104a26a2a27SSteven Rostedt static unsigned nmi_wait_count; 105a26a2a27SSteven Rostedt static atomic_t nmi_update_count = ATOMIC_INIT(0); 106b807c3d0SSteven Rostedt 107b807c3d0SSteven Rostedt int ftrace_arch_read_dyn_info(char *buf, int size) 108b807c3d0SSteven Rostedt { 109b807c3d0SSteven Rostedt int r; 110b807c3d0SSteven Rostedt 111b807c3d0SSteven Rostedt r = snprintf(buf, size, "%u %u", 112b807c3d0SSteven Rostedt nmi_wait_count, 113b807c3d0SSteven Rostedt atomic_read(&nmi_update_count)); 114b807c3d0SSteven Rostedt return r; 115b807c3d0SSteven Rostedt } 116b807c3d0SSteven Rostedt 11717666f02SSteven Rostedt static void ftrace_mod_code(void) 11817666f02SSteven Rostedt { 11917666f02SSteven Rostedt /* 12017666f02SSteven Rostedt * Yes, more than one CPU process can be writing to mod_code_status. 12117666f02SSteven Rostedt * (and the code itself) 12217666f02SSteven Rostedt * But if one were to fail, then they all should, and if one were 12317666f02SSteven Rostedt * to succeed, then they all should. 12417666f02SSteven Rostedt */ 12517666f02SSteven Rostedt mod_code_status = probe_kernel_write(mod_code_ip, mod_code_newcode, 12617666f02SSteven Rostedt MCOUNT_INSN_SIZE); 127*90c7ac49SSteven Rostedt 128*90c7ac49SSteven Rostedt /* if we fail, then kill any new writers */ 129*90c7ac49SSteven Rostedt if (mod_code_status) 130*90c7ac49SSteven Rostedt mod_code_write = 0; 13117666f02SSteven Rostedt } 13217666f02SSteven Rostedt 13317666f02SSteven Rostedt void ftrace_nmi_enter(void) 13417666f02SSteven Rostedt { 13517666f02SSteven Rostedt atomic_inc(&in_nmi); 13617666f02SSteven Rostedt /* Must have in_nmi seen before reading write flag */ 13717666f02SSteven Rostedt smp_mb(); 138b807c3d0SSteven Rostedt if (mod_code_write) { 13917666f02SSteven Rostedt ftrace_mod_code(); 140b807c3d0SSteven Rostedt atomic_inc(&nmi_update_count); 141b807c3d0SSteven Rostedt } 14217666f02SSteven Rostedt } 14317666f02SSteven Rostedt 14417666f02SSteven Rostedt void ftrace_nmi_exit(void) 14517666f02SSteven Rostedt { 14617666f02SSteven Rostedt /* Finish all executions before clearing in_nmi */ 14717666f02SSteven Rostedt smp_wmb(); 14817666f02SSteven Rostedt atomic_dec(&in_nmi); 14917666f02SSteven Rostedt } 15017666f02SSteven Rostedt 15117666f02SSteven Rostedt static void wait_for_nmi(void) 15217666f02SSteven Rostedt { 153b807c3d0SSteven Rostedt int waited = 0; 154b807c3d0SSteven Rostedt 155b807c3d0SSteven Rostedt while (atomic_read(&in_nmi)) { 156b807c3d0SSteven Rostedt waited = 1; 15717666f02SSteven Rostedt cpu_relax(); 15817666f02SSteven Rostedt } 15917666f02SSteven Rostedt 160b807c3d0SSteven Rostedt if (waited) 161b807c3d0SSteven Rostedt nmi_wait_count++; 162b807c3d0SSteven Rostedt } 163b807c3d0SSteven Rostedt 16417666f02SSteven Rostedt static int 16517666f02SSteven Rostedt do_ftrace_mod_code(unsigned long ip, void *new_code) 16617666f02SSteven Rostedt { 16717666f02SSteven Rostedt mod_code_ip = (void *)ip; 16817666f02SSteven Rostedt mod_code_newcode = new_code; 16917666f02SSteven Rostedt 17017666f02SSteven Rostedt /* The buffers need to be visible before we let NMIs write them */ 17117666f02SSteven Rostedt smp_wmb(); 17217666f02SSteven Rostedt 17317666f02SSteven Rostedt mod_code_write = 1; 17417666f02SSteven Rostedt 17517666f02SSteven Rostedt /* Make sure write bit is visible before we wait on NMIs */ 17617666f02SSteven Rostedt smp_mb(); 17717666f02SSteven Rostedt 17817666f02SSteven Rostedt wait_for_nmi(); 17917666f02SSteven Rostedt 18017666f02SSteven Rostedt /* Make sure all running NMIs have finished before we write the code */ 18117666f02SSteven Rostedt smp_mb(); 18217666f02SSteven Rostedt 18317666f02SSteven Rostedt ftrace_mod_code(); 18417666f02SSteven Rostedt 18517666f02SSteven Rostedt /* Make sure the write happens before clearing the bit */ 18617666f02SSteven Rostedt smp_wmb(); 18717666f02SSteven Rostedt 18817666f02SSteven Rostedt mod_code_write = 0; 18917666f02SSteven Rostedt 19017666f02SSteven Rostedt /* make sure NMIs see the cleared bit */ 19117666f02SSteven Rostedt smp_mb(); 19217666f02SSteven Rostedt 19317666f02SSteven Rostedt wait_for_nmi(); 19417666f02SSteven Rostedt 19517666f02SSteven Rostedt return mod_code_status; 19617666f02SSteven Rostedt } 19717666f02SSteven Rostedt 19817666f02SSteven Rostedt 199caf4b323SFrederic Weisbecker 200caf4b323SFrederic Weisbecker 201caf4b323SFrederic Weisbecker static unsigned char ftrace_nop[MCOUNT_INSN_SIZE]; 202caf4b323SFrederic Weisbecker 20331e88909SSteven Rostedt static unsigned char *ftrace_nop_replace(void) 204caf4b323SFrederic Weisbecker { 205caf4b323SFrederic Weisbecker return ftrace_nop; 206caf4b323SFrederic Weisbecker } 207caf4b323SFrederic Weisbecker 20831e88909SSteven Rostedt static int 2093d083395SSteven Rostedt ftrace_modify_code(unsigned long ip, unsigned char *old_code, 2103d083395SSteven Rostedt unsigned char *new_code) 2113d083395SSteven Rostedt { 2126f93fc07SSteven Rostedt unsigned char replaced[MCOUNT_INSN_SIZE]; 2133d083395SSteven Rostedt 2143d083395SSteven Rostedt /* 2153d083395SSteven Rostedt * Note: Due to modules and __init, code can 2163d083395SSteven Rostedt * disappear and change, we need to protect against faulting 21776aefee5SSteven Rostedt * as well as code changing. We do this by using the 218ab9a0918SSteven Rostedt * probe_kernel_* functions. 2193d083395SSteven Rostedt * 2203d083395SSteven Rostedt * No real locking needed, this code is run through 2216f93fc07SSteven Rostedt * kstop_machine, or before SMP starts. 2223d083395SSteven Rostedt */ 22376aefee5SSteven Rostedt 22476aefee5SSteven Rostedt /* read the text we want to modify */ 225ab9a0918SSteven Rostedt if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE)) 226593eb8a2SSteven Rostedt return -EFAULT; 2276f93fc07SSteven Rostedt 22876aefee5SSteven Rostedt /* Make sure it is what we expect it to be */ 2296f93fc07SSteven Rostedt if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0) 230593eb8a2SSteven Rostedt return -EINVAL; 2316f93fc07SSteven Rostedt 23276aefee5SSteven Rostedt /* replace the text with the new text */ 23317666f02SSteven Rostedt if (do_ftrace_mod_code(ip, new_code)) 234593eb8a2SSteven Rostedt return -EPERM; 2356f93fc07SSteven Rostedt 2363d083395SSteven Rostedt sync_core(); 2373d083395SSteven Rostedt 2386f93fc07SSteven Rostedt return 0; 2393d083395SSteven Rostedt } 2403d083395SSteven Rostedt 24131e88909SSteven Rostedt int ftrace_make_nop(struct module *mod, 24231e88909SSteven Rostedt struct dyn_ftrace *rec, unsigned long addr) 24331e88909SSteven Rostedt { 24431e88909SSteven Rostedt unsigned char *new, *old; 24531e88909SSteven Rostedt unsigned long ip = rec->ip; 24631e88909SSteven Rostedt 24731e88909SSteven Rostedt old = ftrace_call_replace(ip, addr); 24831e88909SSteven Rostedt new = ftrace_nop_replace(); 24931e88909SSteven Rostedt 25031e88909SSteven Rostedt return ftrace_modify_code(rec->ip, old, new); 25131e88909SSteven Rostedt } 25231e88909SSteven Rostedt 25331e88909SSteven Rostedt int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) 25431e88909SSteven Rostedt { 25531e88909SSteven Rostedt unsigned char *new, *old; 25631e88909SSteven Rostedt unsigned long ip = rec->ip; 25731e88909SSteven Rostedt 25831e88909SSteven Rostedt old = ftrace_nop_replace(); 25931e88909SSteven Rostedt new = ftrace_call_replace(ip, addr); 26031e88909SSteven Rostedt 26131e88909SSteven Rostedt return ftrace_modify_code(rec->ip, old, new); 26231e88909SSteven Rostedt } 26331e88909SSteven Rostedt 26415adc048SSteven Rostedt int ftrace_update_ftrace_func(ftrace_func_t func) 265d61f82d0SSteven Rostedt { 266d61f82d0SSteven Rostedt unsigned long ip = (unsigned long)(&ftrace_call); 267395a59d0SAbhishek Sagar unsigned char old[MCOUNT_INSN_SIZE], *new; 268d61f82d0SSteven Rostedt int ret; 269d61f82d0SSteven Rostedt 270395a59d0SAbhishek Sagar memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE); 271d61f82d0SSteven Rostedt new = ftrace_call_replace(ip, (unsigned long)func); 272d61f82d0SSteven Rostedt ret = ftrace_modify_code(ip, old, new); 273d61f82d0SSteven Rostedt 274d61f82d0SSteven Rostedt return ret; 275d61f82d0SSteven Rostedt } 276d61f82d0SSteven Rostedt 277d61f82d0SSteven Rostedt int __init ftrace_dyn_arch_init(void *data) 2783d083395SSteven Rostedt { 279732f3ca7SSteven Rostedt extern const unsigned char ftrace_test_p6nop[]; 280732f3ca7SSteven Rostedt extern const unsigned char ftrace_test_nop5[]; 281732f3ca7SSteven Rostedt extern const unsigned char ftrace_test_jmp[]; 282732f3ca7SSteven Rostedt int faulted = 0; 2833d083395SSteven Rostedt 284732f3ca7SSteven Rostedt /* 285732f3ca7SSteven Rostedt * There is no good nop for all x86 archs. 286732f3ca7SSteven Rostedt * We will default to using the P6_NOP5, but first we 287732f3ca7SSteven Rostedt * will test to make sure that the nop will actually 288732f3ca7SSteven Rostedt * work on this CPU. If it faults, we will then 289732f3ca7SSteven Rostedt * go to a lesser efficient 5 byte nop. If that fails 290732f3ca7SSteven Rostedt * we then just use a jmp as our nop. This isn't the most 291732f3ca7SSteven Rostedt * efficient nop, but we can not use a multi part nop 292732f3ca7SSteven Rostedt * since we would then risk being preempted in the middle 293732f3ca7SSteven Rostedt * of that nop, and if we enabled tracing then, it might 294732f3ca7SSteven Rostedt * cause a system crash. 295732f3ca7SSteven Rostedt * 296732f3ca7SSteven Rostedt * TODO: check the cpuid to determine the best nop. 297732f3ca7SSteven Rostedt */ 298732f3ca7SSteven Rostedt asm volatile ( 299732f3ca7SSteven Rostedt "ftrace_test_jmp:" 300732f3ca7SSteven Rostedt "jmp ftrace_test_p6nop\n" 3018b27386aSAnders Kaseorg "nop\n" 3028b27386aSAnders Kaseorg "nop\n" 3038b27386aSAnders Kaseorg "nop\n" /* 2 byte jmp + 3 bytes */ 304732f3ca7SSteven Rostedt "ftrace_test_p6nop:" 305732f3ca7SSteven Rostedt P6_NOP5 306732f3ca7SSteven Rostedt "jmp 1f\n" 307732f3ca7SSteven Rostedt "ftrace_test_nop5:" 308732f3ca7SSteven Rostedt ".byte 0x66,0x66,0x66,0x66,0x90\n" 309732f3ca7SSteven Rostedt "1:" 310732f3ca7SSteven Rostedt ".section .fixup, \"ax\"\n" 311732f3ca7SSteven Rostedt "2: movl $1, %0\n" 312732f3ca7SSteven Rostedt " jmp ftrace_test_nop5\n" 313732f3ca7SSteven Rostedt "3: movl $2, %0\n" 314732f3ca7SSteven Rostedt " jmp 1b\n" 315732f3ca7SSteven Rostedt ".previous\n" 316732f3ca7SSteven Rostedt _ASM_EXTABLE(ftrace_test_p6nop, 2b) 317732f3ca7SSteven Rostedt _ASM_EXTABLE(ftrace_test_nop5, 3b) 318732f3ca7SSteven Rostedt : "=r"(faulted) : "0" (faulted)); 319d61f82d0SSteven Rostedt 320732f3ca7SSteven Rostedt switch (faulted) { 321732f3ca7SSteven Rostedt case 0: 322732f3ca7SSteven Rostedt pr_info("ftrace: converting mcount calls to 0f 1f 44 00 00\n"); 3238115f3f0SSteven Rostedt memcpy(ftrace_nop, ftrace_test_p6nop, MCOUNT_INSN_SIZE); 324732f3ca7SSteven Rostedt break; 325732f3ca7SSteven Rostedt case 1: 326732f3ca7SSteven Rostedt pr_info("ftrace: converting mcount calls to 66 66 66 66 90\n"); 3278115f3f0SSteven Rostedt memcpy(ftrace_nop, ftrace_test_nop5, MCOUNT_INSN_SIZE); 328732f3ca7SSteven Rostedt break; 329732f3ca7SSteven Rostedt case 2: 3308b27386aSAnders Kaseorg pr_info("ftrace: converting mcount calls to jmp . + 5\n"); 3318115f3f0SSteven Rostedt memcpy(ftrace_nop, ftrace_test_jmp, MCOUNT_INSN_SIZE); 332732f3ca7SSteven Rostedt break; 333732f3ca7SSteven Rostedt } 334d61f82d0SSteven Rostedt 335732f3ca7SSteven Rostedt /* The return code is retured via data */ 336732f3ca7SSteven Rostedt *(unsigned long *)data = 0; 337dfa60abaSSteven Rostedt 3383d083395SSteven Rostedt return 0; 3393d083395SSteven Rostedt } 340caf4b323SFrederic Weisbecker #endif 341e7d3737eSFrederic Weisbecker 342fb52607aSFrederic Weisbecker #ifdef CONFIG_FUNCTION_GRAPH_TRACER 343e7d3737eSFrederic Weisbecker 3445a45cfe1SSteven Rostedt #ifdef CONFIG_DYNAMIC_FTRACE 3455a45cfe1SSteven Rostedt extern void ftrace_graph_call(void); 3465a45cfe1SSteven Rostedt 3475a45cfe1SSteven Rostedt static int ftrace_mod_jmp(unsigned long ip, 3485a45cfe1SSteven Rostedt int old_offset, int new_offset) 3495a45cfe1SSteven Rostedt { 3505a45cfe1SSteven Rostedt unsigned char code[MCOUNT_INSN_SIZE]; 3515a45cfe1SSteven Rostedt 3525a45cfe1SSteven Rostedt if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE)) 3535a45cfe1SSteven Rostedt return -EFAULT; 3545a45cfe1SSteven Rostedt 3555a45cfe1SSteven Rostedt if (code[0] != 0xe9 || old_offset != *(int *)(&code[1])) 3565a45cfe1SSteven Rostedt return -EINVAL; 3575a45cfe1SSteven Rostedt 3585a45cfe1SSteven Rostedt *(int *)(&code[1]) = new_offset; 3595a45cfe1SSteven Rostedt 3605a45cfe1SSteven Rostedt if (do_ftrace_mod_code(ip, &code)) 3615a45cfe1SSteven Rostedt return -EPERM; 3625a45cfe1SSteven Rostedt 3635a45cfe1SSteven Rostedt return 0; 3645a45cfe1SSteven Rostedt } 3655a45cfe1SSteven Rostedt 3665a45cfe1SSteven Rostedt int ftrace_enable_ftrace_graph_caller(void) 3675a45cfe1SSteven Rostedt { 3685a45cfe1SSteven Rostedt unsigned long ip = (unsigned long)(&ftrace_graph_call); 3695a45cfe1SSteven Rostedt int old_offset, new_offset; 3705a45cfe1SSteven Rostedt 3715a45cfe1SSteven Rostedt old_offset = (unsigned long)(&ftrace_stub) - (ip + MCOUNT_INSN_SIZE); 3725a45cfe1SSteven Rostedt new_offset = (unsigned long)(&ftrace_graph_caller) - (ip + MCOUNT_INSN_SIZE); 3735a45cfe1SSteven Rostedt 3745a45cfe1SSteven Rostedt return ftrace_mod_jmp(ip, old_offset, new_offset); 3755a45cfe1SSteven Rostedt } 3765a45cfe1SSteven Rostedt 3775a45cfe1SSteven Rostedt int ftrace_disable_ftrace_graph_caller(void) 3785a45cfe1SSteven Rostedt { 3795a45cfe1SSteven Rostedt unsigned long ip = (unsigned long)(&ftrace_graph_call); 3805a45cfe1SSteven Rostedt int old_offset, new_offset; 3815a45cfe1SSteven Rostedt 3825a45cfe1SSteven Rostedt old_offset = (unsigned long)(&ftrace_graph_caller) - (ip + MCOUNT_INSN_SIZE); 3835a45cfe1SSteven Rostedt new_offset = (unsigned long)(&ftrace_stub) - (ip + MCOUNT_INSN_SIZE); 3845a45cfe1SSteven Rostedt 3855a45cfe1SSteven Rostedt return ftrace_mod_jmp(ip, old_offset, new_offset); 3865a45cfe1SSteven Rostedt } 3875a45cfe1SSteven Rostedt 3885a45cfe1SSteven Rostedt #else /* CONFIG_DYNAMIC_FTRACE */ 389e7d3737eSFrederic Weisbecker 390e7d3737eSFrederic Weisbecker /* 391e7d3737eSFrederic Weisbecker * These functions are picked from those used on 392e7d3737eSFrederic Weisbecker * this page for dynamic ftrace. They have been 393e7d3737eSFrederic Weisbecker * simplified to ignore all traces in NMI context. 394e7d3737eSFrederic Weisbecker */ 395e7d3737eSFrederic Weisbecker static atomic_t in_nmi; 396e7d3737eSFrederic Weisbecker 397e7d3737eSFrederic Weisbecker void ftrace_nmi_enter(void) 398e7d3737eSFrederic Weisbecker { 399e7d3737eSFrederic Weisbecker atomic_inc(&in_nmi); 400e7d3737eSFrederic Weisbecker } 401e7d3737eSFrederic Weisbecker 402e7d3737eSFrederic Weisbecker void ftrace_nmi_exit(void) 403e7d3737eSFrederic Weisbecker { 404e7d3737eSFrederic Weisbecker atomic_dec(&in_nmi); 405e7d3737eSFrederic Weisbecker } 4065a45cfe1SSteven Rostedt 407e7d3737eSFrederic Weisbecker #endif /* !CONFIG_DYNAMIC_FTRACE */ 408e7d3737eSFrederic Weisbecker 409e7d3737eSFrederic Weisbecker /* Add a function return address to the trace stack on thread info.*/ 410e7d3737eSFrederic Weisbecker static int push_return_trace(unsigned long ret, unsigned long long time, 411287b6e68SFrederic Weisbecker unsigned long func, int *depth) 412e7d3737eSFrederic Weisbecker { 413e7d3737eSFrederic Weisbecker int index; 414f201ae23SFrederic Weisbecker 415f201ae23SFrederic Weisbecker if (!current->ret_stack) 416f201ae23SFrederic Weisbecker return -EBUSY; 417e7d3737eSFrederic Weisbecker 418e7d3737eSFrederic Weisbecker /* The return trace stack is full */ 419f201ae23SFrederic Weisbecker if (current->curr_ret_stack == FTRACE_RETFUNC_DEPTH - 1) { 420f201ae23SFrederic Weisbecker atomic_inc(¤t->trace_overrun); 421e7d3737eSFrederic Weisbecker return -EBUSY; 4220231022cSFrederic Weisbecker } 423e7d3737eSFrederic Weisbecker 424f201ae23SFrederic Weisbecker index = ++current->curr_ret_stack; 425e7d3737eSFrederic Weisbecker barrier(); 426f201ae23SFrederic Weisbecker current->ret_stack[index].ret = ret; 427f201ae23SFrederic Weisbecker current->ret_stack[index].func = func; 428f201ae23SFrederic Weisbecker current->ret_stack[index].calltime = time; 429287b6e68SFrederic Weisbecker *depth = index; 430e7d3737eSFrederic Weisbecker 431e7d3737eSFrederic Weisbecker return 0; 432e7d3737eSFrederic Weisbecker } 433e7d3737eSFrederic Weisbecker 434e7d3737eSFrederic Weisbecker /* Retrieve a function return address to the trace stack on thread info.*/ 435287b6e68SFrederic Weisbecker static void pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret) 436e7d3737eSFrederic Weisbecker { 437e7d3737eSFrederic Weisbecker int index; 438e7d3737eSFrederic Weisbecker 439f201ae23SFrederic Weisbecker index = current->curr_ret_stack; 44062679efeSSteven Rostedt 44162679efeSSteven Rostedt if (unlikely(index < 0)) { 44262679efeSSteven Rostedt ftrace_graph_stop(); 44362679efeSSteven Rostedt WARN_ON(1); 44462679efeSSteven Rostedt /* Might as well panic, otherwise we have no where to go */ 44562679efeSSteven Rostedt *ret = (unsigned long)panic; 44662679efeSSteven Rostedt return; 44762679efeSSteven Rostedt } 44862679efeSSteven Rostedt 449f201ae23SFrederic Weisbecker *ret = current->ret_stack[index].ret; 450287b6e68SFrederic Weisbecker trace->func = current->ret_stack[index].func; 451287b6e68SFrederic Weisbecker trace->calltime = current->ret_stack[index].calltime; 452287b6e68SFrederic Weisbecker trace->overrun = atomic_read(¤t->trace_overrun); 453287b6e68SFrederic Weisbecker trace->depth = index; 454e49dc19cSSteven Rostedt barrier(); 455f201ae23SFrederic Weisbecker current->curr_ret_stack--; 45662679efeSSteven Rostedt 457e7d3737eSFrederic Weisbecker } 458e7d3737eSFrederic Weisbecker 459e7d3737eSFrederic Weisbecker /* 460e7d3737eSFrederic Weisbecker * Send the trace to the ring-buffer. 461e7d3737eSFrederic Weisbecker * @return the original return address. 462e7d3737eSFrederic Weisbecker */ 463e7d3737eSFrederic Weisbecker unsigned long ftrace_return_to_handler(void) 464e7d3737eSFrederic Weisbecker { 465fb52607aSFrederic Weisbecker struct ftrace_graph_ret trace; 466287b6e68SFrederic Weisbecker unsigned long ret; 467e7d3737eSFrederic Weisbecker 468287b6e68SFrederic Weisbecker pop_return_trace(&trace, &ret); 469287b6e68SFrederic Weisbecker trace.rettime = cpu_clock(raw_smp_processor_id()); 470287b6e68SFrederic Weisbecker ftrace_graph_return(&trace); 471287b6e68SFrederic Weisbecker 47262679efeSSteven Rostedt if (unlikely(!ret)) { 47362679efeSSteven Rostedt ftrace_graph_stop(); 47462679efeSSteven Rostedt WARN_ON(1); 47562679efeSSteven Rostedt /* Might as well panic. What else to do? */ 47662679efeSSteven Rostedt ret = (unsigned long)panic; 47762679efeSSteven Rostedt } 47862679efeSSteven Rostedt 479287b6e68SFrederic Weisbecker return ret; 480e7d3737eSFrederic Weisbecker } 481e7d3737eSFrederic Weisbecker 482e7d3737eSFrederic Weisbecker /* 483e7d3737eSFrederic Weisbecker * Hook the return address and push it in the stack of return addrs 484e7d3737eSFrederic Weisbecker * in current thread info. 485e7d3737eSFrederic Weisbecker */ 486e7d3737eSFrederic Weisbecker void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) 487e7d3737eSFrederic Weisbecker { 488e7d3737eSFrederic Weisbecker unsigned long old; 489e7d3737eSFrederic Weisbecker unsigned long long calltime; 490e7d3737eSFrederic Weisbecker int faulted; 491287b6e68SFrederic Weisbecker struct ftrace_graph_ent trace; 492e7d3737eSFrederic Weisbecker unsigned long return_hooker = (unsigned long) 493e7d3737eSFrederic Weisbecker &return_to_handler; 494e7d3737eSFrederic Weisbecker 495e7d3737eSFrederic Weisbecker /* Nmi's are currently unsupported */ 496380c4b14SFrederic Weisbecker if (unlikely(atomic_read(&in_nmi))) 497380c4b14SFrederic Weisbecker return; 498380c4b14SFrederic Weisbecker 499380c4b14SFrederic Weisbecker if (unlikely(atomic_read(¤t->tracing_graph_pause))) 500e7d3737eSFrederic Weisbecker return; 501e7d3737eSFrederic Weisbecker 502e7d3737eSFrederic Weisbecker /* 503e7d3737eSFrederic Weisbecker * Protect against fault, even if it shouldn't 504e7d3737eSFrederic Weisbecker * happen. This tool is too much intrusive to 505e7d3737eSFrederic Weisbecker * ignore such a protection. 506e7d3737eSFrederic Weisbecker */ 507e7d3737eSFrederic Weisbecker asm volatile( 508f47a454dSSteven Rostedt "1: " _ASM_MOV " (%[parent]), %[old]\n" 509f47a454dSSteven Rostedt "2: " _ASM_MOV " %[return_hooker], (%[parent])\n" 510e7d3737eSFrederic Weisbecker " movl $0, %[faulted]\n" 511e3944bfaSSteven Rostedt "3:\n" 512e7d3737eSFrederic Weisbecker 513e7d3737eSFrederic Weisbecker ".section .fixup, \"ax\"\n" 514e3944bfaSSteven Rostedt "4: movl $1, %[faulted]\n" 515e3944bfaSSteven Rostedt " jmp 3b\n" 516e7d3737eSFrederic Weisbecker ".previous\n" 517e7d3737eSFrederic Weisbecker 518e3944bfaSSteven Rostedt _ASM_EXTABLE(1b, 4b) 519e3944bfaSSteven Rostedt _ASM_EXTABLE(2b, 4b) 520e7d3737eSFrederic Weisbecker 521f47a454dSSteven Rostedt : [old] "=r" (old), [faulted] "=r" (faulted) 522f47a454dSSteven Rostedt : [parent] "r" (parent), [return_hooker] "r" (return_hooker) 523e7d3737eSFrederic Weisbecker : "memory" 524e7d3737eSFrederic Weisbecker ); 525e7d3737eSFrederic Weisbecker 52614a866c5SSteven Rostedt if (unlikely(faulted)) { 52714a866c5SSteven Rostedt ftrace_graph_stop(); 52814a866c5SSteven Rostedt WARN_ON(1); 529e7d3737eSFrederic Weisbecker return; 530e7d3737eSFrederic Weisbecker } 531e7d3737eSFrederic Weisbecker 53214a866c5SSteven Rostedt if (unlikely(!__kernel_text_address(old))) { 53314a866c5SSteven Rostedt ftrace_graph_stop(); 534e7d3737eSFrederic Weisbecker *parent = old; 53514a866c5SSteven Rostedt WARN_ON(1); 536e7d3737eSFrederic Weisbecker return; 537e7d3737eSFrederic Weisbecker } 538e7d3737eSFrederic Weisbecker 539e7d3737eSFrederic Weisbecker calltime = cpu_clock(raw_smp_processor_id()); 540e7d3737eSFrederic Weisbecker 541287b6e68SFrederic Weisbecker if (push_return_trace(old, calltime, 542287b6e68SFrederic Weisbecker self_addr, &trace.depth) == -EBUSY) { 543e7d3737eSFrederic Weisbecker *parent = old; 544287b6e68SFrederic Weisbecker return; 545287b6e68SFrederic Weisbecker } 546287b6e68SFrederic Weisbecker 547287b6e68SFrederic Weisbecker trace.func = self_addr; 548287b6e68SFrederic Weisbecker 549e49dc19cSSteven Rostedt /* Only trace if the calling function expects to */ 550e49dc19cSSteven Rostedt if (!ftrace_graph_entry(&trace)) { 551e49dc19cSSteven Rostedt current->curr_ret_stack--; 552e49dc19cSSteven Rostedt *parent = old; 553e49dc19cSSteven Rostedt } 554e7d3737eSFrederic Weisbecker } 555fb52607aSFrederic Weisbecker #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 556