b67af11a77ecf0763801030346d6ceefc5f7ace1
[lttng-modules.git] / src / lttng-event-notifier-notification.c
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
8 #include <linux/bug.h>
9
10 #include <lttng/lttng-bytecode.h>
11 #include <lttng/events.h>
12 #include <lttng/msgpack.h>
13 #include <lttng/event-notifier-notification.h>
14
15 /*
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.
22 */
23 #define CAPTURE_BUFFER_SIZE 512
24
25 struct lttng_event_notifier_notification {
26 int notification_fd;
27 uint64_t event_notifier_token;
28 uint8_t capture_buf[CAPTURE_BUFFER_SIZE];
29 struct lttng_msgpack_writer writer;
30 bool has_captures;
31 };
32
33 static
34 int capture_enum(struct lttng_msgpack_writer *writer,
35 struct lttng_interpreter_output *output)
36 {
37 int ret;
38
39 /*
40 * Enums are captured as a map containing 2 key-value pairs. Such as:
41 * - type: enum
42 * value: 177
43 */
44 ret = lttng_msgpack_begin_map(writer, 2);
45 if (ret) {
46 WARN_ON_ONCE(1);
47 goto end;
48 }
49
50 ret = lttng_msgpack_write_str(writer, "type");
51 if (ret) {
52 WARN_ON_ONCE(1);
53 goto end;
54 }
55
56 ret = lttng_msgpack_write_str(writer, "enum");
57 if (ret) {
58 WARN_ON_ONCE(1);
59 goto end;
60 }
61
62 ret = lttng_msgpack_write_str(writer, "value");
63 if (ret) {
64 WARN_ON_ONCE(1);
65 goto end;
66 }
67
68 switch (output->type) {
69 case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
70 ret = lttng_msgpack_write_signed_integer(writer, output->u.s);
71 if (ret) {
72 WARN_ON_ONCE(1);
73 goto end;
74 }
75 break;
76 case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
77 ret = lttng_msgpack_write_signed_integer(writer, output->u.u);
78 if (ret) {
79 WARN_ON_ONCE(1);
80 goto end;
81 }
82 break;
83 default:
84 WARN_ON(1);
85 }
86
87 ret = lttng_msgpack_end_map(writer);
88 if (ret)
89 WARN_ON_ONCE(1);
90
91 end:
92 return ret;
93 }
94
95 static
96 int64_t capture_sequence_element_signed(uint8_t *ptr,
97 const struct lttng_integer_type *type)
98 {
99 int64_t value = 0;
100 unsigned int size = type->size;
101 bool byte_order_reversed = type->reverse_byte_order;
102
103 switch (size) {
104 case 8:
105 value = *ptr;
106 break;
107 case 16:
108 {
109 int16_t tmp;
110 tmp = *(int16_t *) ptr;
111 if (byte_order_reversed)
112 __swab16s(&tmp);
113
114 value = tmp;
115 break;
116 }
117 case 32:
118 {
119 int32_t tmp;
120 tmp = *(int32_t *) ptr;
121 if (byte_order_reversed)
122 __swab32s(&tmp);
123
124 value = tmp;
125 break;
126 }
127 case 64:
128 {
129 int64_t tmp;
130 tmp = *(int64_t *) ptr;
131 if (byte_order_reversed)
132 __swab64s(&tmp);
133
134 value = tmp;
135 break;
136 }
137 default:
138 WARN_ON(1);
139 }
140
141 return value;
142 }
143
144 static
145 uint64_t capture_sequence_element_unsigned(uint8_t *ptr,
146 const struct lttng_integer_type *type)
147 {
148 uint64_t value = 0;
149 unsigned int size = type->size;
150 bool byte_order_reversed = type->reverse_byte_order;
151
152 switch (size) {
153 case 8:
154 value = *ptr;
155 break;
156 case 16:
157 {
158 uint16_t tmp;
159 tmp = *(uint16_t *) ptr;
160 if (byte_order_reversed)
161 __swab16s(&tmp);
162
163 value = tmp;
164 break;
165 }
166 case 32:
167 {
168 uint32_t tmp;
169 tmp = *(uint32_t *) ptr;
170 if (byte_order_reversed)
171 __swab32s(&tmp);
172
173 value = tmp;
174 break;
175 }
176 case 64:
177 {
178 uint64_t tmp;
179 tmp = *(uint64_t *) ptr;
180 if (byte_order_reversed)
181 __swab64s(&tmp);
182
183 value = tmp;
184 break;
185 }
186 default:
187 WARN_ON(1);
188 }
189
190 return value;
191 }
192
193 int capture_sequence(struct lttng_msgpack_writer *writer,
194 struct lttng_interpreter_output *output)
195 {
196 const struct lttng_integer_type *integer_type = NULL;
197 const struct lttng_type *nested_type;
198 uint8_t *ptr;
199 bool signedness;
200 int ret, i;
201
202 ret = lttng_msgpack_begin_array(writer, output->u.sequence.nr_elem);
203 if (ret) {
204 WARN_ON_ONCE(1);
205 goto end;
206 }
207
208 ptr = (uint8_t *) output->u.sequence.ptr;
209 nested_type = output->u.sequence.nested_type;
210 switch (nested_type->atype) {
211 case atype_integer:
212 integer_type = &nested_type->u.integer;
213 break;
214 case atype_enum_nestable:
215 /* Treat enumeration as an integer. */
216 integer_type = &nested_type->u.enum_nestable.container_type->u.integer;
217 break;
218 default:
219 /* Capture of array of non-integer are not supported. */
220 WARN_ON(1);
221 }
222 signedness = integer_type->signedness;
223 for (i = 0; i < output->u.sequence.nr_elem; i++) {
224 if (signedness) {
225 ret = lttng_msgpack_write_signed_integer(writer,
226 capture_sequence_element_signed(ptr, integer_type));
227 if (ret) {
228 WARN_ON_ONCE(1);
229 goto end;
230 }
231 } else {
232 ret = lttng_msgpack_write_unsigned_integer(writer,
233 capture_sequence_element_unsigned(ptr, integer_type));
234 if (ret) {
235 WARN_ON_ONCE(1);
236 goto end;
237 }
238 }
239
240 /*
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
245 * away.
246 */
247 WARN_ON(integer_type->alignment > integer_type->size);
248
249 /* Size is in number of bits. */
250 ptr += (integer_type->size / CHAR_BIT) ;
251 }
252
253 ret = lttng_msgpack_end_array(writer);
254 if (ret)
255 WARN_ON_ONCE(1);
256 end:
257 return ret;
258 }
259
260 static
261 int notification_append_capture(
262 struct lttng_event_notifier_notification *notif,
263 struct lttng_interpreter_output *output)
264 {
265 struct lttng_msgpack_writer *writer = &notif->writer;
266 int ret = 0;
267
268 switch (output->type) {
269 case LTTNG_INTERPRETER_TYPE_S64:
270 ret = lttng_msgpack_write_signed_integer(writer, output->u.s);
271 if (ret) {
272 WARN_ON_ONCE(1);
273 goto end;
274 }
275 break;
276 case LTTNG_INTERPRETER_TYPE_U64:
277 ret = lttng_msgpack_write_unsigned_integer(writer, output->u.u);
278 if (ret) {
279 WARN_ON_ONCE(1);
280 goto end;
281 }
282 break;
283 case LTTNG_INTERPRETER_TYPE_STRING:
284 ret = lttng_msgpack_write_str(writer, output->u.str.str);
285 if (ret) {
286 WARN_ON_ONCE(1);
287 goto end;
288 }
289 break;
290 case LTTNG_INTERPRETER_TYPE_SEQUENCE:
291 ret = capture_sequence(writer, output);
292 if (ret) {
293 WARN_ON_ONCE(1);
294 goto end;
295 }
296 break;
297 case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
298 case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
299 ret = capture_enum(writer, output);
300 if (ret) {
301 WARN_ON_ONCE(1);
302 goto end;
303 }
304 break;
305 default:
306 ret = -1;
307 WARN_ON(1);
308 }
309 end:
310 return ret;
311 }
312
313 static
314 int notification_append_empty_capture(
315 struct lttng_event_notifier_notification *notif)
316 {
317 int ret = lttng_msgpack_write_nil(&notif->writer);
318 if (ret)
319 WARN_ON_ONCE(1);
320
321 return ret;
322 }
323
324 static
325 int notification_init(struct lttng_event_notifier_notification *notif,
326 struct lttng_event_notifier *event_notifier)
327 {
328 struct lttng_msgpack_writer *writer = &notif->writer;
329 int ret = 0;
330
331 notif->has_captures = false;
332
333 if (event_notifier->num_captures > 0) {
334 lttng_msgpack_writer_init(writer, notif->capture_buf,
335 CAPTURE_BUFFER_SIZE);
336
337 ret = lttng_msgpack_begin_array(writer, event_notifier->num_captures);
338 if (ret) {
339 WARN_ON_ONCE(1);
340 goto end;
341 }
342
343 notif->has_captures = true;
344 }
345
346 end:
347 return ret;
348 }
349
350 static
351 void notification_send(struct lttng_event_notifier_notification *notif,
352 struct lttng_event_notifier *event_notifier)
353 {
354 struct lttng_event_notifier_group *event_notifier_group = event_notifier->group;
355 struct lib_ring_buffer_ctx ctx;
356 struct lttng_kernel_event_notifier_notification kernel_notif;
357 size_t capture_buffer_content_len, reserve_size;
358 int ret;
359
360 reserve_size = sizeof(kernel_notif);
361 kernel_notif.token = event_notifier->user_token;
362
363 if (notif->has_captures) {
364 capture_buffer_content_len = notif->writer.write_pos - notif->writer.buffer;
365 } else {
366 capture_buffer_content_len = 0;
367 }
368
369 WARN_ON_ONCE(capture_buffer_content_len > CAPTURE_BUFFER_SIZE);
370
371 reserve_size += capture_buffer_content_len;
372 kernel_notif.capture_buf_size = capture_buffer_content_len;
373
374 lib_ring_buffer_ctx_init(&ctx, event_notifier_group->chan, NULL, reserve_size,
375 lttng_alignof(kernel_notif), -1);
376 ret = event_notifier_group->ops->event_reserve(&ctx, 0);
377 if (ret < 0) {
378 //TODO: error handling with counter maps
379 //silently drop for now.
380 WARN_ON_ONCE(1);
381 return;
382 }
383
384 lib_ring_buffer_align_ctx(&ctx, lttng_alignof(kernel_notif));
385
386 /* Write the notif structure. */
387 event_notifier_group->ops->event_write(&ctx, &kernel_notif,
388 sizeof(kernel_notif));
389
390 /*
391 * Write the capture buffer. No need to realigned as the below is a raw
392 * char* buffer.
393 */
394 event_notifier_group->ops->event_write(&ctx, &notif->capture_buf,
395 capture_buffer_content_len);
396
397 event_notifier_group->ops->event_commit(&ctx);
398 irq_work_queue(&event_notifier_group->wakeup_pending);
399 }
400
401 void lttng_event_notifier_notification_send(struct lttng_event_notifier *event_notifier,
402 struct lttng_probe_ctx *lttng_probe_ctx,
403 const char *stack_data)
404 {
405 struct lttng_event_notifier_notification notif = { 0 };
406 int ret;
407
408 if (unlikely(!READ_ONCE(event_notifier->enabled)))
409 return;
410
411 ret = notification_init(&notif, event_notifier);
412 if (ret) {
413 WARN_ON_ONCE(1);
414 goto end;
415 }
416
417 if (unlikely(!list_empty(&event_notifier->capture_bytecode_runtime_head))) {
418 struct lttng_bytecode_runtime *capture_bc_runtime;
419
420 /*
421 * Iterate over all the capture bytecodes. If the interpreter
422 * functions returns successfully, append the value of the
423 * `output` parameter to the capture buffer. If the interpreter
424 * fails, append an empty capture to the buffer.
425 */
426 list_for_each_entry(capture_bc_runtime,
427 &event_notifier->capture_bytecode_runtime_head, node) {
428 struct lttng_interpreter_output output;
429
430 if (capture_bc_runtime->interpreter_funcs.capture(capture_bc_runtime,
431 lttng_probe_ctx, stack_data, &output) & LTTNG_INTERPRETER_RECORD_FLAG)
432 ret = notification_append_capture(&notif, &output);
433 else
434 ret = notification_append_empty_capture(&notif);
435
436 if (ret)
437 printk(KERN_WARNING "Error appending capture to notification");
438 }
439 }
440
441 /*
442 * Send the notification (including the capture buffer) to the
443 * sessiond.
444 */
445 notification_send(&notif, event_notifier);
446 end:
447 return;
448 }
This page took 0.037845 seconds and 3 git commands to generate.