^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Dynamic function tracing support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2008 Abhishek Sagar <sagar.abhishek@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2010 Rabin Vincent <rabin@rab.in>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * For licencing details, see COPYING.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Defines low-level handling of mcount calls when the kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * is compiled with the -pg flag. When using dynamic ftrace, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * mcount call-sites get patched with NOP till they are enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * All code mutation routines here are called under stop_machine().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/ftrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/stop_machine.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/opcodes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/ftrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/insn.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/set_memory.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/patch.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #ifdef CONFIG_THUMB2_KERNEL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define NOP 0xf85deb04 /* pop.w {lr} */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define NOP 0xe8bd4000 /* pop {lr} */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #ifdef CONFIG_DYNAMIC_FTRACE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static int __ftrace_modify_code(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int *command = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) ftrace_modify_all_code(*command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) void arch_ftrace_update_code(int command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) stop_machine(__ftrace_modify_code, &command, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return NOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) int ftrace_arch_code_modify_prepare(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) int ftrace_arch_code_modify_post_process(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* Make sure any TLB misses during machine stop are cleared. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) flush_tlb_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) bool warn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return arm_gen_branch_link(pc, addr, warn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static int ftrace_modify_code(unsigned long pc, unsigned long old,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned long new, bool validate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) unsigned long replaced;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (IS_ENABLED(CONFIG_THUMB2_KERNEL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) old = __opcode_to_mem_thumb32(old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) old = __opcode_to_mem_arm(old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (validate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (copy_from_kernel_nofault(&replaced, (void *)pc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) MCOUNT_INSN_SIZE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (replaced != old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) __patch_text((void *)pc, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int ftrace_update_ftrace_func(ftrace_func_t func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) unsigned long pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) unsigned long new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) pc = (unsigned long)&ftrace_call;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) new = ftrace_call_replace(pc, (unsigned long)func, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) ret = ftrace_modify_code(pc, 0, new, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) pc = (unsigned long)&ftrace_regs_call;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) new = ftrace_call_replace(pc, (unsigned long)func, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ret = ftrace_modify_code(pc, 0, new, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) unsigned long new, old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) unsigned long ip = rec->ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) unsigned long aaddr = adjust_address(rec, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct module *mod = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #ifdef CONFIG_ARM_MODULE_PLTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) mod = rec->arch.mod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) old = ftrace_nop_replace(rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) new = ftrace_call_replace(ip, aaddr, !mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #ifdef CONFIG_ARM_MODULE_PLTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (!new && mod) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) aaddr = get_module_plt(mod, ip, aaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) new = ftrace_call_replace(ip, aaddr, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return ftrace_modify_code(rec->ip, old, new, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) unsigned long new, old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) unsigned long ip = rec->ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) old = ftrace_call_replace(ip, adjust_address(rec, old_addr), true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) new = ftrace_call_replace(ip, adjust_address(rec, addr), true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return ftrace_modify_code(rec->ip, old, new, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) int ftrace_make_nop(struct module *mod,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct dyn_ftrace *rec, unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) unsigned long aaddr = adjust_address(rec, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) unsigned long ip = rec->ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) unsigned long old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) unsigned long new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #ifdef CONFIG_ARM_MODULE_PLTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /* mod is only supplied during module loading */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (!mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) mod = rec->arch.mod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) rec->arch.mod = mod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) old = ftrace_call_replace(ip, aaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) !IS_ENABLED(CONFIG_ARM_MODULE_PLTS) || !mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #ifdef CONFIG_ARM_MODULE_PLTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (!old && mod) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) aaddr = get_module_plt(mod, ip, aaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) old = ftrace_call_replace(ip, aaddr, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) new = ftrace_nop_replace(rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ret = ftrace_modify_code(ip, old, new, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) int __init ftrace_dyn_arch_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #endif /* CONFIG_DYNAMIC_FTRACE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) #ifdef CONFIG_FUNCTION_GRAPH_TRACER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) unsigned long frame_pointer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) unsigned long return_hooker = (unsigned long) &return_to_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) unsigned long old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (unlikely(atomic_read(¤t->tracing_graph_pause)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) old = *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) *parent = return_hooker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (function_graph_enter(old, self_addr, frame_pointer, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) *parent = old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) #ifdef CONFIG_DYNAMIC_FTRACE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) extern unsigned long ftrace_graph_call;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) extern unsigned long ftrace_graph_call_old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) extern void ftrace_graph_caller_old(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) extern unsigned long ftrace_graph_regs_call;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) extern void ftrace_graph_regs_caller(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static int __ftrace_modify_caller(unsigned long *callsite,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) void (*func) (void), bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) unsigned long caller_fn = (unsigned long) func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) unsigned long pc = (unsigned long) callsite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) unsigned long branch = arm_gen_branch(pc, caller_fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) unsigned long nop = 0xe1a00000; /* mov r0, r0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) unsigned long old = enable ? nop : branch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) unsigned long new = enable ? branch : nop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return ftrace_modify_code(pc, old, new, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static int ftrace_modify_graph_caller(bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) ret = __ftrace_modify_caller(&ftrace_graph_call,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) ftrace_graph_caller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) ret = __ftrace_modify_caller(&ftrace_graph_regs_call,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ftrace_graph_regs_caller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) int ftrace_enable_ftrace_graph_caller(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return ftrace_modify_graph_caller(true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) int ftrace_disable_ftrace_graph_caller(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return ftrace_modify_graph_caller(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) #endif /* CONFIG_DYNAMIC_FTRACE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) #endif /* CONFIG_FUNCTION_GRAPH_TRACER */