Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
1
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
3a2af2d
Documentation
arch
alpha
arm
avr32
blackfin
cris
frv
h8300
ia64
m32r
m68k
m68knommu
microblaze
mips
alchemy
ar7
bcm47xx
bcm63xx
boot
cavium-octeon
cobalt
configs
dec
emma
fw
gt64120
include
jazz
kernel
cpufreq
.gitignore
8250-platform.c
Makefile
asm-offsets.c
binfmt_elfn32.c
binfmt_elfo32.c
branch.c
cevt-bcm1480.c
cevt-ds1287.c
cevt-gt641xx.c
cevt-r4k.c
cevt-sb1250.c
cevt-smtc.c
cevt-txx9.c
cpu-bugs64.c
cpu-probe.c
csrc-bcm1480.c
csrc-ioasic.c
csrc-powertv.c
csrc-r4k.c
csrc-sb1250.c
early_printk.c
entry.S
ftrace.c
genex.S
gpio_txx9.c
head.S
i8253.c
i8259.c
init_task.c
irq-gic.c
irq-gt641xx.c
irq-msc01.c
irq-rm7000.c
irq-rm9000.c
irq.c
irq_cpu.c
irq_txx9.c
kgdb.c
kspd.c
linux32.c
machine_kexec.c
mcount.S
mips-mt-fpaff.c
mips-mt.c
mips_ksyms.c
module.c
octeon_switch.S
proc.c
process.c
ptrace.c
ptrace32.c
r2300_fpu.S
r2300_switch.S
r4k_fpu.S
r4k_switch.S
r6000_fpu.S
relocate_kernel.S
reset.c
rtlx.c
scall32-o32.S
scall64-64.S
scall64-n32.S
scall64-o32.S
setup.c
signal-common.h
signal.c
signal32.c
signal_n32.c
smp-cmp.c
smp-mt.c
smp-up.c
smp.c
smtc-asm.S
smtc-proc.c
smtc.c
spinlock_test.c
spram.c
stacktrace.c
sync-r4k.c
syscall.c
time.c
topology.c
traps.c
unaligned.c
vdso.c
vmlinux.lds.S
vpe.c
watch.c
lasat
lib
loongson
math-emu
mipssim
mm
mti-malta
nxp
oprofile
pci
pmc-sierra
power
powertv
rb532
sgi-ip22
sgi-ip27
sgi-ip32
sibyte
sni
txx9
vr41xx
Kconfig
Kconfig.debug
Makefile
mn10300
parisc
powerpc
s390
score
sh
sparc
um
x86
xtensa
.gitignore
Kconfig
block
crypto
drivers
firmware
fs
include
init
ipc
kernel
lib
mm
net
samples
scripts
security
sound
tools
usr
virt
.gitignore
.mailmap
COPYING
CREDITS
Kbuild
MAINTAINERS
Makefile
README
REPORTING-BUGS
Breadcrumbs
linux
/
arch
/
mips
/
kernel
/
ftrace.c
Copy path
Blame
Blame
Latest commit
History
History
287 lines (236 loc) · 7.31 KB
Breadcrumbs
linux
/
arch
/
mips
/
kernel
/
ftrace.c
Top
File metadata and controls
Code
Blame
287 lines (236 loc) · 7.31 KB
Raw
/* * Code for replacing ftrace calls with jumps. * * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com> * Copyright (C) 2009 DSLab, Lanzhou University, China * Author: Wu Zhangjin <wuzhangjin@gmail.com> * * Thanks goes to Steven Rostedt for writing the original x86 version. */ #include <linux/uaccess.h> #include <linux/init.h> #include <linux/ftrace.h> #include <asm/cacheflush.h> #include <asm/asm.h> #include <asm/asm-offsets.h> #ifdef CONFIG_DYNAMIC_FTRACE #define JAL 0x0c000000 /* jump & link: ip --> ra, jump to target */ #define ADDR_MASK 0x03ffffff /* op_code|addr : 31...26|25 ....0 */ #define jump_insn_encode(op_code, addr) \ ((unsigned int)((op_code) | (((addr) >> 2) & ADDR_MASK))) static unsigned int ftrace_nop = 0x00000000; static int ftrace_modify_code(unsigned long ip, unsigned int new_code) { int faulted; /* *(unsigned int *)ip = new_code; */ safe_store_code(new_code, ip, faulted); if (unlikely(faulted)) return -EFAULT; flush_icache_range(ip, ip + 8); return 0; } static int lui_v1; static int jal_mcount; int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr) { unsigned int new; int faulted; unsigned long ip = rec->ip; /* We have compiled module with -mlong-calls, but compiled the kernel * without it, we need to cope with them respectively. */ if (ip & 0x40000000) { /* record it for ftrace_make_call */ if (lui_v1 == 0) { /* lui_v1 = *(unsigned int *)ip; */ safe_load_code(lui_v1, ip, faulted); if (unlikely(faulted)) return -EFAULT; } #if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) /* lui v1, hi_16bit_of_mcount --> b 1f (0x10000005) * addiu v1, v1, low_16bit_of_mcount * move at, ra * move $12, ra_address * jalr v1 * sub sp, sp, 8 * 1: offset = 5 instructions */ new = 0x10000005; #else /* lui v1, hi_16bit_of_mcount --> b 1f (0x10000004) * addiu v1, v1, low_16bit_of_mcount * move at, ra * jalr v1 * nop | move $12, ra_address | sub sp, sp, 8 * 1: offset = 4 instructions */ new = 0x10000004; #endif } else { /* record/calculate it for ftrace_make_call */ if (jal_mcount == 0) { /* We can record it directly like this: * jal_mcount = *(unsigned int *)ip; * Herein, jump over the first two nop instructions */ jal_mcount = jump_insn_encode(JAL, (MCOUNT_ADDR + 8)); } /* move at, ra * jalr v1 --> nop */ new = ftrace_nop; } return ftrace_modify_code(ip, new); } static int modified; /* initialized as 0 by default */ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) { unsigned int new; unsigned long ip = rec->ip; /* We just need to remove the "b ftrace_stub" at the fist time! */ if (modified == 0) { modified = 1; ftrace_modify_code(addr, ftrace_nop); } /* ip, module: 0xc0000000, kernel: 0x80000000 */ new = (ip & 0x40000000) ? lui_v1 : jal_mcount; return ftrace_modify_code(ip, new); } #define FTRACE_CALL_IP ((unsigned long)(&ftrace_call)) int ftrace_update_ftrace_func(ftrace_func_t func) { unsigned int new; new = jump_insn_encode(JAL, (unsigned long)func); return ftrace_modify_code(FTRACE_CALL_IP, new); } int __init ftrace_dyn_arch_init(void *data) { /* The return code is retured via data */ *(unsigned long *)data = 0; return 0; } #endif /* CONFIG_DYNAMIC_FTRACE */ #ifdef CONFIG_FUNCTION_GRAPH_TRACER #ifdef CONFIG_DYNAMIC_FTRACE extern void ftrace_graph_call(void); #define JMP 0x08000000 /* jump to target directly */ #define CALL_FTRACE_GRAPH_CALLER \ jump_insn_encode(JMP, (unsigned long)(&ftrace_graph_caller)) #define FTRACE_GRAPH_CALL_IP ((unsigned long)(&ftrace_graph_call)) int ftrace_enable_ftrace_graph_caller(void) { return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, CALL_FTRACE_GRAPH_CALLER); } int ftrace_disable_ftrace_graph_caller(void) { return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, ftrace_nop); } #endif /* !CONFIG_DYNAMIC_FTRACE */ #ifndef KBUILD_MCOUNT_RA_ADDRESS #define S_RA_SP (0xafbf << 16) /* s{d,w} ra, offset(sp) */ #define S_R_SP (0xafb0 << 16) /* s{d,w} R, offset(sp) */ #define OFFSET_MASK 0xffff /* stack offset range: 0 ~ PT_SIZE */ unsigned long ftrace_get_parent_addr(unsigned long self_addr, unsigned long parent, unsigned long parent_addr, unsigned long fp) { unsigned long sp, ip, ra; unsigned int code; int faulted; /* in module or kernel? */ if (self_addr & 0x40000000) { /* module: move to the instruction "lui v1, HI_16BIT_OF_MCOUNT" */ ip = self_addr - 20; } else { /* kernel: move to the instruction "move ra, at" */ ip = self_addr - 12; } /* search the text until finding the non-store instruction or "s{d,w} * ra, offset(sp)" instruction */ do { ip -= 4; /* get the code at "ip": code = *(unsigned int *)ip; */ safe_load_code(code, ip, faulted); if (unlikely(faulted)) return 0; /* If we hit the non-store instruction before finding where the * ra is stored, then this is a leaf function and it does not * store the ra on the stack. */ if ((code & S_R_SP) != S_R_SP) return parent_addr; } while (((code & S_RA_SP) != S_RA_SP)); sp = fp + (code & OFFSET_MASK); /* ra = *(unsigned long *)sp; */ safe_load_stack(ra, sp, faulted); if (unlikely(faulted)) return 0; if (ra == parent) return sp; return 0; } #endif /* * Hook the return address and push it in the stack of return addrs * in current thread info. */ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, unsigned long fp) { unsigned long old; struct ftrace_graph_ent trace; unsigned long return_hooker = (unsigned long) &return_to_handler; int faulted; if (unlikely(atomic_read(¤t->tracing_graph_pause))) return; /* "parent" is the stack address saved the return address of the caller * of _mcount. * * if the gcc < 4.5, a leaf function does not save the return address * in the stack address, so, we "emulate" one in _mcount's stack space, * and hijack it directly, but for a non-leaf function, it save the * return address to the its own stack space, we can not hijack it * directly, but need to find the real stack address, * ftrace_get_parent_addr() does it! * * if gcc>= 4.5, with the new -mmcount-ra-address option, for a * non-leaf function, the location of the return address will be saved * to $12 for us, and for a leaf function, only put a zero into $12. we * do it in ftrace_graph_caller of mcount.S. */ /* old = *parent; */ safe_load_stack(old, parent, faulted); if (unlikely(faulted)) goto out; #ifndef KBUILD_MCOUNT_RA_ADDRESS parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old, (unsigned long)parent, fp); /* If fails when getting the stack address of the non-leaf function's * ra, stop function graph tracer and return */ if (parent == 0) goto out; #endif /* *parent = return_hooker; */ safe_store_stack(return_hooker, parent, faulted); if (unlikely(faulted)) goto out; if (ftrace_push_return_trace(old, self_addr, &trace.depth, fp) == -EBUSY) { *parent = old; return; } trace.func = self_addr; /* Only trace if the calling function expects to */ if (!ftrace_graph_entry(&trace)) { current->curr_ret_stack--; *parent = old; } return; out: ftrace_graph_stop(); WARN_ON(1); } #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
You can’t perform that action at this time.