History

ring-buffer: Flush and stop persistent ring buffer on panic

On real hardware, panic and machine reboot may not flush hardware cache to memory. This means the persistent ring buffer, which relies on a coherent state of memory, may not have its events written to the buffer and they may be lost. Moreover, there may be inconsistency with the counters which are used for validation of the integrity of the persistent ring buffer which may cause all data to be discarded. To avoid this issue, stop recording of the ring buffer on panic and flush the cache of the ring buffer's memory.

Masami Hiramatsu (Google) committed 6 months ago

Commit a494d3c1 parent a254b6d23 files · +65 −0Browse files

Unified · Split

23 files
  1. arch/alpha/include/asm/Kbuild +1 −0
  2. arch/arc/include/asm/Kbuild +1 −0
  3. arch/arm/include/asm/Kbuild +1 −0
  4. arch/arm64/include/asm/ring_buffer.h +10 −0
  5. arch/csky/include/asm/Kbuild +1 −0
  6. arch/hexagon/include/asm/Kbuild +1 −0
  7. arch/loongarch/include/asm/Kbuild +1 −0
  8. arch/m68k/include/asm/Kbuild +1 −0
  9. arch/microblaze/include/asm/Kbuild +1 −0
  10. arch/mips/include/asm/Kbuild +1 −0
  11. arch/nios2/include/asm/Kbuild +1 −0
  12. arch/openrisc/include/asm/Kbuild +1 −0
  13. arch/parisc/include/asm/Kbuild +1 −0
  14. arch/powerpc/include/asm/Kbuild +1 −0
  15. arch/riscv/include/asm/Kbuild +1 −0
  16. arch/s390/include/asm/Kbuild +1 −0
  17. arch/sh/include/asm/Kbuild +1 −0
  18. arch/sparc/include/asm/Kbuild +1 −0
  19. arch/um/include/asm/Kbuild +1 −0
  20. arch/x86/include/asm/Kbuild +1 −0
  21. arch/xtensa/include/asm/Kbuild +1 −0
  22. include/asm-generic/ring_buffer.h +13 −0
  23. kernel/trace/ring_buffer.c +22 −0
