Remove dependency on kallsyms for splice_to_pipe (kernel 4.2+)
[lttng-modules.git] / probes / lttng-ftrace.c
CommitLineData
9f36eaed
MJ
1/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1)
2 *
886d51a3 3 * probes/lttng-ftrace.c
e0a7a7c4
MD
4 *
5 * LTTng function tracer integration module.
6 *
886d51a3 7 * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
e0a7a7c4
MD
8 */
9
e3de3dde
MD
10/*
11 * Ftrace function tracer does not seem to provide synchronization between probe
12 * teardown and callback execution. Therefore, we make this module permanently
13 * loaded (unloadable).
4133fce7
MD
14 *
15 * TODO: Move to register_ftrace_function() (which is exported for
16 * modules) for Linux >= 3.0. It is faster (only enables the selected
17 * functions), and will stay there.
e3de3dde
MD
18 */
19
e0a7a7c4
MD
20#include <linux/module.h>
21#include <linux/ftrace.h>
22#include <linux/slab.h>
156a3977
MD
23#include <lttng-events.h>
24#include <wrapper/ringbuffer/frontend_types.h>
25#include <wrapper/ftrace.h>
26#include <wrapper/vmalloc.h>
27#include <lttng-tracer.h>
e0a7a7c4 28
5d849667
MJ
29#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0))
30static
31void lttng_ftrace_handler(unsigned long ip, unsigned long parent_ip,
32 struct trace_array *tr, struct ftrace_probe_ops *ops,
33 void *data)
34{
35 struct lttng_event *event = data;
36 struct lttng_probe_ctx lttng_probe_ctx = {
37 .event = event,
38 .interruptible = !irqs_disabled(),
39 };
40 struct lttng_channel *chan = event->chan;
41 struct lib_ring_buffer_ctx ctx;
42 struct {
43 unsigned long ip;
44 unsigned long parent_ip;
45 } payload;
46 int ret;
47
a8f2d0c7 48 if (unlikely(!READ_ONCE(chan->session->active)))
5d849667 49 return;
a8f2d0c7 50 if (unlikely(!READ_ONCE(chan->enabled)))
5d849667 51 return;
a8f2d0c7 52 if (unlikely(!READ_ONCE(event->enabled)))
5d849667
MJ
53 return;
54
55 lib_ring_buffer_ctx_init(&ctx, chan->chan, &lttng_probe_ctx,
56 sizeof(payload), lttng_alignof(payload), -1);
57 ret = chan->ops->event_reserve(&ctx, event->id);
58 if (ret < 0)
59 return;
60 payload.ip = ip;
61 payload.parent_ip = parent_ip;
62 lib_ring_buffer_align_ctx(&ctx, lttng_alignof(payload));
63 chan->ops->event_write(&ctx, &payload, sizeof(payload));
64 chan->ops->event_commit(&ctx);
65 return;
66}
67#else
e0a7a7c4 68static
5a9479dc 69void lttng_ftrace_handler(unsigned long ip, unsigned long parent_ip, void **data)
e0a7a7c4 70{
a90917c3 71 struct lttng_event *event = *data;
79150a49
JD
72 struct lttng_probe_ctx lttng_probe_ctx = {
73 .event = event,
ccecf3fb 74 .interruptible = !irqs_disabled(),
79150a49 75 };
a90917c3 76 struct lttng_channel *chan = event->chan;
e0a7a7c4
MD
77 struct lib_ring_buffer_ctx ctx;
78 struct {
79 unsigned long ip;
80 unsigned long parent_ip;
81 } payload;
82 int ret;
83
a8f2d0c7 84 if (unlikely(!READ_ONCE(chan->session->active)))
5a9479dc 85 return;
a8f2d0c7 86 if (unlikely(!READ_ONCE(chan->enabled)))
e64957da 87 return;
a8f2d0c7 88 if (unlikely(!READ_ONCE(event->enabled)))
e64957da
MD
89 return;
90
79150a49 91 lib_ring_buffer_ctx_init(&ctx, chan->chan, &lttng_probe_ctx,
a90917c3 92 sizeof(payload), lttng_alignof(payload), -1);
4e1f08f4 93 ret = chan->ops->event_reserve(&ctx, event->id);
e0a7a7c4 94 if (ret < 0)
5a9479dc 95 return;
e0a7a7c4
MD
96 payload.ip = ip;
97 payload.parent_ip = parent_ip;
a90917c3 98 lib_ring_buffer_align_ctx(&ctx, lttng_alignof(payload));
e0a7a7c4
MD
99 chan->ops->event_write(&ctx, &payload, sizeof(payload));
100 chan->ops->event_commit(&ctx);
5a9479dc 101 return;
e0a7a7c4 102}
5d849667 103#endif
e0a7a7c4
MD
104
105/*
106 * Create event description
107 */
108static
a90917c3 109int lttng_create_ftrace_event(const char *name, struct lttng_event *event)
e0a7a7c4
MD
110{
111 struct lttng_event_field *fields;
112 struct lttng_event_desc *desc;
113 int ret;
114
115 desc = kzalloc(sizeof(*event->desc), GFP_KERNEL);
116 if (!desc)
117 return -ENOMEM;
118 desc->name = kstrdup(name, GFP_KERNEL);
119 if (!desc->name) {
120 ret = -ENOMEM;
121 goto error_str;
122 }
123 desc->nr_fields = 2;
124 desc->fields = fields =
125 kzalloc(2 * sizeof(struct lttng_event_field), GFP_KERNEL);
0d1a681e
MD
126 if (!desc->fields) {
127 ret = -ENOMEM;
128 goto error_fields;
129 }
e0a7a7c4
MD
130 fields[0].name = "ip";
131 fields[0].type.atype = atype_integer;
ba1f5986 132 fields[0].type.u.basic.integer.size = sizeof(unsigned long) * CHAR_BIT;
a90917c3 133 fields[0].type.u.basic.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT;
06254b0f 134 fields[0].type.u.basic.integer.signedness = lttng_is_signed_type(unsigned long);
e0a7a7c4
MD
135 fields[0].type.u.basic.integer.reverse_byte_order = 0;
136 fields[0].type.u.basic.integer.base = 16;
137 fields[0].type.u.basic.integer.encoding = lttng_encode_none;
138
139 fields[1].name = "parent_ip";
140 fields[1].type.atype = atype_integer;
ba1f5986 141 fields[1].type.u.basic.integer.size = sizeof(unsigned long) * CHAR_BIT;
a90917c3 142 fields[1].type.u.basic.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT;
06254b0f 143 fields[1].type.u.basic.integer.signedness = lttng_is_signed_type(unsigned long);
e0a7a7c4
MD
144 fields[1].type.u.basic.integer.reverse_byte_order = 0;
145 fields[1].type.u.basic.integer.base = 16;
146 fields[1].type.u.basic.integer.encoding = lttng_encode_none;
147
dc7f600a 148 desc->owner = THIS_MODULE;
e0a7a7c4
MD
149 event->desc = desc;
150
151 return 0;
152
0d1a681e
MD
153error_fields:
154 kfree(desc->name);
e0a7a7c4
MD
155error_str:
156 kfree(desc);
157 return ret;
158}
159
160static
161struct ftrace_probe_ops lttng_ftrace_ops = {
162 .func = lttng_ftrace_handler,
163};
164
165int lttng_ftrace_register(const char *name,
166 const char *symbol_name,
a90917c3 167 struct lttng_event *event)
e0a7a7c4
MD
168{
169 int ret;
170
171 ret = lttng_create_ftrace_event(name, event);
172 if (ret)
173 goto error;
174
8a586098 175 event->u.ftrace.symbol_name = kstrdup(symbol_name, GFP_KERNEL);
e0a7a7c4
MD
176 if (!event->u.ftrace.symbol_name)
177 goto name_error;
178
16a9a591
MD
179 /* Ensure the memory we just allocated don't trigger page faults */
180 wrapper_vmalloc_sync_all();
181
5a9479dc 182 ret = wrapper_register_ftrace_function_probe(event->u.ftrace.symbol_name,
e0a7a7c4 183 &lttng_ftrace_ops, event);
8a586098 184 if (ret < 0)
e0a7a7c4
MD
185 goto register_error;
186 return 0;
187
188register_error:
189 kfree(event->u.ftrace.symbol_name);
190name_error:
191 kfree(event->desc->name);
192 kfree(event->desc);
193error:
194 return ret;
195}
196EXPORT_SYMBOL_GPL(lttng_ftrace_register);
197
a90917c3 198void lttng_ftrace_unregister(struct lttng_event *event)
e0a7a7c4 199{
5a9479dc 200 wrapper_unregister_ftrace_function_probe(event->u.ftrace.symbol_name,
e0a7a7c4 201 &lttng_ftrace_ops, event);
edeb3137
MD
202}
203EXPORT_SYMBOL_GPL(lttng_ftrace_unregister);
204
a90917c3 205void lttng_ftrace_destroy_private(struct lttng_event *event)
edeb3137 206{
e0a7a7c4 207 kfree(event->u.ftrace.symbol_name);
25f53c39 208 kfree(event->desc->fields);
e0a7a7c4
MD
209 kfree(event->desc->name);
210 kfree(event->desc);
211}
edeb3137 212EXPORT_SYMBOL_GPL(lttng_ftrace_destroy_private);
e0a7a7c4 213
e3de3dde
MD
214int lttng_ftrace_init(void)
215{
16a9a591 216 wrapper_vmalloc_sync_all();
e3de3dde
MD
217 return 0;
218}
219module_init(lttng_ftrace_init)
220
1695dc9a
MD
221/*
222 * Ftrace takes care of waiting for a grace period (RCU sched) at probe
223 * unregistration, and disables preemption around probe call.
224 */
225void lttng_ftrace_exit(void)
226{
227}
228module_exit(lttng_ftrace_exit)
229
e0a7a7c4 230MODULE_LICENSE("GPL and additional rights");
1c124020
MJ
231MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@efficios.com>");
232MODULE_DESCRIPTION("LTTng ftrace probes");
13ab8b0a
MD
233MODULE_VERSION(__stringify(LTTNG_MODULES_MAJOR_VERSION) "."
234 __stringify(LTTNG_MODULES_MINOR_VERSION) "."
235 __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION)
236 LTTNG_MODULES_EXTRAVERSION);
This page took 0.047373 seconds and 4 git commands to generate.