1 /* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
3 * lttng-event-notifier-notification.c
5 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
10 #include <lttng/lttng-bytecode.h>
11 #include <lttng/events.h>
12 #include <lttng/msgpack.h>
13 #include <lttng/event-notifier-notification.h>
16 * The capture buffer size needs to be below 1024 bytes to avoid the
17 * frame to be larger than the 1024 limit enforced by the kernel. If we
18 * ever need to increase it, we will need to use a memory allocation
19 * scheme which allows allocating temporary memory chunks from the
20 * instrumentation sites. This could be done by adapting lttng
21 * tp-mempool to become nmi-safe and lock-free.
23 #define CAPTURE_BUFFER_SIZE 512
25 struct lttng_event_notifier_notification
{
27 uint64_t event_notifier_token
;
28 uint8_t capture_buf
[CAPTURE_BUFFER_SIZE
];
29 struct lttng_msgpack_writer writer
;
34 int capture_enum(struct lttng_msgpack_writer
*writer
,
35 struct lttng_interpreter_output
*output
)
40 * Enums are captured as a map containing 2 key-value pairs. Such as:
44 ret
= lttng_msgpack_begin_map(writer
, 2);
50 ret
= lttng_msgpack_write_str(writer
, "type");
56 ret
= lttng_msgpack_write_str(writer
, "enum");
62 ret
= lttng_msgpack_write_str(writer
, "value");
68 switch (output
->type
) {
69 case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM
:
70 ret
= lttng_msgpack_write_signed_integer(writer
, output
->u
.s
);
76 case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM
:
77 ret
= lttng_msgpack_write_signed_integer(writer
, output
->u
.u
);
87 ret
= lttng_msgpack_end_map(writer
);
96 int64_t capture_sequence_element_signed(uint8_t *ptr
,
97 const struct lttng_integer_type
*type
)
100 unsigned int size
= type
->size
;
101 bool byte_order_reversed
= type
->reverse_byte_order
;
110 tmp
= *(int16_t *) ptr
;
111 if (byte_order_reversed
)
120 tmp
= *(int32_t *) ptr
;
121 if (byte_order_reversed
)
130 tmp
= *(int64_t *) ptr
;
131 if (byte_order_reversed
)
145 uint64_t capture_sequence_element_unsigned(uint8_t *ptr
,
146 const struct lttng_integer_type
*type
)
149 unsigned int size
= type
->size
;
150 bool byte_order_reversed
= type
->reverse_byte_order
;
159 tmp
= *(uint16_t *) ptr
;
160 if (byte_order_reversed
)
169 tmp
= *(uint32_t *) ptr
;
170 if (byte_order_reversed
)
179 tmp
= *(uint64_t *) ptr
;
180 if (byte_order_reversed
)
193 int capture_sequence(struct lttng_msgpack_writer
*writer
,
194 struct lttng_interpreter_output
*output
)
196 const struct lttng_integer_type
*integer_type
= NULL
;
197 const struct lttng_type
*nested_type
;
202 ret
= lttng_msgpack_begin_array(writer
, output
->u
.sequence
.nr_elem
);
208 ptr
= (uint8_t *) output
->u
.sequence
.ptr
;
209 nested_type
= output
->u
.sequence
.nested_type
;
210 switch (nested_type
->atype
) {
212 integer_type
= &nested_type
->u
.integer
;
214 case atype_enum_nestable
:
215 /* Treat enumeration as an integer. */
216 integer_type
= &nested_type
->u
.enum_nestable
.container_type
->u
.integer
;
219 /* Capture of array of non-integer are not supported. */
222 signedness
= integer_type
->signedness
;
223 for (i
= 0; i
< output
->u
.sequence
.nr_elem
; i
++) {
225 ret
= lttng_msgpack_write_signed_integer(writer
,
226 capture_sequence_element_signed(ptr
, integer_type
));
232 ret
= lttng_msgpack_write_unsigned_integer(writer
,
233 capture_sequence_element_unsigned(ptr
, integer_type
));
241 * We assume that alignment is smaller or equal to the size.
242 * This currently holds true but if it changes in the future,
243 * we will want to change the pointer arithmetics below to
244 * take into account that the next element might be further
247 WARN_ON(integer_type
->alignment
> integer_type
->size
);
249 /* Size is in number of bits. */
250 ptr
+= (integer_type
->size
/ CHAR_BIT
) ;
253 ret
= lttng_msgpack_end_array(writer
);
261 int notification_append_capture(
262 struct lttng_event_notifier_notification
*notif
,
263 struct lttng_interpreter_output
*output
)
265 struct lttng_msgpack_writer
*writer
= ¬if
->writer
;
268 switch (output
->type
) {
269 case LTTNG_INTERPRETER_TYPE_S64
:
270 ret
= lttng_msgpack_write_signed_integer(writer
, output
->u
.s
);
276 case LTTNG_INTERPRETER_TYPE_U64
:
277 ret
= lttng_msgpack_write_unsigned_integer(writer
, output
->u
.u
);
283 case LTTNG_INTERPRETER_TYPE_STRING
:
284 ret
= lttng_msgpack_write_str(writer
, output
->u
.str
.str
);
290 case LTTNG_INTERPRETER_TYPE_SEQUENCE
:
291 ret
= capture_sequence(writer
, output
);
297 case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM
:
298 case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM
:
299 ret
= capture_enum(writer
, output
);
314 int notification_append_empty_capture(
315 struct lttng_event_notifier_notification
*notif
)
317 int ret
= lttng_msgpack_write_nil(¬if
->writer
);
325 int notification_init(struct lttng_event_notifier_notification
*notif
,
326 struct lttng_event_notifier
*event_notifier
)
328 struct lttng_msgpack_writer
*writer
= ¬if
->writer
;
331 notif
->has_captures
= false;
333 if (event_notifier
->num_captures
> 0) {
334 lttng_msgpack_writer_init(writer
, notif
->capture_buf
,
335 CAPTURE_BUFFER_SIZE
);
337 ret
= lttng_msgpack_begin_array(writer
, event_notifier
->num_captures
);
343 notif
->has_captures
= true;
351 void record_error(struct lttng_event_notifier
*event_notifier
)
354 struct lttng_event_notifier_group
*event_notifier_group
= event_notifier
->group
;
355 size_t dimension_index
[1];
358 dimension_index
[0] = event_notifier
->error_counter_index
;
360 ret
= event_notifier_group
->error_counter
->ops
->counter_add(
361 event_notifier_group
->error_counter
->counter
,
368 void notification_send(struct lttng_event_notifier_notification
*notif
,
369 struct lttng_event_notifier
*event_notifier
)
371 struct lttng_event_notifier_group
*event_notifier_group
= event_notifier
->group
;
372 struct lib_ring_buffer_ctx ctx
;
373 struct lttng_kernel_event_notifier_notification kernel_notif
;
374 size_t capture_buffer_content_len
, reserve_size
;
377 reserve_size
= sizeof(kernel_notif
);
378 kernel_notif
.token
= event_notifier
->user_token
;
380 if (notif
->has_captures
) {
381 capture_buffer_content_len
= notif
->writer
.write_pos
- notif
->writer
.buffer
;
383 capture_buffer_content_len
= 0;
386 WARN_ON_ONCE(capture_buffer_content_len
> CAPTURE_BUFFER_SIZE
);
388 reserve_size
+= capture_buffer_content_len
;
389 kernel_notif
.capture_buf_size
= capture_buffer_content_len
;
391 lib_ring_buffer_ctx_init(&ctx
, event_notifier_group
->chan
, NULL
, reserve_size
,
392 lttng_alignof(kernel_notif
), -1);
393 ret
= event_notifier_group
->ops
->event_reserve(&ctx
, 0);
395 record_error(event_notifier
);
399 lib_ring_buffer_align_ctx(&ctx
, lttng_alignof(kernel_notif
));
401 /* Write the notif structure. */
402 event_notifier_group
->ops
->event_write(&ctx
, &kernel_notif
,
403 sizeof(kernel_notif
));
406 * Write the capture buffer. No need to realigned as the below is a raw
409 event_notifier_group
->ops
->event_write(&ctx
, ¬if
->capture_buf
,
410 capture_buffer_content_len
);
412 event_notifier_group
->ops
->event_commit(&ctx
);
413 irq_work_queue(&event_notifier_group
->wakeup_pending
);
416 void lttng_event_notifier_notification_send(struct lttng_event_notifier
*event_notifier
,
417 struct lttng_probe_ctx
*lttng_probe_ctx
,
418 const char *stack_data
)
420 struct lttng_event_notifier_notification notif
= { 0 };
423 if (unlikely(!READ_ONCE(event_notifier
->enabled
)))
426 ret
= notification_init(¬if
, event_notifier
);
432 if (unlikely(!list_empty(&event_notifier
->capture_bytecode_runtime_head
))) {
433 struct lttng_bytecode_runtime
*capture_bc_runtime
;
436 * Iterate over all the capture bytecodes. If the interpreter
437 * functions returns successfully, append the value of the
438 * `output` parameter to the capture buffer. If the interpreter
439 * fails, append an empty capture to the buffer.
441 list_for_each_entry(capture_bc_runtime
,
442 &event_notifier
->capture_bytecode_runtime_head
, node
) {
443 struct lttng_interpreter_output output
;
445 if (capture_bc_runtime
->interpreter_funcs
.capture(capture_bc_runtime
,
446 lttng_probe_ctx
, stack_data
, &output
) & LTTNG_INTERPRETER_RECORD_FLAG
)
447 ret
= notification_append_capture(¬if
, &output
);
449 ret
= notification_append_empty_capture(¬if
);
452 printk(KERN_WARNING
"Error appending capture to notification");
457 * Send the notification (including the capture buffer) to the
460 notification_send(¬if
, event_notifier
);