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
5generic-y += asm-offsets.h5generic-y += asm-offsets.h
6generic-y += kvm_para.h6generic-y += kvm_para.h
7generic-y += mcs_spinlock.h7generic-y += mcs_spinlock.h
8generic-y += ring_buffer.h
8generic-y += text-patching.h9generic-y += text-patching.h
arch/arc/include/asm/Kbuild+1−0
@@ -5,5 +5,6 @@ generic-y += extable.h · 4 unmodified lines
5generic-y += kvm_para.h5generic-y += kvm_para.h
6generic-y += mcs_spinlock.h6generic-y += mcs_spinlock.h
7generic-y += parport.h7generic-y += parport.h
8generic-y += ring_buffer.h
8generic-y += user.h9generic-y += user.h
9generic-y += text-patching.h10generic-y += text-patching.h
arch/arm/include/asm/Kbuild+1−0
@@ -3,6 +3,7 @@ generic-y += early_ioremap.h · 2 unmodified lines
3generic-y += extable.h3generic-y += extable.h
4generic-y += flat.h4generic-y += flat.h
5generic-y += parport.h5generic-y += parport.h
6generic-y += ring_buffer.h
6 7
7generated-y += mach-types.h8generated-y += mach-types.h
8generated-y += unistd-nr.h9generated-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
9generic-y += qrwlock_types.h9generic-y += qrwlock_types.h
10generic-y += qspinlock.h10generic-y += qspinlock.h
11generic-y += parport.h11generic-y += parport.h
12generic-y += ring_buffer.h
12generic-y += user.h13generic-y += user.h
13generic-y += vmlinux.lds.h14generic-y += vmlinux.lds.h
14generic-y += text-patching.h15generic-y += text-patching.h
arch/hexagon/include/asm/Kbuild+1−0
@@ -5,4 +5,5 @@ generic-y += extable.h · 4 unmodified lines
5generic-y += iomap.h5generic-y += iomap.h
6generic-y += kvm_para.h6generic-y += kvm_para.h
7generic-y += mcs_spinlock.h7generic-y += mcs_spinlock.h
8generic-y += ring_buffer.h
8generic-y += text-patching.h9generic-y += text-patching.h
arch/loongarch/include/asm/Kbuild+1−0
@@ -10,5 +10,6 @@ generic-y += qrwlock.h · 9 unmodified lines
10generic-y += user.h10generic-y += user.h
11generic-y += ioctl.h11generic-y += ioctl.h
12generic-y += mmzone.h12generic-y += mmzone.h
13generic-y += ring_buffer.h
13generic-y += statfs.h14generic-y += statfs.h
14generic-y += text-patching.h15generic-y += text-patching.h
arch/m68k/include/asm/Kbuild+1−0
@@ -3,5 +3,6 @@ generated-y += syscall_table.h · 2 unmodified lines
3generic-y += extable.h3generic-y += extable.h
4generic-y += kvm_para.h4generic-y += kvm_para.h
5generic-y += mcs_spinlock.h5generic-y += mcs_spinlock.h
6generic-y += ring_buffer.h
6generic-y += spinlock.h7generic-y += spinlock.h
7generic-y += text-patching.h8generic-y += text-patching.h
arch/microblaze/include/asm/Kbuild+1−0
@@ -5,6 +5,7 @@ generic-y += extable.h · 4 unmodified lines
5generic-y += kvm_para.h5generic-y += kvm_para.h
6generic-y += mcs_spinlock.h6generic-y += mcs_spinlock.h
7generic-y += parport.h7generic-y += parport.h
8generic-y += ring_buffer.h
8generic-y += syscalls.h9generic-y += syscalls.h
9generic-y += tlb.h10generic-y += tlb.h
10generic-y += user.h11generic-y += user.h
arch/mips/include/asm/Kbuild+1−0
@@ -12,5 +12,6 @@ generic-y += mcs_spinlock.h · 11 unmodified lines
12generic-y += parport.h12generic-y += parport.h
13generic-y += qrwlock.h13generic-y += qrwlock.h
14generic-y += qspinlock.h14generic-y += qspinlock.h
15generic-y += ring_buffer.h
15generic-y += user.h16generic-y += user.h
16generic-y += text-patching.h17generic-y += text-patching.h
arch/nios2/include/asm/Kbuild+1−0
@@ -5,6 +5,7 @@ generic-y += cmpxchg.h · 4 unmodified lines
5generic-y += extable.h5generic-y += extable.h
6generic-y += kvm_para.h6generic-y += kvm_para.h
7generic-y += mcs_spinlock.h7generic-y += mcs_spinlock.h
8generic-y += ring_buffer.h
8generic-y += spinlock.h9generic-y += spinlock.h
9generic-y += user.h10generic-y += user.h
10generic-y += text-patching.h11generic-y += text-patching.h
arch/openrisc/include/asm/Kbuild+1−0
@@ -8,4 +8,5 @@ generic-y += spinlock_types.h · 7 unmodified lines
8generic-y += spinlock.h8generic-y += spinlock.h
9generic-y += qrwlock_types.h9generic-y += qrwlock_types.h
10generic-y += qrwlock.h10generic-y += qrwlock.h
11generic-y += ring_buffer.h
11generic-y += user.h12generic-y += user.h
arch/parisc/include/asm/Kbuild+1−0
@@ -4,4 +4,5 @@ generated-y += syscall_table_64.h · 3 unmodified lines
4generic-y += agp.h4generic-y += agp.h
5generic-y += kvm_para.h5generic-y += kvm_para.h
6generic-y += mcs_spinlock.h6generic-y += mcs_spinlock.h
7generic-y += ring_buffer.h
7generic-y += user.h8generic-y += user.h
arch/powerpc/include/asm/Kbuild+1−0
@@ -5,4 +5,5 @@ generated-y += syscall_table_spu.h · 4 unmodified lines
5generic-y += agp.h5generic-y += agp.h
6generic-y += mcs_spinlock.h6generic-y += mcs_spinlock.h
7generic-y += qrwlock.h7generic-y += qrwlock.h
8generic-y += ring_buffer.h
8generic-y += early_ioremap.h9generic-y += early_ioremap.h
arch/riscv/include/asm/Kbuild+1−0
@@ -14,5 +14,6 @@ generic-y += ticket_spinlock.h · 13 unmodified lines
14generic-y += qrwlock.h14generic-y += qrwlock.h
15generic-y += qrwlock_types.h15generic-y += qrwlock_types.h
16generic-y += qspinlock.h16generic-y += qspinlock.h
17generic-y += ring_buffer.h
17generic-y += user.h18generic-y += user.h
18generic-y += vmlinux.lds.h19generic-y += vmlinux.lds.h
arch/s390/include/asm/Kbuild+1−0
@@ -7,3 +7,4 @@ generated-y += unistd_nr.h · 6 unmodified lines
7generic-y += asm-offsets.h7generic-y += asm-offsets.h
8generic-y += mcs_spinlock.h8generic-y += mcs_spinlock.h
9generic-y += mmzone.h9generic-y += mmzone.h
10generic-y += ring_buffer.h
arch/sh/include/asm/Kbuild+1−0
@@ -3,4 +3,5 @@ generated-y += syscall_table.h · 2 unmodified lines
3generic-y += kvm_para.h3generic-y += kvm_para.h
4generic-y += mcs_spinlock.h4generic-y += mcs_spinlock.h
5generic-y += parport.h5generic-y += parport.h
6generic-y += ring_buffer.h
6generic-y += text-patching.h7generic-y += text-patching.h
arch/sparc/include/asm/Kbuild+1−0
@@ -4,4 +4,5 @@ generated-y += syscall_table_64.h · 3 unmodified lines
4generic-y += agp.h4generic-y += agp.h
5generic-y += kvm_para.h5generic-y += kvm_para.h
6generic-y += mcs_spinlock.h6generic-y += mcs_spinlock.h
7generic-y += ring_buffer.h
7generic-y += text-patching.h8generic-y += text-patching.h
arch/um/include/asm/Kbuild+1−0
@@ -17,6 +17,7 @@ generic-y += module.lds.h · 16 unmodified lines
17generic-y += parport.h17generic-y += parport.h
18generic-y += percpu.h18generic-y += percpu.h
19generic-y += preempt.h19generic-y += preempt.h
20generic-y += ring_buffer.h
20generic-y += runtime-const.h21generic-y += runtime-const.h
21generic-y += softirq_stack.h22generic-y += softirq_stack.h
22generic-y += switch_to.h23generic-y += switch_to.h
arch/x86/include/asm/Kbuild+1−0
@@ -14,3 +14,4 @@ generic-y += early_ioremap.h · 13 unmodified lines
14generic-y += fprobe.h14generic-y += fprobe.h
15generic-y += mcs_spinlock.h15generic-y += mcs_spinlock.h
16generic-y += mmzone.h16generic-y += mmzone.h
17generic-y += ring_buffer.h
arch/xtensa/include/asm/Kbuild+1−0
@@ -6,5 +6,6 @@ generic-y += mcs_spinlock.h · 5 unmodified lines
6generic-y += parport.h6generic-y += parport.h
7generic-y += qrwlock.h7generic-y += qrwlock.h
8generic-y += qspinlock.h8generic-y += qspinlock.h
9generic-y += ring_buffer.h
9generic-y += user.h10generic-y += user.h
10generic-y += text-patching.h11generic-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
7#include <linux/ring_buffer_types.h>7#include <linux/ring_buffer_types.h>
8#include <linux/sched/isolation.h>8#include <linux/sched/isolation.h>
9#include <linux/trace_recursion.h>9#include <linux/trace_recursion.h>
10#include <linux/panic_notifier.h>
10#include <linux/trace_events.h>11#include <linux/trace_events.h>
11#include <linux/ring_buffer.h>12#include <linux/ring_buffer.h>
12#include <linux/trace_clock.h>13#include <linux/trace_clock.h>
@@ -31,6 +32,7 @@ · 18 unmodified lines
31#include <linux/oom.h>32#include <linux/oom.h>
32#include <linux/mm.h>33#include <linux/mm.h>
33 34
35#include <asm/ring_buffer.h>
34#include <asm/local64.h>36#include <asm/local64.h>
35#include <asm/local.h>37#include <asm/local.h>
36#include <asm/setup.h>38#include <asm/setup.h>
@@ -559,6 +561,7 @@ struct trace_buffer { · 522 unmodified lines
559 561
560 unsigned long range_addr_start;562 unsigned long range_addr_start;
561 unsigned long range_addr_end;563 unsigned long range_addr_end;
564 struct notifier_block flush_nb;
562 565
563 struct ring_buffer_meta *meta;566 struct ring_buffer_meta *meta;
564 567
@@ -2521,6 +2524,16 @@ static void rb_free_cpu_buffer(struct ring_buffer_per_cpu *cpu_buffer) · 1956 unmodified lines
2521 kfree(cpu_buffer);2524 kfree(cpu_buffer);
2522}2525}
2523 2526
2527/* Stop recording on a persistent buffer and flush cache if needed. */
2528static 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
2524static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags,2537static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags,
2525 int order, unsigned long start,2538 int order, unsigned long start,
2526 unsigned long end,2539 unsigned long end,
@@ -2651,6 +2664,12 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags, · 124 unmodified lines
2651 2664
2652 mutex_init(&buffer->mutex);2665 mutex_init(&buffer->mutex);
2653 2666
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
2654 return_ptr(buffer);2673 return_ptr(buffer);
2655 2674
2656 fail_free_buffers:2675 fail_free_buffers:
@@ -2749,6 +2768,9 @@ ring_buffer_free(struct trace_buffer *buffer) · 92 unmodified lines
2749{2768{
2750 int cpu;2769 int cpu;
2751 2770
2771 if (buffer->range_addr_start && buffer->range_addr_end)
2772 atomic_notifier_chain_unregister(&panic_notifier_list, &buffer->flush_nb);
2773
2752 cpuhp_state_remove_instance(CPUHP_TRACE_RB_PREPARE, &buffer->node);2774 cpuhp_state_remove_instance(CPUHP_TRACE_RB_PREPARE, &buffer->node);
2753 2775
2754 irq_work_sync(&buffer->irq_work.work);2776 irq_work_sync(&buffer->irq_work.work);