aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/ftrace.c
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2009-06-12 04:26:44 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-06-12 04:27:38 -0400
commitdfd9f7abc0fb67b5781f340d982384cea53b2884 (patch)
tree850baae88167699f45ba1dea1765b9156373db72 /arch/s390/kernel/ftrace.c
parenta2b53673fae14601bb520acf6a6f154463994565 (diff)
[S390] ftrace: add dynamic ftrace support
Dynamic ftrace support for s390. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/ftrace.c')
-rw-r--r--arch/s390/kernel/ftrace.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c
new file mode 100644
index 000000000000..0b81a784e039
--- /dev/null
+++ b/arch/s390/kernel/ftrace.c
@@ -0,0 +1,132 @@
1/*
2 * Dynamic function tracer architecture backend.
3 *
4 * Copyright IBM Corp. 2009
5 *
6 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
7 *
8 */
9
10#include <linux/uaccess.h>
11#include <linux/ftrace.h>
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <asm/lowcore.h>
15
16void ftrace_disable_code(void);
17void ftrace_call_code(void);
18void ftrace_nop_code(void);
19
20#define FTRACE_INSN_SIZE 4
21
22#ifdef CONFIG_64BIT
23
24asm(
25 " .align 4\n"
26 "ftrace_disable_code:\n"
27 " j 0f\n"
28 " .word 0x0024\n"
29 " lg %r1,"__stringify(__LC_FTRACE_FUNC)"\n"
30 " basr %r14,%r1\n"
31 " lg %r14,8(15)\n"
32 " lgr %r0,%r0\n"
33 "0:\n");
34
35asm(
36 " .align 4\n"
37 "ftrace_nop_code:\n"
38 " j .+"__stringify(MCOUNT_INSN_SIZE)"\n");
39
40asm(
41 " .align 4\n"
42 "ftrace_call_code:\n"
43 " stg %r14,8(%r15)\n");
44
45#else /* CONFIG_64BIT */
46
47asm(
48 " .align 4\n"
49 "ftrace_disable_code:\n"
50 " j 0f\n"
51 " l %r1,"__stringify(__LC_FTRACE_FUNC)"\n"
52 " basr %r14,%r1\n"
53 " l %r14,4(%r15)\n"
54 " j 0f\n"
55 " bcr 0,%r7\n"
56 " bcr 0,%r7\n"
57 " bcr 0,%r7\n"
58 " bcr 0,%r7\n"
59 " bcr 0,%r7\n"
60 " bcr 0,%r7\n"
61 "0:\n");
62
63asm(
64 " .align 4\n"
65 "ftrace_nop_code:\n"
66 " j .+"__stringify(MCOUNT_INSN_SIZE)"\n");
67
68asm(
69 " .align 4\n"
70 "ftrace_call_code:\n"
71 " st %r14,4(%r15)\n");
72
73#endif /* CONFIG_64BIT */
74
75static int ftrace_modify_code(unsigned long ip,
76 void *old_code, int old_size,
77 void *new_code, int new_size)
78{
79 unsigned char replaced[MCOUNT_INSN_SIZE];
80
81 /*
82 * Note: Due to modules code can disappear and change.
83 * We need to protect against faulting as well as code
84 * changing. We do this by using the probe_kernel_*
85 * functions.
86 * This however is just a simple sanity check.
87 */
88 if (probe_kernel_read(replaced, (void *)ip, old_size))
89 return -EFAULT;
90 if (memcmp(replaced, old_code, old_size) != 0)
91 return -EINVAL;
92 if (probe_kernel_write((void *)ip, new_code, new_size))
93 return -EPERM;
94 return 0;
95}
96
97static int ftrace_make_initial_nop(struct module *mod, struct dyn_ftrace *rec,
98 unsigned long addr)
99{
100 return ftrace_modify_code(rec->ip,
101 ftrace_call_code, FTRACE_INSN_SIZE,
102 ftrace_disable_code, MCOUNT_INSN_SIZE);
103}
104
105int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
106 unsigned long addr)
107{
108 if (addr == MCOUNT_ADDR)
109 return ftrace_make_initial_nop(mod, rec, addr);
110 return ftrace_modify_code(rec->ip,
111 ftrace_call_code, FTRACE_INSN_SIZE,
112 ftrace_nop_code, FTRACE_INSN_SIZE);
113}
114
115int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
116{
117 return ftrace_modify_code(rec->ip,
118 ftrace_nop_code, FTRACE_INSN_SIZE,
119 ftrace_call_code, FTRACE_INSN_SIZE);
120}
121
122int ftrace_update_ftrace_func(ftrace_func_t func)
123{
124 ftrace_dyn_func = (unsigned long)func;
125 return 0;
126}
127
128int __init ftrace_dyn_arch_init(void *data)
129{
130 *(unsigned long *)data = 0;
131 return 0;
132}