summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/0028-printk-nbcon-Implement-emergency-sections.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-rt/0028-printk-nbcon-Implement-emergency-sections.patch')
-rw-r--r--debian/patches-rt/0028-printk-nbcon-Implement-emergency-sections.patch201
1 files changed, 201 insertions, 0 deletions
diff --git a/debian/patches-rt/0028-printk-nbcon-Implement-emergency-sections.patch b/debian/patches-rt/0028-printk-nbcon-Implement-emergency-sections.patch
new file mode 100644
index 000000000..f3a05868e
--- /dev/null
+++ b/debian/patches-rt/0028-printk-nbcon-Implement-emergency-sections.patch
@@ -0,0 +1,201 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 11 Sep 2023 15:21:57 +0000
+Subject: [PATCH 28/48] printk: nbcon: Implement emergency sections
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.8/older/patches-6.8.2-rt11.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 | 4 ++
+ kernel/printk/nbcon.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++
+ kernel/printk/printk.c | 13 ++++++-
+ 3 files changed, 98 insertions(+), 2 deletions(-)
+
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -559,10 +559,14 @@ 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 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 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/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_atomic_emit_one - Print one record for an nbcon console using the
+ * write_atomic() callback
+@@ -977,9 +1000,15 @@ static bool nbcon_atomic_emit_one(struct
+ */
+ 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;
+ }
+
+@@ -1147,6 +1176,60 @@ 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();
++
++ WARN_ON_ONCE(*cpu_emergency_nesting == 0);
++
++ if (*cpu_emergency_nesting == 1) {
++ nbcon_atomic_flush_pending();
++ do_trigger_flush = true;
++ }
++
++ /* Undo the nesting count of nbcon_cpu_emergency_enter(). */
++ (*cpu_emergency_nesting)--;
++
++ preempt_enable();
++
++ if (do_trigger_flush)
++ printk_trigger_flush();
++}
++
++/**
+ * 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
+@@ -2417,16 +2417,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();
+ }
+