Fix: dma_fence tracepoint Kbuild typo
[lttng-modules.git] / src / lttng-event-notifier-notification.c
CommitLineData
21f58fb7
FD
1/* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
2 *
3 * lttng-event-notifier-notification.c
4 *
5 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
6 */
7
42f3ef8c
FD
8#include <linux/bug.h>
9
10#include <lttng/lttng-bytecode.h>
21f58fb7 11#include <lttng/events.h>
42f3ef8c 12#include <lttng/msgpack.h>
21f58fb7 13#include <lttng/event-notifier-notification.h>
437d5aa5 14#include <lttng/events-internal.h>
11b589f6 15#include <lttng/probe-user.h>
6657edec 16#include <wrapper/barrier.h>
21f58fb7 17
99d223ad 18/*
e699ee6c
MD
19 * The capture buffer size needs to be below 1024 bytes to avoid the
20 * frame to be larger than the 1024 limit enforced by the kernel. If we
21 * ever need to increase it, we will need to use a memory allocation
22 * scheme which allows allocating temporary memory chunks from the
23 * instrumentation sites. This could be done by adapting lttng
24 * tp-mempool to become nmi-safe and lock-free.
99d223ad
FD
25 */
26#define CAPTURE_BUFFER_SIZE 512
27
28struct lttng_event_notifier_notification {
29 int notification_fd;
30 uint64_t event_notifier_token;
31 uint8_t capture_buf[CAPTURE_BUFFER_SIZE];
32 struct lttng_msgpack_writer writer;
33 bool has_captures;
34};
35
42f3ef8c
FD
36static
37int capture_enum(struct lttng_msgpack_writer *writer,
38 struct lttng_interpreter_output *output)
39{
40 int ret;
41
42 /*
43 * Enums are captured as a map containing 2 key-value pairs. Such as:
44 * - type: enum
45 * value: 177
46 */
47 ret = lttng_msgpack_begin_map(writer, 2);
48 if (ret) {
49 WARN_ON_ONCE(1);
50 goto end;
51 }
52
53 ret = lttng_msgpack_write_str(writer, "type");
54 if (ret) {
55 WARN_ON_ONCE(1);
56 goto end;
57 }
58
59 ret = lttng_msgpack_write_str(writer, "enum");
60 if (ret) {
61 WARN_ON_ONCE(1);
62 goto end;
63 }
64
65 ret = lttng_msgpack_write_str(writer, "value");
66 if (ret) {
67 WARN_ON_ONCE(1);
68 goto end;
69 }
70
71 switch (output->type) {
72 case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
73 ret = lttng_msgpack_write_signed_integer(writer, output->u.s);
74 if (ret) {
75 WARN_ON_ONCE(1);
76 goto end;
77 }
78 break;
79 case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
80 ret = lttng_msgpack_write_signed_integer(writer, output->u.u);
81 if (ret) {
82 WARN_ON_ONCE(1);
83 goto end;
84 }
85 break;
86 default:
87 WARN_ON(1);
88 }
89
90 ret = lttng_msgpack_end_map(writer);
91 if (ret)
92 WARN_ON_ONCE(1);
93
94end:
95 return ret;
96}
97
98static
99int64_t capture_sequence_element_signed(uint8_t *ptr,
437d5aa5 100 const struct lttng_kernel_type_integer *type)
42f3ef8c
FD
101{
102 int64_t value = 0;
103 unsigned int size = type->size;
11b589f6 104 bool user = type->user;
42f3ef8c
FD
105 bool byte_order_reversed = type->reverse_byte_order;
106
107 switch (size) {
108 case 8:
11b589f6
MD
109 {
110 int8_t tmp;
111
112 if (user) {
113 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(int8_t)))
114 tmp = 0;
115 } else {
116 tmp = *ptr;
117 }
118 value = tmp;
42f3ef8c 119 break;
11b589f6 120 }
42f3ef8c
FD
121 case 16:
122 {
123 int16_t tmp;
11b589f6
MD
124
125 if (user) {
126 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(int16_t)))
127 tmp = 0;
128 } else {
129 tmp = *(int16_t *) ptr;
130 }
42f3ef8c
FD
131 if (byte_order_reversed)
132 __swab16s(&tmp);
42f3ef8c
FD
133 value = tmp;
134 break;
135 }
136 case 32:
137 {
138 int32_t tmp;
11b589f6
MD
139
140 if (user) {
141 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(int32_t)))
142 tmp = 0;
143 } else {
144 tmp = *(int32_t *) ptr;
145 }
42f3ef8c
FD
146 if (byte_order_reversed)
147 __swab32s(&tmp);
42f3ef8c
FD
148 value = tmp;
149 break;
150 }
151 case 64:
152 {
153 int64_t tmp;
11b589f6
MD
154
155 if (user) {
156 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(int64_t)))
157 tmp = 0;
158 } else {
159 tmp = *(int64_t *) ptr;
160 }
42f3ef8c
FD
161 if (byte_order_reversed)
162 __swab64s(&tmp);
42f3ef8c
FD
163 value = tmp;
164 break;
165 }
166 default:
167 WARN_ON(1);
168 }
169
170 return value;
171}
172
173static
174uint64_t capture_sequence_element_unsigned(uint8_t *ptr,
437d5aa5 175 const struct lttng_kernel_type_integer *type)
42f3ef8c
FD
176{
177 uint64_t value = 0;
178 unsigned int size = type->size;
11b589f6 179 bool user = type->user;
42f3ef8c
FD
180 bool byte_order_reversed = type->reverse_byte_order;
181
182 switch (size) {
183 case 8:
11b589f6
MD
184 {
185 uint8_t tmp;
186
187 if (user) {
188 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(uint8_t)))
189 tmp = 0;
190 } else {
191 tmp = *ptr;
192 }
193 value = tmp;
42f3ef8c 194 break;
11b589f6 195 }
42f3ef8c
FD
196 case 16:
197 {
198 uint16_t tmp;
11b589f6
MD
199
200 if (user) {
201 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(uint16_t)))
202 tmp = 0;
203 } else {
204 tmp = *(uint16_t *) ptr;
205 }
42f3ef8c
FD
206 if (byte_order_reversed)
207 __swab16s(&tmp);
42f3ef8c
FD
208 value = tmp;
209 break;
210 }
211 case 32:
212 {
213 uint32_t tmp;
11b589f6
MD
214
215 if (user) {
216 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(uint32_t)))
217 tmp = 0;
218 } else {
219 tmp = *(uint32_t *) ptr;
220 }
42f3ef8c
FD
221 if (byte_order_reversed)
222 __swab32s(&tmp);
42f3ef8c
FD
223 value = tmp;
224 break;
225 }
226 case 64:
227 {
228 uint64_t tmp;
11b589f6
MD
229
230 if (user) {
231 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(uint64_t)))
232 tmp = 0;
233 } else {
234 tmp = *(uint64_t *) ptr;
235 }
42f3ef8c
FD
236 if (byte_order_reversed)
237 __swab64s(&tmp);
42f3ef8c
FD
238 value = tmp;
239 break;
240 }
241 default:
242 WARN_ON(1);
243 }
244
245 return value;
246}
247
42f3ef8c
FD
248int capture_sequence(struct lttng_msgpack_writer *writer,
249 struct lttng_interpreter_output *output)
250{
437d5aa5
MD
251 const struct lttng_kernel_type_integer *integer_type = NULL;
252 const struct lttng_kernel_type_common *nested_type;
42f3ef8c
FD
253 uint8_t *ptr;
254 bool signedness;
255 int ret, i;
256
257 ret = lttng_msgpack_begin_array(writer, output->u.sequence.nr_elem);
258 if (ret) {
259 WARN_ON_ONCE(1);
260 goto end;
261 }
262
263 ptr = (uint8_t *) output->u.sequence.ptr;
264 nested_type = output->u.sequence.nested_type;
12bb2edb
MD
265 switch (nested_type->type) {
266 case lttng_kernel_type_integer:
437d5aa5 267 integer_type = lttng_kernel_get_type_integer(nested_type);
42f3ef8c 268 break;
437d5aa5 269 case lttng_kernel_type_enum:
42f3ef8c 270 /* Treat enumeration as an integer. */
437d5aa5 271 integer_type = lttng_kernel_get_type_integer(lttng_kernel_get_type_enum(nested_type)->container_type);
42f3ef8c
FD
272 break;
273 default:
274 /* Capture of array of non-integer are not supported. */
275 WARN_ON(1);
276 }
277 signedness = integer_type->signedness;
278 for (i = 0; i < output->u.sequence.nr_elem; i++) {
279 if (signedness) {
280 ret = lttng_msgpack_write_signed_integer(writer,
281 capture_sequence_element_signed(ptr, integer_type));
282 if (ret) {
283 WARN_ON_ONCE(1);
284 goto end;
285 }
286 } else {
287 ret = lttng_msgpack_write_unsigned_integer(writer,
288 capture_sequence_element_unsigned(ptr, integer_type));
289 if (ret) {
290 WARN_ON_ONCE(1);
291 goto end;
292 }
293 }
294
295 /*
296 * We assume that alignment is smaller or equal to the size.
297 * This currently holds true but if it changes in the future,
298 * we will want to change the pointer arithmetics below to
299 * take into account that the next element might be further
300 * away.
301 */
302 WARN_ON(integer_type->alignment > integer_type->size);
303
304 /* Size is in number of bits. */
305 ptr += (integer_type->size / CHAR_BIT) ;
306 }
307
308 ret = lttng_msgpack_end_array(writer);
309 if (ret)
310 WARN_ON_ONCE(1);
311end:
312 return ret;
313}
314
99d223ad
FD
315static
316int notification_append_capture(
317 struct lttng_event_notifier_notification *notif,
318 struct lttng_interpreter_output *output)
319{
320 struct lttng_msgpack_writer *writer = &notif->writer;
321 int ret = 0;
322
323 switch (output->type) {
324 case LTTNG_INTERPRETER_TYPE_S64:
325 ret = lttng_msgpack_write_signed_integer(writer, output->u.s);
326 if (ret) {
327 WARN_ON_ONCE(1);
328 goto end;
329 }
330 break;
331 case LTTNG_INTERPRETER_TYPE_U64:
332 ret = lttng_msgpack_write_unsigned_integer(writer, output->u.u);
333 if (ret) {
334 WARN_ON_ONCE(1);
335 goto end;
336 }
337 break;
338 case LTTNG_INTERPRETER_TYPE_STRING:
8915cf5e
MD
339 if (output->u.str.user) {
340 ret = lttng_msgpack_write_user_str(writer, output->u.str.user_str);
341 } else {
342 ret = lttng_msgpack_write_str(writer, output->u.str.str);
343 }
99d223ad
FD
344 if (ret) {
345 WARN_ON_ONCE(1);
346 goto end;
347 }
348 break;
349 case LTTNG_INTERPRETER_TYPE_SEQUENCE:
350 ret = capture_sequence(writer, output);
351 if (ret) {
352 WARN_ON_ONCE(1);
353 goto end;
354 }
355 break;
356 case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
357 case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
358 ret = capture_enum(writer, output);
359 if (ret) {
360 WARN_ON_ONCE(1);
361 goto end;
362 }
363 break;
364 default:
365 ret = -1;
366 WARN_ON(1);
367 }
368end:
369 return ret;
370}
371
372static
373int notification_append_empty_capture(
374 struct lttng_event_notifier_notification *notif)
375{
376 int ret = lttng_msgpack_write_nil(&notif->writer);
377 if (ret)
378 WARN_ON_ONCE(1);
379
380 return ret;
381}
382
383static
384int notification_init(struct lttng_event_notifier_notification *notif,
a67ba386 385 struct lttng_kernel_event_notifier *event_notifier)
99d223ad
FD
386{
387 struct lttng_msgpack_writer *writer = &notif->writer;
388 int ret = 0;
389
390 notif->has_captures = false;
391
a67ba386 392 if (event_notifier->priv->num_captures > 0) {
99d223ad
FD
393 lttng_msgpack_writer_init(writer, notif->capture_buf,
394 CAPTURE_BUFFER_SIZE);
395
a67ba386 396 ret = lttng_msgpack_begin_array(writer, event_notifier->priv->num_captures);
99d223ad
FD
397 if (ret) {
398 WARN_ON_ONCE(1);
399 goto end;
400 }
401
402 notif->has_captures = true;
403 }
404
405end:
406 return ret;
407}
408
99f52fcc 409static
a67ba386 410void record_error(struct lttng_kernel_event_notifier *event_notifier)
99f52fcc
FD
411{
412
a67ba386 413 struct lttng_event_notifier_group *event_notifier_group = event_notifier->priv->group;
ab04d7b1 414 struct lttng_counter *error_counter;
99f52fcc
FD
415 size_t dimension_index[1];
416 int ret;
417
ab04d7b1 418 /*
6657edec 419 * lttng_smp_load_acquire paired with lttng_smp_store_release orders
ab04d7b1
MD
420 * creation of the error counter and setting error_counter_len
421 * before the error_counter is used.
422 */
6657edec 423 error_counter = lttng_smp_load_acquire(&event_notifier_group->error_counter);
a83d6831 424 /* This group may not have an error counter attached to it. */
ab04d7b1 425 if (!error_counter)
a83d6831
FD
426 return;
427
a67ba386 428 dimension_index[0] = event_notifier->priv->error_counter_index;
99f52fcc 429
ab04d7b1 430 ret = error_counter->ops->counter_add(error_counter->counter,
99f52fcc
FD
431 dimension_index, 1);
432 if (ret)
433 WARN_ON_ONCE(1);
434}
435
99d223ad
FD
436static
437void notification_send(struct lttng_event_notifier_notification *notif,
a67ba386 438 struct lttng_kernel_event_notifier *event_notifier)
21f58fb7 439{
a67ba386 440 struct lttng_event_notifier_group *event_notifier_group = event_notifier->priv->group;
8a57ec02 441 struct lttng_kernel_ring_buffer_ctx ctx;
606828e4 442 struct lttng_kernel_abi_event_notifier_notification kernel_notif;
99d223ad 443 size_t capture_buffer_content_len, reserve_size;
21f58fb7
FD
444 int ret;
445
99d223ad 446 reserve_size = sizeof(kernel_notif);
a67ba386 447 kernel_notif.token = event_notifier->priv->parent.user_token;
21f58fb7 448
99d223ad
FD
449 if (notif->has_captures) {
450 capture_buffer_content_len = notif->writer.write_pos - notif->writer.buffer;
451 } else {
452 capture_buffer_content_len = 0;
453 }
454
455 WARN_ON_ONCE(capture_buffer_content_len > CAPTURE_BUFFER_SIZE);
456
457 reserve_size += capture_buffer_content_len;
458 kernel_notif.capture_buf_size = capture_buffer_content_len;
459
8a445457 460 lib_ring_buffer_ctx_init(&ctx, event_notifier_group->chan, reserve_size,
b1199bd3 461 lttng_alignof(kernel_notif), NULL);
c2fb9c1c 462 ret = event_notifier_group->ops->event_reserve(&ctx);
21f58fb7 463 if (ret < 0) {
99f52fcc 464 record_error(event_notifier);
21f58fb7
FD
465 return;
466 }
99d223ad 467
99d223ad
FD
468 /* Write the notif structure. */
469 event_notifier_group->ops->event_write(&ctx, &kernel_notif,
f5ffbd77 470 sizeof(kernel_notif), lttng_alignof(kernel_notif));
99d223ad
FD
471
472 /*
473 * Write the capture buffer. No need to realigned as the below is a raw
474 * char* buffer.
475 */
476 event_notifier_group->ops->event_write(&ctx, &notif->capture_buf,
f5ffbd77 477 capture_buffer_content_len, 1);
99d223ad 478
21f58fb7
FD
479 event_notifier_group->ops->event_commit(&ctx);
480 irq_work_queue(&event_notifier_group->wakeup_pending);
481}
99d223ad 482
a67ba386 483void lttng_event_notifier_notification_send(struct lttng_kernel_event_notifier *event_notifier,
c3eddb2e 484 const char *stack_data,
a92e844e 485 struct lttng_kernel_probe_ctx *probe_ctx,
a67ba386 486 struct lttng_kernel_notification_ctx *notif_ctx)
99d223ad
FD
487{
488 struct lttng_event_notifier_notification notif = { 0 };
489 int ret;
490
a67ba386 491 if (unlikely(!READ_ONCE(event_notifier->parent.enabled)))
99d223ad
FD
492 return;
493
494 ret = notification_init(&notif, event_notifier);
495 if (ret) {
496 WARN_ON_ONCE(1);
497 goto end;
498 }
499
c3eddb2e 500 if (unlikely(notif_ctx->eval_capture)) {
218585b9 501 struct lttng_kernel_bytecode_runtime *capture_bc_runtime;
99d223ad
FD
502
503 /*
504 * Iterate over all the capture bytecodes. If the interpreter
505 * functions returns successfully, append the value of the
506 * `output` parameter to the capture buffer. If the interpreter
507 * fails, append an empty capture to the buffer.
508 */
c3eddb2e 509 list_for_each_entry_rcu(capture_bc_runtime,
a67ba386 510 &event_notifier->priv->capture_bytecode_runtime_head, node) {
99d223ad
FD
511 struct lttng_interpreter_output output;
512
8a445457
MD
513 if (capture_bc_runtime->interpreter_func(capture_bc_runtime,
514 stack_data, probe_ctx, &output) == LTTNG_KERNEL_BYTECODE_INTERPRETER_OK)
99d223ad
FD
515 ret = notification_append_capture(&notif, &output);
516 else
517 ret = notification_append_empty_capture(&notif);
518
519 if (ret)
520 printk(KERN_WARNING "Error appending capture to notification");
521 }
522 }
523
524 /*
525 * Send the notification (including the capture buffer) to the
526 * sessiond.
527 */
528 notification_send(&notif, event_notifier);
529end:
530 return;
531}
This page took 0.058315 seconds and 4 git commands to generate.