arch/alpha/include/asm/Kbuild+1−0
@@ -5,4 +5,5 @@ generic-y += agp.h · 4 unmodified lines
55 generic-y += asm-offsets.h
66 generic-y += kvm_para.h
77 generic-y += mcs_spinlock.h
8+generic-y += ring_buffer.h
89 generic-y += text-patching.h
arch/arc/include/asm/Kbuild+1−0
@@ -5,5 +5,6 @@ generic-y += extable.h · 4 unmodified lines
55 generic-y += kvm_para.h
66 generic-y += mcs_spinlock.h
77 generic-y += parport.h
8+generic-y += ring_buffer.h
89 generic-y += user.h
910 generic-y += text-patching.h
arch/arm/include/asm/Kbuild+1−0
@@ -3,6 +3,7 @@ generic-y += early_ioremap.h · 2 unmodified lines
33 generic-y += extable.h
44 generic-y += flat.h
55 generic-y += parport.h
6+generic-y += ring_buffer.h
67
78 generated-y += mach-types.h
89 generated-y += unistd-nr.h
arch/arm64/include/asm/ring_buffer.h+10−0
@@ -0,0 +1,10 @@
1+/* SPDX-License-Identifier: GPL-2.0-only */
2+#ifndef _ASM_ARM64_RING_BUFFER_H
3+#define _ASM_ARM64_RING_BUFFER_H
4+
5+#include <asm/cacheflush.h>
6+
7+/* Flush D-cache on persistent ring buffer */
8+#define arch_ring_buffer_flush_range(start, end) dcache_clean_pop(start, end)
9+
10+#endif /* _ASM_ARM64_RING_BUFFER_H */
arch/csky/include/asm/Kbuild+1−0
@@ -9,6 +9,7 @@ generic-y += qrwlock.h · 8 unmodified lines
99 generic-y += qrwlock_types.h
1010 generic-y += qspinlock.h
1111 generic-y += parport.h
12+generic-y += ring_buffer.h
1213 generic-y += user.h
1314 generic-y += vmlinux.lds.h
1415 generic-y += text-patching.h
arch/hexagon/include/asm/Kbuild+1−0
@@ -5,4 +5,5 @@ generic-y += extable.h · 4 unmodified lines
55 generic-y += iomap.h
66 generic-y += kvm_para.h
77 generic-y += mcs_spinlock.h
8+generic-y += ring_buffer.h
89 generic-y += text-patching.h
arch/loongarch/include/asm/Kbuild+1−0
@@ -10,5 +10,6 @@ generic-y += qrwlock.h · 9 unmodified lines
1010 generic-y += user.h
1111 generic-y += ioctl.h
1212 generic-y += mmzone.h
13+generic-y += ring_buffer.h
1314 generic-y += statfs.h
1415 generic-y += text-patching.h
arch/m68k/include/asm/Kbuild+1−0
@@ -3,5 +3,6 @@ generated-y += syscall_table.h · 2 unmodified lines
33 generic-y += extable.h
44 generic-y += kvm_para.h
55 generic-y += mcs_spinlock.h
6+generic-y += ring_buffer.h
67 generic-y += spinlock.h
78 generic-y += text-patching.h
arch/microblaze/include/asm/Kbuild+1−0
@@ -5,6 +5,7 @@ generic-y += extable.h · 4 unmodified lines
55 generic-y += kvm_para.h
66 generic-y += mcs_spinlock.h
77 generic-y += parport.h
8+generic-y += ring_buffer.h
89 generic-y += syscalls.h
910 generic-y += tlb.h
1011 generic-y += user.h
arch/mips/include/asm/Kbuild+1−0
@@ -12,5 +12,6 @@ generic-y += mcs_spinlock.h · 11 unmodified lines
1212 generic-y += parport.h
1313 generic-y += qrwlock.h
1414 generic-y += qspinlock.h
15+generic-y += ring_buffer.h
1516 generic-y += user.h
1617 generic-y += text-patching.h
arch/nios2/include/asm/Kbuild+1−0
@@ -5,6 +5,7 @@ generic-y += cmpxchg.h · 4 unmodified lines
55 generic-y += extable.h
66 generic-y += kvm_para.h
77 generic-y += mcs_spinlock.h
8+generic-y += ring_buffer.h
89 generic-y += spinlock.h
910 generic-y += user.h
1011 generic-y += text-patching.h
arch/openrisc/include/asm/Kbuild+1−0
@@ -8,4 +8,5 @@ generic-y += spinlock_types.h · 7 unmodified lines
88 generic-y += spinlock.h
99 generic-y += qrwlock_types.h
1010 generic-y += qrwlock.h
11+generic-y += ring_buffer.h
1112 generic-y += user.h
arch/parisc/include/asm/Kbuild+1−0
@@ -4,4 +4,5 @@ generated-y += syscall_table_64.h · 3 unmodified lines
44 generic-y += agp.h
55 generic-y += kvm_para.h
66 generic-y += mcs_spinlock.h
7+generic-y += ring_buffer.h
78 generic-y += user.h
arch/powerpc/include/asm/Kbuild+1−0
@@ -5,4 +5,5 @@ generated-y += syscall_table_spu.h · 4 unmodified lines
55 generic-y += agp.h
66 generic-y += mcs_spinlock.h
77 generic-y += qrwlock.h
8+generic-y += ring_buffer.h
89 generic-y += early_ioremap.h
arch/riscv/include/asm/Kbuild+1−0
@@ -14,5 +14,6 @@ generic-y += ticket_spinlock.h · 13 unmodified lines
1414 generic-y += qrwlock.h
1515 generic-y += qrwlock_types.h
1616 generic-y += qspinlock.h
17+generic-y += ring_buffer.h
1718 generic-y += user.h
1819 generic-y += vmlinux.lds.h
arch/s390/include/asm/Kbuild+1−0
@@ -7,3 +7,4 @@ generated-y += unistd_nr.h · 6 unmodified lines
77 generic-y += asm-offsets.h
88 generic-y += mcs_spinlock.h
99 generic-y += mmzone.h
10+generic-y += ring_buffer.h
arch/sh/include/asm/Kbuild+1−0
@@ -3,4 +3,5 @@ generated-y += syscall_table.h · 2 unmodified lines
33 generic-y += kvm_para.h
44 generic-y += mcs_spinlock.h
55 generic-y += parport.h
6+generic-y += ring_buffer.h
67 generic-y += text-patching.h
arch/sparc/include/asm/Kbuild+1−0
@@ -4,4 +4,5 @@ generated-y += syscall_table_64.h · 3 unmodified lines
44 generic-y += agp.h
55 generic-y += kvm_para.h
66 generic-y += mcs_spinlock.h
7+generic-y += ring_buffer.h
78 generic-y += text-patching.h
arch/um/include/asm/Kbuild+1−0
@@ -17,6 +17,7 @@ generic-y += module.lds.h · 16 unmodified lines
1717 generic-y += parport.h
1818 generic-y += percpu.h
1919 generic-y += preempt.h
20+generic-y += ring_buffer.h
2021 generic-y += runtime-const.h
2122 generic-y += softirq_stack.h
2223 generic-y += switch_to.h
arch/x86/include/asm/Kbuild+1−0
@@ -14,3 +14,4 @@ generic-y += early_ioremap.h · 13 unmodified lines
1414 generic-y += fprobe.h
1515 generic-y += mcs_spinlock.h
1616 generic-y += mmzone.h
17+generic-y += ring_buffer.h
arch/xtensa/include/asm/Kbuild+1−0
@@ -6,5 +6,6 @@ generic-y += mcs_spinlock.h · 5 unmodified lines
66 generic-y += parport.h
77 generic-y += qrwlock.h
88 generic-y += qspinlock.h
9+generic-y += ring_buffer.h
910 generic-y += user.h
1011 generic-y += text-patching.h
include/asm-generic/ring_buffer.h+13−0
@@ -0,0 +1,13 @@
1+/* SPDX-License-Identifier: GPL-2.0-only */
2+/*
3+ * Generic arch dependent ring_buffer macros.
4+ */
5+#ifndef __ASM_GENERIC_RING_BUFFER_H__
6+#define __ASM_GENERIC_RING_BUFFER_H__
7+
8+#include <linux/cacheflush.h>
9+
10+/* Flush cache on ring buffer range if needed. Do nothing by default. */
11+#define arch_ring_buffer_flush_range(start, end) do { } while (0)
12+
13+#endif /* __ASM_GENERIC_RING_BUFFER_H__ */
kernel/trace/ring_buffer.c+22−0
@@ -7,6 +7,7 @@ · 6 unmodified lines
77 #include <linux/ring_buffer_types.h>
88 #include <linux/sched/isolation.h>
99 #include <linux/trace_recursion.h>
10+#include <linux/panic_notifier.h>
1011 #include <linux/trace_events.h>
1112 #include <linux/ring_buffer.h>
1213 #include <linux/trace_clock.h>
@@ -31,6 +32,7 @@ · 18 unmodified lines
3132 #include <linux/oom.h>
3233 #include <linux/mm.h>
3334
35+#include <asm/ring_buffer.h>
3436 #include <asm/local64.h>
3537 #include <asm/local.h>
3638 #include <asm/setup.h>
@@ -559,6 +561,7 @@ struct trace_buffer { · 522 unmodified lines
559561
560562 unsigned long range_addr_start;
561563 unsigned long range_addr_end;
564+ struct notifier_block flush_nb;
562565
563566 struct ring_buffer_meta *meta;
564567
@@ -2521,6 +2524,16 @@ static void rb_free_cpu_buffer(struct ring_buffer_per_cpu *cpu_buffer) · 1956 unmodified lines
25212524 kfree(cpu_buffer);
25222525 }
25232526
2527+/* Stop recording on a persistent buffer and flush cache if needed. */
2528+static int rb_flush_buffer_cb(struct notifier_block *nb, unsigned long event, void *data)
2529+{
2530+ struct trace_buffer *buffer = container_of(nb, struct trace_buffer, flush_nb);
2531+
2532+ ring_buffer_record_off(buffer);
2533+ arch_ring_buffer_flush_range(buffer->range_addr_start, buffer->range_addr_end);
2534+ return NOTIFY_DONE;
2535+}
2536+
25242537 static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags,
25252538 int order, unsigned long start,
25262539 unsigned long end,
@@ -2651,6 +2664,12 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags, · 124 unmodified lines
26512664
26522665 mutex_init(&buffer->mutex);
26532666
2667+ /* Persistent ring buffer needs to flush cache before reboot. */
2668+ if (start && end) {
2669+ buffer->flush_nb.notifier_call = rb_flush_buffer_cb;
2670+ atomic_notifier_chain_register(&panic_notifier_list, &buffer->flush_nb);
2671+ }
2672+
26542673 return_ptr(buffer);
26552674
26562675 fail_free_buffers:
@@ -2749,6 +2768,9 @@ ring_buffer_free(struct trace_buffer *buffer) · 92 unmodified lines
27492768 {
27502769 int cpu;
27512770
2771+ if (buffer->range_addr_start && buffer->range_addr_end)
2772+ atomic_notifier_chain_unregister(&panic_notifier_list, &buffer->flush_nb);
2773+
27522774 cpuhp_state_remove_instance(CPUHP_TRACE_RB_PREPARE, &buffer->node);
27532775
27542776 irq_work_sync(&buffer->irq_work.work);