Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'trace-v6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull tracing fixes from Steven Rostedt:

- Fix trace histogram sort function cmp_entries_dup()

The sort function cmp_entries_dup() returns either 1 or 0, and not -1
if parameter "a" is less than "b" by memcmp().

- Fix archs that call trace_hardirqs_off() without RCU watching

Both x86 and arm64 no longer call any tracepoints with RCU not
watching. It was assumed that it was safe to get rid of
trace_*_rcuidle() version of the tracepoint calls. This was needed to
get rid of the SRCU protection and be able to implement features like
faultable traceponits and add rust tracepoints.

Unfortunately, there were a few architectures that still relied on
that logic. There's only one file that has tracepoints that are
called without RCU watching. Add macro logic around the tracepoints
for architectures that do not have CONFIG_ARCH_WANTS_NO_INSTR defined
will check if the code is in the idle path (the only place RCU isn't
watching), and enable RCU around calling the tracepoint, but only do
it if the tracepoint is enabled.

* tag 'trace-v6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
tracing: Fix archs that still call tracepoints without RCU watching
tracing: Fix cmp_entries_dup() to respect sort() comparison rules

+38 -11
+37 -6
kernel/trace/trace_preemptirq.c
··· 10 10 #include <linux/module.h> 11 11 #include <linux/ftrace.h> 12 12 #include <linux/kprobes.h> 13 + #include <linux/hardirq.h> 13 14 #include "trace.h" 14 15 15 16 #define CREATE_TRACE_POINTS 16 17 #include <trace/events/preemptirq.h> 18 + 19 + /* 20 + * Use regular trace points on architectures that implement noinstr 21 + * tooling: these calls will only happen with RCU enabled, which can 22 + * use a regular tracepoint. 23 + * 24 + * On older architectures, RCU may not be watching in idle. In that 25 + * case, wake up RCU to watch while calling the tracepoint. These 26 + * aren't NMI-safe - so exclude NMI contexts: 27 + */ 28 + #ifdef CONFIG_ARCH_WANTS_NO_INSTR 29 + #define trace(point, args) trace_##point(args) 30 + #else 31 + #define trace(point, args) \ 32 + do { \ 33 + if (trace_##point##_enabled()) { \ 34 + bool exit_rcu = false; \ 35 + if (in_nmi()) \ 36 + break; \ 37 + if (!IS_ENABLED(CONFIG_TINY_RCU) && \ 38 + is_idle_task(current)) { \ 39 + ct_irq_enter(); \ 40 + exit_rcu = true; \ 41 + } \ 42 + trace_##point(args); \ 43 + if (exit_rcu) \ 44 + ct_irq_exit(); \ 45 + } \ 46 + } while (0) 47 + #endif 17 48 18 49 #ifdef CONFIG_TRACE_IRQFLAGS 19 50 /* Per-cpu variable to prevent redundant calls when IRQs already off */ ··· 59 28 void trace_hardirqs_on_prepare(void) 60 29 { 61 30 if (this_cpu_read(tracing_irq_cpu)) { 62 - trace_irq_enable(CALLER_ADDR0, CALLER_ADDR1); 31 + trace(irq_enable, TP_ARGS(CALLER_ADDR0, CALLER_ADDR1)); 63 32 tracer_hardirqs_on(CALLER_ADDR0, CALLER_ADDR1); 64 33 this_cpu_write(tracing_irq_cpu, 0); 65 34 } ··· 70 39 void trace_hardirqs_on(void) 71 40 { 72 41 if (this_cpu_read(tracing_irq_cpu)) { 73 - trace_irq_enable(CALLER_ADDR0, CALLER_ADDR1); 42 + trace(irq_enable, TP_ARGS(CALLER_ADDR0, CALLER_ADDR1)); 74 43 tracer_hardirqs_on(CALLER_ADDR0, CALLER_ADDR1); 75 44 this_cpu_write(tracing_irq_cpu, 0); 76 45 } ··· 92 61 if (!this_cpu_read(tracing_irq_cpu)) { 93 62 this_cpu_write(tracing_irq_cpu, 1); 94 63 tracer_hardirqs_off(CALLER_ADDR0, CALLER_ADDR1); 95 - trace_irq_disable(CALLER_ADDR0, CALLER_ADDR1); 64 + trace(irq_disable, TP_ARGS(CALLER_ADDR0, CALLER_ADDR1)); 96 65 } 97 66 98 67 } ··· 106 75 if (!this_cpu_read(tracing_irq_cpu)) { 107 76 this_cpu_write(tracing_irq_cpu, 1); 108 77 tracer_hardirqs_off(CALLER_ADDR0, CALLER_ADDR1); 109 - trace_irq_disable(CALLER_ADDR0, CALLER_ADDR1); 78 + trace(irq_disable, TP_ARGS(CALLER_ADDR0, CALLER_ADDR1)); 110 79 } 111 80 } 112 81 EXPORT_SYMBOL(trace_hardirqs_off); ··· 117 86 118 87 void trace_preempt_on(unsigned long a0, unsigned long a1) 119 88 { 120 - trace_preempt_enable(a0, a1); 89 + trace(preempt_enable, TP_ARGS(a0, a1)); 121 90 tracer_preempt_on(a0, a1); 122 91 } 123 92 124 93 void trace_preempt_off(unsigned long a0, unsigned long a1) 125 94 { 126 - trace_preempt_disable(a0, a1); 95 + trace(preempt_disable, TP_ARGS(a0, a1)); 127 96 tracer_preempt_off(a0, a1); 128 97 } 129 98 #endif
+1 -5
kernel/trace/tracing_map.c
··· 845 845 static int cmp_entries_dup(const void *A, const void *B) 846 846 { 847 847 const struct tracing_map_sort_entry *a, *b; 848 - int ret = 0; 849 848 850 849 a = *(const struct tracing_map_sort_entry **)A; 851 850 b = *(const struct tracing_map_sort_entry **)B; 852 851 853 - if (memcmp(a->key, b->key, a->elt->map->key_size)) 854 - ret = 1; 855 - 856 - return ret; 852 + return memcmp(a->key, b->key, a->elt->map->key_size); 857 853 } 858 854 859 855 static int cmp_entries_sum(const void *A, const void *B)