forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/kernel/trace/trace_syscalls.c
....@@ -7,6 +7,7 @@
77 #include <linux/module.h> /* for MODULE_NAME_LEN via KSYM_SYMBOL_LEN */
88 #include <linux/ftrace.h>
99 #include <linux/perf_event.h>
10
+#include <linux/xarray.h>
1011 #include <asm/syscall.h>
1112
1213 #include "trace_output.h"
....@@ -30,6 +31,7 @@
3031 extern struct syscall_metadata *__start_syscalls_metadata[];
3132 extern struct syscall_metadata *__stop_syscalls_metadata[];
3233
34
+static DEFINE_XARRAY(syscalls_metadata_sparse);
3335 static struct syscall_metadata **syscalls_metadata;
3436
3537 #ifndef ARCH_HAS_SYSCALL_MATCH_SYM_NAME
....@@ -101,6 +103,9 @@
101103
102104 static struct syscall_metadata *syscall_nr_to_meta(int nr)
103105 {
106
+ if (IS_ENABLED(CONFIG_HAVE_SPARSE_SYSCALL_NR))
107
+ return xa_load(&syscalls_metadata_sparse, (unsigned long)nr);
108
+
104109 if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
105110 return NULL;
106111
....@@ -198,11 +203,10 @@
198203
199204 extern char *__bad_type_size(void);
200205
201
-#define SYSCALL_FIELD(type, field, name) \
202
- sizeof(type) != sizeof(trace.field) ? \
203
- __bad_type_size() : \
204
- #type, #name, offsetof(typeof(trace), field), \
205
- sizeof(trace.field), is_signed_type(type)
206
+#define SYSCALL_FIELD(_type, _name) { \
207
+ .type = #_type, .name = #_name, \
208
+ .size = sizeof(_type), .align = __alignof__(_type), \
209
+ .is_signed = is_signed_type(_type), .filter_type = FILTER_OTHER }
206210
207211 static int __init
208212 __set_enter_print_fmt(struct syscall_metadata *entry, char *buf, int len)
....@@ -269,38 +273,19 @@
269273 {
270274 struct syscall_trace_enter trace;
271275 struct syscall_metadata *meta = call->data;
272
- int ret;
273
- int i;
274276 int offset = offsetof(typeof(trace), args);
275
-
276
- ret = trace_define_field(call, SYSCALL_FIELD(int, nr, __syscall_nr),
277
- FILTER_OTHER);
278
- if (ret)
279
- return ret;
277
+ int ret = 0;
278
+ int i;
280279
281280 for (i = 0; i < meta->nb_args; i++) {
282281 ret = trace_define_field(call, meta->types[i],
283282 meta->args[i], offset,
284283 sizeof(unsigned long), 0,
285284 FILTER_OTHER);
285
+ if (ret)
286
+ break;
286287 offset += sizeof(unsigned long);
287288 }
288
-
289
- return ret;
290
-}
291
-
292
-static int __init syscall_exit_define_fields(struct trace_event_call *call)
293
-{
294
- struct syscall_trace_exit trace;
295
- int ret;
296
-
297
- ret = trace_define_field(call, SYSCALL_FIELD(int, nr, __syscall_nr),
298
- FILTER_OTHER);
299
- if (ret)
300
- return ret;
301
-
302
- ret = trace_define_field(call, SYSCALL_FIELD(long, ret, ret),
303
- FILTER_OTHER);
304289
305290 return ret;
306291 }
....@@ -312,9 +297,9 @@
312297 struct syscall_trace_enter *entry;
313298 struct syscall_metadata *sys_data;
314299 struct ring_buffer_event *event;
315
- struct ring_buffer *buffer;
316
- unsigned long irq_flags;
317
- int pc;
300
+ struct trace_buffer *buffer;
301
+ unsigned int trace_ctx;
302
+ unsigned long args[6];
318303 int syscall_nr;
319304 int size;
320305
....@@ -336,21 +321,21 @@
336321
337322 size = sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args;
338323
339
- local_save_flags(irq_flags);
340
- pc = preempt_count();
324
+ trace_ctx = tracing_gen_ctx();
341325
342
- buffer = tr->trace_buffer.buffer;
326
+ buffer = tr->array_buffer.buffer;
343327 event = trace_buffer_lock_reserve(buffer,
344
- sys_data->enter_event->event.type, size, irq_flags, pc);
328
+ sys_data->enter_event->event.type, size, trace_ctx);
345329 if (!event)
346330 return;
347331
348332 entry = ring_buffer_event_data(event);
349333 entry->nr = syscall_nr;
350
- syscall_get_arguments(current, regs, 0, sys_data->nb_args, entry->args);
334
+ syscall_get_arguments(current, regs, args);
335
+ memcpy(entry->args, args, sizeof(unsigned long) * sys_data->nb_args);
351336
352337 event_trigger_unlock_commit(trace_file, buffer, event, entry,
353
- irq_flags, pc);
338
+ trace_ctx);
354339 }
355340
356341 static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret)
....@@ -360,9 +345,8 @@
360345 struct syscall_trace_exit *entry;
361346 struct syscall_metadata *sys_data;
362347 struct ring_buffer_event *event;
363
- struct ring_buffer *buffer;
364
- unsigned long irq_flags;
365
- int pc;
348
+ struct trace_buffer *buffer;
349
+ unsigned int trace_ctx;
366350 int syscall_nr;
367351
368352 syscall_nr = trace_get_syscall_nr(current, regs);
....@@ -381,13 +365,12 @@
381365 if (!sys_data)
382366 return;
383367
384
- local_save_flags(irq_flags);
385
- pc = preempt_count();
368
+ trace_ctx = tracing_gen_ctx();
386369
387
- buffer = tr->trace_buffer.buffer;
370
+ buffer = tr->array_buffer.buffer;
388371 event = trace_buffer_lock_reserve(buffer,
389372 sys_data->exit_event->event.type, sizeof(*entry),
390
- irq_flags, pc);
373
+ trace_ctx);
391374 if (!event)
392375 return;
393376
....@@ -396,7 +379,7 @@
396379 entry->ret = syscall_get_return_value(current, regs);
397380
398381 event_trigger_unlock_commit(trace_file, buffer, event, entry,
399
- irq_flags, pc);
382
+ trace_ctx);
400383 }
401384
402385 static int reg_event_syscall_enter(struct trace_event_file *file,
....@@ -500,6 +483,13 @@
500483 return id;
501484 }
502485
486
+static struct trace_event_fields __refdata syscall_enter_fields_array[] = {
487
+ SYSCALL_FIELD(int, __syscall_nr),
488
+ { .type = TRACE_FUNCTION_TYPE,
489
+ .define_fields = syscall_enter_define_fields },
490
+ {}
491
+};
492
+
503493 struct trace_event_functions enter_syscall_print_funcs = {
504494 .trace = print_syscall_enter,
505495 };
....@@ -511,7 +501,7 @@
511501 struct trace_event_class __refdata event_class_syscall_enter = {
512502 .system = "syscalls",
513503 .reg = syscall_enter_register,
514
- .define_fields = syscall_enter_define_fields,
504
+ .fields_array = syscall_enter_fields_array,
515505 .get_fields = syscall_get_enter_fields,
516506 .raw_init = init_syscall_trace,
517507 };
....@@ -519,7 +509,11 @@
519509 struct trace_event_class __refdata event_class_syscall_exit = {
520510 .system = "syscalls",
521511 .reg = syscall_exit_register,
522
- .define_fields = syscall_exit_define_fields,
512
+ .fields_array = (struct trace_event_fields[]){
513
+ SYSCALL_FIELD(int, __syscall_nr),
514
+ SYSCALL_FIELD(long, ret),
515
+ {}
516
+ },
523517 .fields = LIST_HEAD_INIT(event_class_syscall_exit.fields),
524518 .raw_init = init_syscall_trace,
525519 };
....@@ -534,12 +528,16 @@
534528 struct syscall_metadata *meta;
535529 unsigned long addr;
536530 int i;
531
+ void *ret;
537532
538
- syscalls_metadata = kcalloc(NR_syscalls, sizeof(*syscalls_metadata),
539
- GFP_KERNEL);
540
- if (!syscalls_metadata) {
541
- WARN_ON(1);
542
- return;
533
+ if (!IS_ENABLED(CONFIG_HAVE_SPARSE_SYSCALL_NR)) {
534
+ syscalls_metadata = kcalloc(NR_syscalls,
535
+ sizeof(*syscalls_metadata),
536
+ GFP_KERNEL);
537
+ if (!syscalls_metadata) {
538
+ WARN_ON(1);
539
+ return;
540
+ }
543541 }
544542
545543 for (i = 0; i < NR_syscalls; i++) {
....@@ -549,7 +547,16 @@
549547 continue;
550548
551549 meta->syscall_nr = i;
552
- syscalls_metadata[i] = meta;
550
+
551
+ if (!IS_ENABLED(CONFIG_HAVE_SPARSE_SYSCALL_NR)) {
552
+ syscalls_metadata[i] = meta;
553
+ } else {
554
+ ret = xa_store(&syscalls_metadata_sparse, i, meta,
555
+ GFP_KERNEL);
556
+ WARN(xa_is_err(ret),
557
+ "Syscall memory allocation failed\n");
558
+ }
559
+
553560 }
554561 }
555562
....@@ -583,6 +590,7 @@
583590 struct syscall_metadata *sys_data;
584591 struct syscall_trace_enter *rec;
585592 struct hlist_head *head;
593
+ unsigned long args[6];
586594 bool valid_prog_array;
587595 int syscall_nr;
588596 int rctx;
....@@ -613,8 +621,8 @@
613621 return;
614622
615623 rec->nr = syscall_nr;
616
- syscall_get_arguments(current, regs, 0, sys_data->nb_args,
617
- (unsigned long *)&rec->args);
624
+ syscall_get_arguments(current, regs, args);
625
+ memcpy(&rec->args, args, sizeof(unsigned long) * sys_data->nb_args);
618626
619627 if ((valid_prog_array &&
620628 !perf_call_bpf_enter(sys_data->enter_event, regs, sys_data, rec)) ||