summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/0025-printk-nbcon-Implement-emergency-sections.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-rt/0025-printk-nbcon-Implement-emergency-sections.patch')
-rw-r--r--debian/patches-rt/0025-printk-nbcon-Implement-emergency-sections.patch283
1 files changed, 283 insertions, 0 deletions
diff --git a/debian/patches-rt/0025-printk-nbcon-Implement-emergency-sections.patch b/debian/patches-rt/0025-printk-nbcon-Implement-emergency-sections.patch
new file mode 100644
index 0000000000..44327c280a
--- /dev/null
+++ b/debian/patches-rt/0025-printk-nbcon-Implement-emergency-sections.patch
@@ -0,0 +1,283 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 11 Sep 2023 15:21:57 +0000
+Subject: [PATCH 25/46] printk: nbcon: Implement emergency sections
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.9/older/patches-6.9-rt5.tar.xz
+
+In emergency situations (something has gone wrong but the
+system continues to operate), usually important information
+(such as a backtrace) is generated via printk(). Each
+individual printk record has little meaning. It is the
+collection of printk messages that is most often needed by
+developers and users.
+
+In order to help ensure that the collection of printk messages
+in an emergency situation are all stored to the ringbuffer as
+quickly as possible, disable console output for that CPU while
+it is in the emergency situation. The consoles need to be
+flushed when exiting the emergency situation.
+
+Add per-CPU emergency nesting tracking because an emergency
+can arise while in an emergency situation.
+
+Add functions to mark the beginning and end of emergency
+sections where the urgent messages are generated.
+
+Do not print if the current CPU is in an emergency state.
+
+When exiting all emergency nesting, flush nbcon consoles
+directly using their atomic callback. Legacy consoles are
+triggered for flushing via irq_work because it is not known
+if the context was safe for a trylock on the console lock.
+
+Note that the emergency state is not system-wide. While one CPU
+is in an emergency state, another CPU may continue to print
+console messages.
+
+Co-developed-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Thomas Gleixner (Intel) <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/console.h | 6 ++
+ kernel/printk/internal.h | 11 ++++
+ kernel/printk/nbcon.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++
+ kernel/printk/printk.c | 25 +++++-----
+ 4 files changed, 146 insertions(+), 12 deletions(-)
+
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -553,10 +553,16 @@ static inline bool console_is_registered
+ hlist_for_each_entry(con, &console_list, node)
+
+ #ifdef CONFIG_PRINTK
++extern void nbcon_cpu_emergency_enter(void);
++extern void nbcon_cpu_emergency_exit(void);
++extern void nbcon_cpu_emergency_flush(void);
+ extern bool nbcon_can_proceed(struct nbcon_write_context *wctxt);
+ extern bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt);
+ extern bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt);
+ #else
++static inline void nbcon_cpu_emergency_enter(void) { }
++static inline void nbcon_cpu_emergency_exit(void) { }
++static inline void nbcon_cpu_emergency_flush(void) { }
+ static inline bool nbcon_can_proceed(struct nbcon_write_context *wctxt) { return false; }
+ static inline bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt) { return false; }
+ static inline bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt) { return false; }
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -153,6 +153,17 @@ static inline bool console_is_usable(str
+
+ #endif /* CONFIG_PRINTK */
+
++extern bool have_boot_console;
++extern bool have_legacy_console;
++
++/*
++ * Specifies if the console lock/unlock dance is needed for console
++ * printing. If @have_boot_console is true, the nbcon consoles will
++ * be printed serially along with the legacy consoles because nbcon
++ * consoles cannot print simultaneously with boot consoles.
++ */
++#define printing_via_unlock (have_legacy_console || have_boot_console)
++
+ extern struct printk_buffers printk_shared_pbufs;
+
+ /**
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -936,6 +936,29 @@ static bool nbcon_emit_next_record(struc
+ return nbcon_context_exit_unsafe(ctxt);
+ }
+
++/* Track the nbcon emergency nesting per CPU. */
++static DEFINE_PER_CPU(unsigned int, nbcon_pcpu_emergency_nesting);
++static unsigned int early_nbcon_pcpu_emergency_nesting __initdata;
++
++/**
++ * nbcon_get_cpu_emergency_nesting - Get the per CPU emergency nesting pointer
++ *
++ * Return: Either a pointer to the per CPU emergency nesting counter of
++ * the current CPU or to the init data during early boot.
++ */
++static __ref unsigned int *nbcon_get_cpu_emergency_nesting(void)
++{
++ /*
++ * The value of __printk_percpu_data_ready gets set in normal
++ * context and before SMP initialization. As a result it could
++ * never change while inside an nbcon emergency section.
++ */
++ if (!printk_percpu_data_ready())
++ return &early_nbcon_pcpu_emergency_nesting;
++
++ return this_cpu_ptr(&nbcon_pcpu_emergency_nesting);
++}
++
+ /**
+ * nbcon_get_default_prio - The appropriate nbcon priority to use for nbcon
+ * printing on the current CPU
+@@ -946,9 +969,15 @@ static bool nbcon_emit_next_record(struc
+ */
+ enum nbcon_prio nbcon_get_default_prio(void)
+ {
++ unsigned int *cpu_emergency_nesting;
++
+ if (this_cpu_in_panic())
+ return NBCON_PRIO_PANIC;
+
++ cpu_emergency_nesting = nbcon_get_cpu_emergency_nesting();
++ if (*cpu_emergency_nesting)
++ return NBCON_PRIO_EMERGENCY;
++
+ return NBCON_PRIO_NORMAL;
+ }
+
+@@ -1200,6 +1229,93 @@ void nbcon_atomic_flush_unsafe(void)
+ }
+
+ /**
++ * nbcon_cpu_emergency_enter - Enter an emergency section where printk()
++ * messages for that CPU are only stored
++ *
++ * Upon exiting the emergency section, all stored messages are flushed.
++ *
++ * Context: Any context. Disables preemption.
++ *
++ * When within an emergency section, no printing occurs on that CPU. This
++ * is to allow all emergency messages to be dumped into the ringbuffer before
++ * flushing the ringbuffer. The actual printing occurs when exiting the
++ * outermost emergency section.
++ */
++void nbcon_cpu_emergency_enter(void)
++{
++ unsigned int *cpu_emergency_nesting;
++
++ preempt_disable();
++
++ cpu_emergency_nesting = nbcon_get_cpu_emergency_nesting();
++ (*cpu_emergency_nesting)++;
++}
++
++/**
++ * nbcon_cpu_emergency_exit - Exit an emergency section and flush the
++ * stored messages
++ *
++ * Flushing only occurs when exiting all nesting for the CPU.
++ *
++ * Context: Any context. Enables preemption.
++ */
++void nbcon_cpu_emergency_exit(void)
++{
++ unsigned int *cpu_emergency_nesting;
++ bool do_trigger_flush = false;
++
++ cpu_emergency_nesting = nbcon_get_cpu_emergency_nesting();
++
++ /*
++ * Flush the messages before enabling preemtion to see them ASAP.
++ *
++ * Reduce the risk of potential softlockup by using the
++ * flush_pending() variant which ignores messages added later. It is
++ * called before decrementing the counter so that the printing context
++ * for the emergency messages is NBCON_PRIO_EMERGENCY.
++ */
++ if (*cpu_emergency_nesting == 1) {
++ nbcon_atomic_flush_pending();
++ do_trigger_flush = true;
++ }
++
++ (*cpu_emergency_nesting)--;
++
++ if (WARN_ON_ONCE(*cpu_emergency_nesting < 0))
++ *cpu_emergency_nesting = 0;
++
++ preempt_enable();
++
++ if (do_trigger_flush)
++ printk_trigger_flush();
++}
++
++/**
++ * nbcon_cpu_emergency_flush - Explicitly flush consoles while
++ * within emergency context
++ *
++ * Both nbcon and legacy consoles are flushed.
++ *
++ * It should be used only when there are too many messages printed
++ * in emergency context, for example, printing backtraces of all
++ * CPUs or processes. It is typically needed when the watchdogs
++ * need to be touched as well.
++ */
++void nbcon_cpu_emergency_flush(void)
++{
++ /* The explicit flush is needed only in the emergency context. */
++ if (*(nbcon_get_cpu_emergency_nesting()) == 0)
++ return;
++
++ nbcon_atomic_flush_pending();
++
++ if (printing_via_unlock && !in_nmi()) {
++ if (console_trylock())
++ console_unlock();
++ }
++}
++
++/**
+ * nbcon_alloc - Allocate buffers needed by the nbcon console
+ * @con: Console to allocate buffers for
+ *
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -468,7 +468,7 @@ static DEFINE_MUTEX(syslog_lock);
+ * present, it is necessary to perform the console lock/unlock dance
+ * whenever console flushing should occur.
+ */
+-static bool have_legacy_console;
++bool have_legacy_console;
+
+ /*
+ * Specifies if an nbcon console is registered. If nbcon consoles are present,
+@@ -483,15 +483,7 @@ static bool have_nbcon_console;
+ * the console lock. This is because boot consoles and nbcon consoles may
+ * have mapped the same hardware.
+ */
+-static bool have_boot_console;
+-
+-/*
+- * Specifies if the console lock/unlock dance is needed for console
+- * printing. If @have_boot_console is true, the nbcon consoles will
+- * be printed serially along with the legacy consoles because nbcon
+- * consoles cannot print simultaneously with boot consoles.
+- */
+-#define printing_via_unlock (have_legacy_console || have_boot_console)
++bool have_boot_console;
+
+ #ifdef CONFIG_PRINTK
+ DECLARE_WAIT_QUEUE_HEAD(log_wait);
+@@ -2412,16 +2404,25 @@ asmlinkage int vprintk_emit(int facility
+ * printing of all remaining records to all consoles so that
+ * this context can return as soon as possible. Hopefully
+ * another printk() caller will take over the printing.
++ *
++ * Also, nbcon_get_default_prio() requires migration disabled.
+ */
+ preempt_disable();
++
+ /*
+ * Try to acquire and then immediately release the console
+ * semaphore. The release will print out buffers. With the
+ * spinning variant, this context tries to take over the
+ * printing from another printing context.
++ *
++ * Skip it in EMERGENCY priority. The console will be
++ * explicitly flushed when exiting the emergency section.
+ */
+- if (console_trylock_spinning())
+- console_unlock();
++ if (nbcon_get_default_prio() != NBCON_PRIO_EMERGENCY) {
++ if (console_trylock_spinning())
++ console_unlock();
++ }
++
+ preempt_enable();
+ }
+