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 21395a59d0SAbhishek Sagar #include <asm/ftrace.h> 22caf4b323SFrederic Weisbecker #include <linux/ftrace.h> 23732f3ca7SSteven Rostedt #include <asm/nops.h> 24caf4b323SFrederic Weisbecker #include <asm/nmi.h> 25dfa60abaSSteven Rostedt 263d083395SSteven Rostedt 27caf4b323SFrederic Weisbecker #ifdef CONFIG_DYNAMIC_FTRACE 283d083395SSteven Rostedt 293d083395SSteven Rostedt union ftrace_code_union { 30395a59d0SAbhishek Sagar char code[MCOUNT_INSN_SIZE]; 313d083395SSteven Rostedt struct { 323d083395SSteven Rostedt char e8; 333d083395SSteven Rostedt int offset; 343d083395SSteven Rostedt } __attribute__((packed)); 353d083395SSteven Rostedt }; 363d083395SSteven Rostedt 3715adc048SSteven Rostedt static int ftrace_calc_offset(long ip, long addr) 383c1720f0SSteven Rostedt { 393c1720f0SSteven Rostedt return (int)(addr - ip); 403d083395SSteven Rostedt } 413d083395SSteven Rostedt 4231e88909SSteven Rostedt static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) 433c1720f0SSteven Rostedt { 443c1720f0SSteven Rostedt static union ftrace_code_union calc; 453c1720f0SSteven Rostedt 463c1720f0SSteven Rostedt calc.e8 = 0xe8; 47395a59d0SAbhishek Sagar calc.offset = ftrace_calc_offset(ip + MCOUNT_INSN_SIZE, addr); 483c1720f0SSteven Rostedt 493c1720f0SSteven Rostedt /* 503c1720f0SSteven Rostedt * No locking needed, this must be called via kstop_machine 513c1720f0SSteven Rostedt * which in essence is like running on a uniprocessor machine. 523c1720f0SSteven Rostedt */ 533c1720f0SSteven Rostedt return calc.code; 543c1720f0SSteven Rostedt } 553c1720f0SSteven Rostedt 5617666f02SSteven Rostedt /* 5717666f02SSteven Rostedt * Modifying code must take extra care. On an SMP machine, if 5817666f02SSteven Rostedt * the code being modified is also being executed on another CPU 5917666f02SSteven Rostedt * that CPU will have undefined results and possibly take a GPF. 6017666f02SSteven Rostedt * We use kstop_machine to stop other CPUS from exectuing code. 6117666f02SSteven Rostedt * But this does not stop NMIs from happening. We still need 6217666f02SSteven Rostedt * to protect against that. We separate out the modification of 6317666f02SSteven Rostedt * the code to take care of this. 6417666f02SSteven Rostedt * 6517666f02SSteven Rostedt * Two buffers are added: An IP buffer and a "code" buffer. 6617666f02SSteven Rostedt * 67a26a2a27SSteven Rostedt * 1) Put the instruction pointer into the IP buffer 6817666f02SSteven Rostedt * and the new code into the "code" buffer. 6917666f02SSteven Rostedt * 2) Set a flag that says we are modifying code 7017666f02SSteven Rostedt * 3) Wait for any running NMIs to finish. 7117666f02SSteven Rostedt * 4) Write the code 7217666f02SSteven Rostedt * 5) clear the flag. 7317666f02SSteven Rostedt * 6) Wait for any running NMIs to finish. 7417666f02SSteven Rostedt * 7517666f02SSteven Rostedt * If an NMI is executed, the first thing it does is to call 7617666f02SSteven Rostedt * "ftrace_nmi_enter". This will check if the flag is set to write 7717666f02SSteven Rostedt * and if it is, it will write what is in the IP and "code" buffers. 7817666f02SSteven Rostedt * 7917666f02SSteven Rostedt * The trick is, it does not matter if everyone is writing the same 8017666f02SSteven Rostedt * content to the code location. Also, if a CPU is executing code 8117666f02SSteven Rostedt * it is OK to write to that code location if the contents being written 8217666f02SSteven Rostedt * are the same as what exists. 8317666f02SSteven Rostedt */ 8417666f02SSteven Rostedt 85*4e6ea144SSteven Rostedt static atomic_t nmi_running = ATOMIC_INIT(0); 86a26a2a27SSteven Rostedt static int mod_code_status; /* holds return value of text write */ 87a26a2a27SSteven Rostedt static int mod_code_write; /* set when NMI should do the write */ 88a26a2a27SSteven Rostedt static void *mod_code_ip; /* holds the IP to write to */ 89a26a2a27SSteven Rostedt static void *mod_code_newcode; /* holds the text to write to the IP */ 9017666f02SSteven Rostedt 91a26a2a27SSteven Rostedt static unsigned nmi_wait_count; 92a26a2a27SSteven Rostedt static atomic_t nmi_update_count = ATOMIC_INIT(0); 93b807c3d0SSteven Rostedt 94b807c3d0SSteven Rostedt int ftrace_arch_read_dyn_info(char *buf, int size) 95b807c3d0SSteven Rostedt { 96b807c3d0SSteven Rostedt int r; 97b807c3d0SSteven Rostedt 98b807c3d0SSteven Rostedt r = snprintf(buf, size, "%u %u", 99b807c3d0SSteven Rostedt nmi_wait_count, 100b807c3d0SSteven Rostedt atomic_read(&nmi_update_count)); 101b807c3d0SSteven Rostedt return r; 102b807c3d0SSteven Rostedt } 103b807c3d0SSteven Rostedt 10417666f02SSteven Rostedt static void ftrace_mod_code(void) 10517666f02SSteven Rostedt { 10617666f02SSteven Rostedt /* 10717666f02SSteven Rostedt * Yes, more than one CPU process can be writing to mod_code_status. 10817666f02SSteven Rostedt * (and the code itself) 10917666f02SSteven Rostedt * But if one were to fail, then they all should, and if one were 11017666f02SSteven Rostedt * to succeed, then they all should. 11117666f02SSteven Rostedt */ 11217666f02SSteven Rostedt mod_code_status = probe_kernel_write(mod_code_ip, mod_code_newcode, 11317666f02SSteven Rostedt MCOUNT_INSN_SIZE); 11417666f02SSteven Rostedt } 11517666f02SSteven Rostedt 11678d904b4SSteven Rostedt void arch_ftrace_nmi_enter(void) 11717666f02SSteven Rostedt { 118*4e6ea144SSteven Rostedt atomic_inc(&nmi_running); 119*4e6ea144SSteven Rostedt /* Must have nmi_running seen before reading write flag */ 12017666f02SSteven Rostedt smp_mb(); 121b807c3d0SSteven Rostedt if (mod_code_write) { 12217666f02SSteven Rostedt ftrace_mod_code(); 123b807c3d0SSteven Rostedt atomic_inc(&nmi_update_count); 124b807c3d0SSteven Rostedt } 12517666f02SSteven Rostedt } 12617666f02SSteven Rostedt 12778d904b4SSteven Rostedt void arch_ftrace_nmi_exit(void) 12817666f02SSteven Rostedt { 129*4e6ea144SSteven Rostedt /* Finish all executions before clearing nmi_running */ 13017666f02SSteven Rostedt smp_wmb(); 131*4e6ea144SSteven Rostedt atomic_dec(&nmi_running); 13217666f02SSteven Rostedt } 13317666f02SSteven Rostedt 13417666f02SSteven Rostedt static void wait_for_nmi(void) 13517666f02SSteven Rostedt { 136*4e6ea144SSteven Rostedt if (!atomic_read(&nmi_running)) 13789025282SCyrill Gorcunov return; 138b807c3d0SSteven Rostedt 13989025282SCyrill Gorcunov do { 14017666f02SSteven Rostedt cpu_relax(); 141*4e6ea144SSteven Rostedt } while (atomic_read(&nmi_running)); 14217666f02SSteven Rostedt 143b807c3d0SSteven Rostedt nmi_wait_count++; 144b807c3d0SSteven Rostedt } 145b807c3d0SSteven Rostedt 14617666f02SSteven Rostedt static int 14717666f02SSteven Rostedt do_ftrace_mod_code(unsigned long ip, void *new_code) 14817666f02SSteven Rostedt { 14917666f02SSteven Rostedt mod_code_ip = (void *)ip; 15017666f02SSteven Rostedt mod_code_newcode = new_code; 15117666f02SSteven Rostedt 15217666f02SSteven Rostedt /* The buffers need to be visible before we let NMIs write them */ 15317666f02SSteven Rostedt smp_wmb(); 15417666f02SSteven Rostedt 15517666f02SSteven Rostedt mod_code_write = 1; 15617666f02SSteven Rostedt 15717666f02SSteven Rostedt /* Make sure write bit is visible before we wait on NMIs */ 15817666f02SSteven Rostedt smp_mb(); 15917666f02SSteven Rostedt 16017666f02SSteven Rostedt wait_for_nmi(); 16117666f02SSteven Rostedt 16217666f02SSteven Rostedt /* Make sure all running NMIs have finished before we write the code */ 16317666f02SSteven Rostedt smp_mb(); 16417666f02SSteven Rostedt 16517666f02SSteven Rostedt ftrace_mod_code(); 16617666f02SSteven Rostedt 16717666f02SSteven Rostedt /* Make sure the write happens before clearing the bit */ 16817666f02SSteven Rostedt smp_wmb(); 16917666f02SSteven Rostedt 17017666f02SSteven Rostedt mod_code_write = 0; 17117666f02SSteven Rostedt 17217666f02SSteven Rostedt /* make sure NMIs see the cleared bit */ 17317666f02SSteven Rostedt smp_mb(); 17417666f02SSteven Rostedt 17517666f02SSteven Rostedt wait_for_nmi(); 17617666f02SSteven Rostedt 17717666f02SSteven Rostedt return mod_code_status; 17817666f02SSteven Rostedt } 17917666f02SSteven Rostedt 18017666f02SSteven Rostedt 181caf4b323SFrederic Weisbecker 182caf4b323SFrederic Weisbecker 183caf4b323SFrederic Weisbecker static unsigned char ftrace_nop[MCOUNT_INSN_SIZE]; 184caf4b323SFrederic Weisbecker 18531e88909SSteven Rostedt static unsigned char *ftrace_nop_replace(void) 186caf4b323SFrederic Weisbecker { 187caf4b323SFrederic Weisbecker return ftrace_nop; 188caf4b323SFrederic Weisbecker } 189caf4b323SFrederic Weisbecker 19031e88909SSteven Rostedt static int 1913d083395SSteven Rostedt ftrace_modify_code(unsigned long ip, unsigned char *old_code, 1923d083395SSteven Rostedt unsigned char *new_code) 1933d083395SSteven Rostedt { 1946f93fc07SSteven Rostedt unsigned char replaced[MCOUNT_INSN_SIZE]; 1953d083395SSteven Rostedt 1963d083395SSteven Rostedt /* 1973d083395SSteven Rostedt * Note: Due to modules and __init, code can 1983d083395SSteven Rostedt * disappear and change, we need to protect against faulting 19976aefee5SSteven Rostedt * as well as code changing. We do this by using the 200ab9a0918SSteven Rostedt * probe_kernel_* functions. 2013d083395SSteven Rostedt * 2023d083395SSteven Rostedt * No real locking needed, this code is run through 2036f93fc07SSteven Rostedt * kstop_machine, or before SMP starts. 2043d083395SSteven Rostedt */ 20576aefee5SSteven Rostedt 20676aefee5SSteven Rostedt /* read the text we want to modify */ 207ab9a0918SSteven Rostedt if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE)) 208593eb8a2SSteven Rostedt return -EFAULT; 2096f93fc07SSteven Rostedt 21076aefee5SSteven Rostedt /* Make sure it is what we expect it to be */ 2116f93fc07SSteven Rostedt if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0) 212593eb8a2SSteven Rostedt return -EINVAL; 2136f93fc07SSteven Rostedt 21476aefee5SSteven Rostedt /* replace the text with the new text */ 21517666f02SSteven Rostedt if (do_ftrace_mod_code(ip, new_code)) 216593eb8a2SSteven Rostedt return -EPERM; 2176f93fc07SSteven Rostedt 2183d083395SSteven Rostedt sync_core(); 2193d083395SSteven Rostedt 2206f93fc07SSteven Rostedt return 0; 2213d083395SSteven Rostedt } 2223d083395SSteven Rostedt 22331e88909SSteven Rostedt int ftrace_make_nop(struct module *mod, 22431e88909SSteven Rostedt struct dyn_ftrace *rec, unsigned long addr) 22531e88909SSteven Rostedt { 22631e88909SSteven Rostedt unsigned char *new, *old; 22731e88909SSteven Rostedt unsigned long ip = rec->ip; 22831e88909SSteven Rostedt 22931e88909SSteven Rostedt old = ftrace_call_replace(ip, addr); 23031e88909SSteven Rostedt new = ftrace_nop_replace(); 23131e88909SSteven Rostedt 23231e88909SSteven Rostedt return ftrace_modify_code(rec->ip, old, new); 23331e88909SSteven Rostedt } 23431e88909SSteven Rostedt 23531e88909SSteven Rostedt int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) 23631e88909SSteven Rostedt { 23731e88909SSteven Rostedt unsigned char *new, *old; 23831e88909SSteven Rostedt unsigned long ip = rec->ip; 23931e88909SSteven Rostedt 24031e88909SSteven Rostedt old = ftrace_nop_replace(); 24131e88909SSteven Rostedt new = ftrace_call_replace(ip, addr); 24231e88909SSteven Rostedt 24331e88909SSteven Rostedt return ftrace_modify_code(rec->ip, old, new); 24431e88909SSteven Rostedt } 24531e88909SSteven Rostedt 24615adc048SSteven Rostedt int ftrace_update_ftrace_func(ftrace_func_t func) 247d61f82d0SSteven Rostedt { 248d61f82d0SSteven Rostedt unsigned long ip = (unsigned long)(&ftrace_call); 249395a59d0SAbhishek Sagar unsigned char old[MCOUNT_INSN_SIZE], *new; 250d61f82d0SSteven Rostedt int ret; 251d61f82d0SSteven Rostedt 252395a59d0SAbhishek Sagar memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE); 253d61f82d0SSteven Rostedt new = ftrace_call_replace(ip, (unsigned long)func); 254d61f82d0SSteven Rostedt ret = ftrace_modify_code(ip, old, new); 255d61f82d0SSteven Rostedt 256d61f82d0SSteven Rostedt return ret; 257d61f82d0SSteven Rostedt } 258d61f82d0SSteven Rostedt 259d61f82d0SSteven Rostedt int __init ftrace_dyn_arch_init(void *data) 2603d083395SSteven Rostedt { 261732f3ca7SSteven Rostedt extern const unsigned char ftrace_test_p6nop[]; 262732f3ca7SSteven Rostedt extern const unsigned char ftrace_test_nop5[]; 263732f3ca7SSteven Rostedt extern const unsigned char ftrace_test_jmp[]; 264732f3ca7SSteven Rostedt int faulted = 0; 2653d083395SSteven Rostedt 266732f3ca7SSteven Rostedt /* 267732f3ca7SSteven Rostedt * There is no good nop for all x86 archs. 268732f3ca7SSteven Rostedt * We will default to using the P6_NOP5, but first we 269732f3ca7SSteven Rostedt * will test to make sure that the nop will actually 270732f3ca7SSteven Rostedt * work on this CPU. If it faults, we will then 271732f3ca7SSteven Rostedt * go to a lesser efficient 5 byte nop. If that fails 272732f3ca7SSteven Rostedt * we then just use a jmp as our nop. This isn't the most 273732f3ca7SSteven Rostedt * efficient nop, but we can not use a multi part nop 274732f3ca7SSteven Rostedt * since we would then risk being preempted in the middle 275732f3ca7SSteven Rostedt * of that nop, and if we enabled tracing then, it might 276732f3ca7SSteven Rostedt * cause a system crash. 277732f3ca7SSteven Rostedt * 278732f3ca7SSteven Rostedt * TODO: check the cpuid to determine the best nop. 279732f3ca7SSteven Rostedt */ 280732f3ca7SSteven Rostedt asm volatile ( 281732f3ca7SSteven Rostedt "ftrace_test_jmp:" 282732f3ca7SSteven Rostedt "jmp ftrace_test_p6nop\n" 2838b27386aSAnders Kaseorg "nop\n" 2848b27386aSAnders Kaseorg "nop\n" 2858b27386aSAnders Kaseorg "nop\n" /* 2 byte jmp + 3 bytes */ 286732f3ca7SSteven Rostedt "ftrace_test_p6nop:" 287732f3ca7SSteven Rostedt P6_NOP5 288732f3ca7SSteven Rostedt "jmp 1f\n" 289732f3ca7SSteven Rostedt "ftrace_test_nop5:" 290732f3ca7SSteven Rostedt ".byte 0x66,0x66,0x66,0x66,0x90\n" 291732f3ca7SSteven Rostedt "1:" 292732f3ca7SSteven Rostedt ".section .fixup, \"ax\"\n" 293732f3ca7SSteven Rostedt "2: movl $1, %0\n" 294732f3ca7SSteven Rostedt " jmp ftrace_test_nop5\n" 295732f3ca7SSteven Rostedt "3: movl $2, %0\n" 296732f3ca7SSteven Rostedt " jmp 1b\n" 297732f3ca7SSteven Rostedt ".previous\n" 298732f3ca7SSteven Rostedt _ASM_EXTABLE(ftrace_test_p6nop, 2b) 299732f3ca7SSteven Rostedt _ASM_EXTABLE(ftrace_test_nop5, 3b) 300732f3ca7SSteven Rostedt : "=r"(faulted) : "0" (faulted)); 301d61f82d0SSteven Rostedt 302732f3ca7SSteven Rostedt switch (faulted) { 303732f3ca7SSteven Rostedt case 0: 304732f3ca7SSteven Rostedt pr_info("ftrace: converting mcount calls to 0f 1f 44 00 00\n"); 3058115f3f0SSteven Rostedt memcpy(ftrace_nop, ftrace_test_p6nop, MCOUNT_INSN_SIZE); 306732f3ca7SSteven Rostedt break; 307732f3ca7SSteven Rostedt case 1: 308732f3ca7SSteven Rostedt pr_info("ftrace: converting mcount calls to 66 66 66 66 90\n"); 3098115f3f0SSteven Rostedt memcpy(ftrace_nop, ftrace_test_nop5, MCOUNT_INSN_SIZE); 310732f3ca7SSteven Rostedt break; 311732f3ca7SSteven Rostedt case 2: 3128b27386aSAnders Kaseorg pr_info("ftrace: converting mcount calls to jmp . + 5\n"); 3138115f3f0SSteven Rostedt memcpy(ftrace_nop, ftrace_test_jmp, MCOUNT_INSN_SIZE); 314732f3ca7SSteven Rostedt break; 315732f3ca7SSteven Rostedt } 316d61f82d0SSteven Rostedt 317732f3ca7SSteven Rostedt /* The return code is retured via data */ 318732f3ca7SSteven Rostedt *(unsigned long *)data = 0; 319dfa60abaSSteven Rostedt 3203d083395SSteven Rostedt return 0; 3213d083395SSteven Rostedt } 322caf4b323SFrederic Weisbecker #endif 323e7d3737eSFrederic Weisbecker 324fb52607aSFrederic Weisbecker #ifdef CONFIG_FUNCTION_GRAPH_TRACER 325e7d3737eSFrederic Weisbecker 3265a45cfe1SSteven Rostedt #ifdef CONFIG_DYNAMIC_FTRACE 3275a45cfe1SSteven Rostedt extern void ftrace_graph_call(void); 3285a45cfe1SSteven Rostedt 3295a45cfe1SSteven Rostedt static int ftrace_mod_jmp(unsigned long ip, 3305a45cfe1SSteven Rostedt int old_offset, int new_offset) 3315a45cfe1SSteven Rostedt { 3325a45cfe1SSteven Rostedt unsigned char code[MCOUNT_INSN_SIZE]; 3335a45cfe1SSteven Rostedt 3345a45cfe1SSteven Rostedt if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE)) 3355a45cfe1SSteven Rostedt return -EFAULT; 3365a45cfe1SSteven Rostedt 3375a45cfe1SSteven Rostedt if (code[0] != 0xe9 || old_offset != *(int *)(&code[1])) 3385a45cfe1SSteven Rostedt return -EINVAL; 3395a45cfe1SSteven Rostedt 3405a45cfe1SSteven Rostedt *(int *)(&code[1]) = new_offset; 3415a45cfe1SSteven Rostedt 3425a45cfe1SSteven Rostedt if (do_ftrace_mod_code(ip, &code)) 3435a45cfe1SSteven Rostedt return -EPERM; 3445a45cfe1SSteven Rostedt 3455a45cfe1SSteven Rostedt return 0; 3465a45cfe1SSteven Rostedt } 3475a45cfe1SSteven Rostedt 3485a45cfe1SSteven Rostedt int ftrace_enable_ftrace_graph_caller(void) 3495a45cfe1SSteven Rostedt { 3505a45cfe1SSteven Rostedt unsigned long ip = (unsigned long)(&ftrace_graph_call); 3515a45cfe1SSteven Rostedt int old_offset, new_offset; 3525a45cfe1SSteven Rostedt 3535a45cfe1SSteven Rostedt old_offset = (unsigned long)(&ftrace_stub) - (ip + MCOUNT_INSN_SIZE); 3545a45cfe1SSteven Rostedt new_offset = (unsigned long)(&ftrace_graph_caller) - (ip + MCOUNT_INSN_SIZE); 3555a45cfe1SSteven Rostedt 3565a45cfe1SSteven Rostedt return ftrace_mod_jmp(ip, old_offset, new_offset); 3575a45cfe1SSteven Rostedt } 3585a45cfe1SSteven Rostedt 3595a45cfe1SSteven Rostedt int ftrace_disable_ftrace_graph_caller(void) 3605a45cfe1SSteven Rostedt { 3615a45cfe1SSteven Rostedt unsigned long ip = (unsigned long)(&ftrace_graph_call); 3625a45cfe1SSteven Rostedt int old_offset, new_offset; 3635a45cfe1SSteven Rostedt 3645a45cfe1SSteven Rostedt old_offset = (unsigned long)(&ftrace_graph_caller) - (ip + MCOUNT_INSN_SIZE); 3655a45cfe1SSteven Rostedt new_offset = (unsigned long)(&ftrace_stub) - (ip + MCOUNT_INSN_SIZE); 3665a45cfe1SSteven Rostedt 3675a45cfe1SSteven Rostedt return ftrace_mod_jmp(ip, old_offset, new_offset); 3685a45cfe1SSteven Rostedt } 3695a45cfe1SSteven Rostedt 3705a45cfe1SSteven Rostedt #else /* CONFIG_DYNAMIC_FTRACE */ 371e7d3737eSFrederic Weisbecker 372e7d3737eSFrederic Weisbecker /* 373e7d3737eSFrederic Weisbecker * These functions are picked from those used on 374e7d3737eSFrederic Weisbecker * this page for dynamic ftrace. They have been 375e7d3737eSFrederic Weisbecker * simplified to ignore all traces in NMI context. 376e7d3737eSFrederic Weisbecker */ 377*4e6ea144SSteven Rostedt static atomic_t nmi_running; 378e7d3737eSFrederic Weisbecker 37978d904b4SSteven Rostedt void arch_ftrace_nmi_enter(void) 380e7d3737eSFrederic Weisbecker { 381*4e6ea144SSteven Rostedt atomic_inc(&nmi_running); 382e7d3737eSFrederic Weisbecker } 383e7d3737eSFrederic Weisbecker 38478d904b4SSteven Rostedt void arch_ftrace_nmi_exit(void) 385e7d3737eSFrederic Weisbecker { 386*4e6ea144SSteven Rostedt atomic_dec(&nmi_running); 387e7d3737eSFrederic Weisbecker } 3885a45cfe1SSteven Rostedt 389e7d3737eSFrederic Weisbecker #endif /* !CONFIG_DYNAMIC_FTRACE */ 390e7d3737eSFrederic Weisbecker 391e7d3737eSFrederic Weisbecker /* Add a function return address to the trace stack on thread info.*/ 392e7d3737eSFrederic Weisbecker static int push_return_trace(unsigned long ret, unsigned long long time, 393287b6e68SFrederic Weisbecker unsigned long func, int *depth) 394e7d3737eSFrederic Weisbecker { 395e7d3737eSFrederic Weisbecker int index; 396f201ae23SFrederic Weisbecker 397f201ae23SFrederic Weisbecker if (!current->ret_stack) 398f201ae23SFrederic Weisbecker return -EBUSY; 399e7d3737eSFrederic Weisbecker 400e7d3737eSFrederic Weisbecker /* The return trace stack is full */ 401f201ae23SFrederic Weisbecker if (current->curr_ret_stack == FTRACE_RETFUNC_DEPTH - 1) { 402f201ae23SFrederic Weisbecker atomic_inc(¤t->trace_overrun); 403e7d3737eSFrederic Weisbecker return -EBUSY; 4040231022cSFrederic Weisbecker } 405e7d3737eSFrederic Weisbecker 406f201ae23SFrederic Weisbecker index = ++current->curr_ret_stack; 407e7d3737eSFrederic Weisbecker barrier(); 408f201ae23SFrederic Weisbecker current->ret_stack[index].ret = ret; 409f201ae23SFrederic Weisbecker current->ret_stack[index].func = func; 410f201ae23SFrederic Weisbecker current->ret_stack[index].calltime = time; 411287b6e68SFrederic Weisbecker *depth = index; 412e7d3737eSFrederic Weisbecker 413e7d3737eSFrederic Weisbecker return 0; 414e7d3737eSFrederic Weisbecker } 415e7d3737eSFrederic Weisbecker 416e7d3737eSFrederic Weisbecker /* Retrieve a function return address to the trace stack on thread info.*/ 417287b6e68SFrederic Weisbecker static void pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret) 418e7d3737eSFrederic Weisbecker { 419e7d3737eSFrederic Weisbecker int index; 420e7d3737eSFrederic Weisbecker 421f201ae23SFrederic Weisbecker index = current->curr_ret_stack; 42262679efeSSteven Rostedt 42362679efeSSteven Rostedt if (unlikely(index < 0)) { 42462679efeSSteven Rostedt ftrace_graph_stop(); 42562679efeSSteven Rostedt WARN_ON(1); 42662679efeSSteven Rostedt /* Might as well panic, otherwise we have no where to go */ 42762679efeSSteven Rostedt *ret = (unsigned long)panic; 42862679efeSSteven Rostedt return; 42962679efeSSteven Rostedt } 43062679efeSSteven Rostedt 431f201ae23SFrederic Weisbecker *ret = current->ret_stack[index].ret; 432287b6e68SFrederic Weisbecker trace->func = current->ret_stack[index].func; 433287b6e68SFrederic Weisbecker trace->calltime = current->ret_stack[index].calltime; 434287b6e68SFrederic Weisbecker trace->overrun = atomic_read(¤t->trace_overrun); 435287b6e68SFrederic Weisbecker trace->depth = index; 436e49dc19cSSteven Rostedt barrier(); 437f201ae23SFrederic Weisbecker current->curr_ret_stack--; 43862679efeSSteven Rostedt 439e7d3737eSFrederic Weisbecker } 440e7d3737eSFrederic Weisbecker 441e7d3737eSFrederic Weisbecker /* 442e7d3737eSFrederic Weisbecker * Send the trace to the ring-buffer. 443e7d3737eSFrederic Weisbecker * @return the original return address. 444e7d3737eSFrederic Weisbecker */ 445e7d3737eSFrederic Weisbecker unsigned long ftrace_return_to_handler(void) 446e7d3737eSFrederic Weisbecker { 447fb52607aSFrederic Weisbecker struct ftrace_graph_ret trace; 448287b6e68SFrederic Weisbecker unsigned long ret; 449e7d3737eSFrederic Weisbecker 450287b6e68SFrederic Weisbecker pop_return_trace(&trace, &ret); 451287b6e68SFrederic Weisbecker trace.rettime = cpu_clock(raw_smp_processor_id()); 452287b6e68SFrederic Weisbecker ftrace_graph_return(&trace); 453287b6e68SFrederic Weisbecker 45462679efeSSteven Rostedt if (unlikely(!ret)) { 45562679efeSSteven Rostedt ftrace_graph_stop(); 45662679efeSSteven Rostedt WARN_ON(1); 45762679efeSSteven Rostedt /* Might as well panic. What else to do? */ 45862679efeSSteven Rostedt ret = (unsigned long)panic; 45962679efeSSteven Rostedt } 46062679efeSSteven Rostedt 461287b6e68SFrederic Weisbecker return ret; 462e7d3737eSFrederic Weisbecker } 463e7d3737eSFrederic Weisbecker 464e7d3737eSFrederic Weisbecker /* 465e7d3737eSFrederic Weisbecker * Hook the return address and push it in the stack of return addrs 466e7d3737eSFrederic Weisbecker * in current thread info. 467e7d3737eSFrederic Weisbecker */ 468e7d3737eSFrederic Weisbecker void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) 469e7d3737eSFrederic Weisbecker { 470e7d3737eSFrederic Weisbecker unsigned long old; 471e7d3737eSFrederic Weisbecker unsigned long long calltime; 472e7d3737eSFrederic Weisbecker int faulted; 473287b6e68SFrederic Weisbecker struct ftrace_graph_ent trace; 474e7d3737eSFrederic Weisbecker unsigned long return_hooker = (unsigned long) 475e7d3737eSFrederic Weisbecker &return_to_handler; 476e7d3737eSFrederic Weisbecker 477e7d3737eSFrederic Weisbecker /* Nmi's are currently unsupported */ 478*4e6ea144SSteven Rostedt if (unlikely(atomic_read(&nmi_running))) 479380c4b14SFrederic Weisbecker return; 480380c4b14SFrederic Weisbecker 481380c4b14SFrederic Weisbecker if (unlikely(atomic_read(¤t->tracing_graph_pause))) 482e7d3737eSFrederic Weisbecker return; 483e7d3737eSFrederic Weisbecker 484e7d3737eSFrederic Weisbecker /* 485e7d3737eSFrederic Weisbecker * Protect against fault, even if it shouldn't 486e7d3737eSFrederic Weisbecker * happen. This tool is too much intrusive to 487e7d3737eSFrederic Weisbecker * ignore such a protection. 488e7d3737eSFrederic Weisbecker */ 489e7d3737eSFrederic Weisbecker asm volatile( 490347fdd9dSSteven Rostedt "1: " _ASM_MOV " (%[parent_old]), %[old]\n" 491347fdd9dSSteven Rostedt "2: " _ASM_MOV " %[return_hooker], (%[parent_replaced])\n" 492e7d3737eSFrederic Weisbecker " movl $0, %[faulted]\n" 493e7d3737eSFrederic Weisbecker 494e7d3737eSFrederic Weisbecker ".section .fixup, \"ax\"\n" 495e7d3737eSFrederic Weisbecker "3: movl $1, %[faulted]\n" 496e7d3737eSFrederic Weisbecker ".previous\n" 497e7d3737eSFrederic Weisbecker 498347fdd9dSSteven Rostedt _ASM_EXTABLE(1b, 3b) 499347fdd9dSSteven Rostedt _ASM_EXTABLE(2b, 3b) 500e7d3737eSFrederic Weisbecker 501e7d3737eSFrederic Weisbecker : [parent_replaced] "=r" (parent), [old] "=r" (old), 502e7d3737eSFrederic Weisbecker [faulted] "=r" (faulted) 503e7d3737eSFrederic Weisbecker : [parent_old] "0" (parent), [return_hooker] "r" (return_hooker) 504e7d3737eSFrederic Weisbecker : "memory" 505e7d3737eSFrederic Weisbecker ); 506e7d3737eSFrederic Weisbecker 50714a866c5SSteven Rostedt if (unlikely(faulted)) { 50814a866c5SSteven Rostedt ftrace_graph_stop(); 50914a866c5SSteven Rostedt WARN_ON(1); 510e7d3737eSFrederic Weisbecker return; 511e7d3737eSFrederic Weisbecker } 512e7d3737eSFrederic Weisbecker 51314a866c5SSteven Rostedt if (unlikely(!__kernel_text_address(old))) { 51414a866c5SSteven Rostedt ftrace_graph_stop(); 515e7d3737eSFrederic Weisbecker *parent = old; 51614a866c5SSteven Rostedt WARN_ON(1); 517e7d3737eSFrederic Weisbecker return; 518e7d3737eSFrederic Weisbecker } 519e7d3737eSFrederic Weisbecker 520e7d3737eSFrederic Weisbecker calltime = cpu_clock(raw_smp_processor_id()); 521e7d3737eSFrederic Weisbecker 522287b6e68SFrederic Weisbecker if (push_return_trace(old, calltime, 523287b6e68SFrederic Weisbecker self_addr, &trace.depth) == -EBUSY) { 524e7d3737eSFrederic Weisbecker *parent = old; 525287b6e68SFrederic Weisbecker return; 526287b6e68SFrederic Weisbecker } 527287b6e68SFrederic Weisbecker 528287b6e68SFrederic Weisbecker trace.func = self_addr; 529287b6e68SFrederic Weisbecker 530e49dc19cSSteven Rostedt /* Only trace if the calling function expects to */ 531e49dc19cSSteven Rostedt if (!ftrace_graph_entry(&trace)) { 532e49dc19cSSteven Rostedt current->curr_ret_stack--; 533e49dc19cSSteven Rostedt *parent = old; 534e49dc19cSSteven Rostedt } 535e7d3737eSFrederic Weisbecker } 536fb52607aSFrederic Weisbecker #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 537