Skip to content

Commit 0966375

Browse files
committed
tracing/ring-buffer: Clear all memory mapped CPU ring buffers on first recording
The events of a memory mapped ring buffer from the previous boot should not be mixed in with events from the current boot. There's meta data that is used to handle KASLR so that function names can be shown properly. Also, since the timestamps of the previous boot have no meaning to the timestamps of the current boot, having them intermingled in a buffer can also cause confusion because there could possibly be events in the future. When a trace is activated the meta data is reset so that the pointers of are now processed for the new address space. The trace buffers are reset when tracing starts for the first time. The problem here is that the reset only happens on online CPUs. If a CPU is offline, it does not get reset. To demonstrate the issue, a previous boot had tracing enabled in the boot mapped ring buffer on reboot. On the following boot, tracing has not been started yet so the function trace from the previous boot is still visible. # trace-cmd show -B boot_mapped -c 3 | tail <idle>-0 [003] d.h2. 156.462395: __rcu_read_lock <-cpu_emergency_disable_virtualization <idle>-0 [003] d.h2. 156.462396: vmx_emergency_disable_virtualization_cpu <-cpu_emergency_disable_virtualization <idle>-0 [003] d.h2. 156.462396: __rcu_read_unlock <-__sysvec_reboot <idle>-0 [003] d.h2. 156.462397: stop_this_cpu <-__sysvec_reboot <idle>-0 [003] d.h2. 156.462397: set_cpu_online <-stop_this_cpu <idle>-0 [003] d.h2. 156.462397: disable_local_APIC <-stop_this_cpu <idle>-0 [003] d.h2. 156.462398: clear_local_APIC <-disable_local_APIC <idle>-0 [003] d.h2. 156.462574: mcheck_cpu_clear <-stop_this_cpu <idle>-0 [003] d.h2. 156.462575: mce_intel_feature_clear <-stop_this_cpu <idle>-0 [003] d.h2. 156.462575: lmce_supported <-mce_intel_feature_clear Now, if CPU 3 is taken offline, and tracing is started on the memory mapped ring buffer, the events from the previous boot in the CPU 3 ring buffer is not reset. Now those events are using the meta data from the current boot and produces just hex values. # echo 0 > /sys/devices/system/cpu/cpu3/online # trace-cmd start -B boot_mapped -p function # trace-cmd show -B boot_mapped -c 3 | tail <idle>-0 [003] d.h2. 156.462395: 0xffffffff9a1e3194 <-0xffffffff9a0f655e <idle>-0 [003] d.h2. 156.462396: 0xffffffff9a0a1d24 <-0xffffffff9a0f656f <idle>-0 [003] d.h2. 156.462396: 0xffffffff9a1e6bc4 <-0xffffffff9a0f7323 <idle>-0 [003] d.h2. 156.462397: 0xffffffff9a0d12b4 <-0xffffffff9a0f732a <idle>-0 [003] d.h2. 156.462397: 0xffffffff9a1458d4 <-0xffffffff9a0d12e2 <idle>-0 [003] d.h2. 156.462397: 0xffffffff9a0faed4 <-0xffffffff9a0d12e7 <idle>-0 [003] d.h2. 156.462398: 0xffffffff9a0faaf4 <-0xffffffff9a0faef2 <idle>-0 [003] d.h2. 156.462574: 0xffffffff9a0e3444 <-0xffffffff9a0d12ef <idle>-0 [003] d.h2. 156.462575: 0xffffffff9a0e4964 <-0xffffffff9a0d12ef <idle>-0 [003] d.h2. 156.462575: 0xffffffff9a0e3fb0 <-0xffffffff9a0e496f Reset all CPUs when starting a boot mapped ring buffer for the first time, and not just the online CPUs. Fixes: 7a1d1e4 ("tracing/ring-buffer: Add last_boot_info file to boot instance") Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent 580bb35 commit 0966375

File tree

1 file changed

+26
-2
lines changed

1 file changed

+26
-2
lines changed

kernel/trace/trace.c

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2386,6 +2386,25 @@ void tracing_reset_online_cpus(struct array_buffer *buf)
23862386
ring_buffer_record_enable(buffer);
23872387
}
23882388

2389+
static void tracing_reset_all_cpus(struct array_buffer *buf)
2390+
{
2391+
struct trace_buffer *buffer = buf->buffer;
2392+
2393+
if (!buffer)
2394+
return;
2395+
2396+
ring_buffer_record_disable(buffer);
2397+
2398+
/* Make sure all commits have finished */
2399+
synchronize_rcu();
2400+
2401+
buf->time_start = buffer_ftrace_now(buf, buf->cpu);
2402+
2403+
ring_buffer_reset(buffer);
2404+
2405+
ring_buffer_record_enable(buffer);
2406+
}
2407+
23892408
/* Must have trace_types_lock held */
23902409
void tracing_reset_all_online_cpus_unlocked(void)
23912410
{
@@ -6141,8 +6160,13 @@ static void update_last_data(struct trace_array *tr)
61416160
if (!tr->text_delta && !tr->data_delta)
61426161
return;
61436162

6144-
/* Clear old data */
6145-
tracing_reset_online_cpus(&tr->array_buffer);
6163+
/*
6164+
* Need to clear all CPU buffers as there cannot be events
6165+
* from the previous boot mixed with events with this boot
6166+
* as that will cause a confusing trace. Need to clear all
6167+
* CPU buffers, even for those that may currently be offline.
6168+
*/
6169+
tracing_reset_all_cpus(&tr->array_buffer);
61466170

61476171
/* Using current data now */
61486172
tr->text_delta = 0;

0 commit comments

Comments
 (0)