Konstantin Demin
c3d09a3e94
imported from https://salsa.debian.org/kernel-team/linux.git commit 9d5cc9d9d6501d7f1dd7e194d4b245bd0b6c6a22 version 6.11.4-1
174 lines
6.1 KiB
Diff
174 lines
6.1 KiB
Diff
From: Thomas Gleixner <tglx@linutronix.de>
|
|
Date: Tue, 20 Aug 2024 08:35:57 +0206
|
|
Subject: [PATCH 31/54] printk: nbcon: Implement emergency sections
|
|
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.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(). This
|
|
information should be pushed out to the consoles ASAP.
|
|
|
|
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.
|
|
|
|
Perform direct console flushing at the emergency priority if
|
|
the current CPU is in an emergency state and it is safe to do
|
|
so.
|
|
|
|
Note that the emergency state is not system-wide. While one CPU
|
|
is in an emergency state, another CPU may attempt to print
|
|
console messages at normal priority.
|
|
|
|
Also note that printk() already attempts to flush consoles in
|
|
the caller context for normal priority. However, follow-up
|
|
changes will introduce printing kthreads, in which case the
|
|
normal priority printk() calls will offload to the kthreads.
|
|
|
|
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>
|
|
Reviewed-by: Petr Mladek <pmladek@suse.com>
|
|
Link: https://lore.kernel.org/r/20240820063001.36405-32-john.ogness@linutronix.de
|
|
Signed-off-by: Petr Mladek <pmladek@suse.com>
|
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
---
|
|
include/linux/console.h | 4 ++
|
|
kernel/printk/internal.h | 1
|
|
kernel/printk/nbcon.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++-
|
|
3 files changed, 79 insertions(+), 1 deletion(-)
|
|
|
|
--- a/include/linux/console.h
|
|
+++ b/include/linux/console.h
|
|
@@ -553,10 +553,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/internal.h
|
|
+++ b/kernel/printk/internal.h
|
|
@@ -182,6 +182,7 @@ static inline void printk_get_console_fl
|
|
|
|
switch (nbcon_get_default_prio()) {
|
|
case NBCON_PRIO_NORMAL:
|
|
+ case NBCON_PRIO_EMERGENCY:
|
|
if (have_nbcon_console && !have_boot_console)
|
|
ft->nbcon_atomic = true;
|
|
|
|
--- a/kernel/printk/nbcon.c
|
|
+++ b/kernel/printk/nbcon.c
|
|
@@ -972,6 +972,36 @@ 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
|
|
+ *
|
|
+ * Context: For reading, any context. For writing, any context which could
|
|
+ * not be migrated to another CPU.
|
|
+ * Return: Either a pointer to the per CPU emergency nesting counter of
|
|
+ * the current CPU or to the init data during early boot.
|
|
+ *
|
|
+ * The function is safe for reading per-CPU variables in any context because
|
|
+ * preemption is disabled if the current CPU is in the emergency state. See
|
|
+ * also nbcon_cpu_emergency_enter().
|
|
+ */
|
|
+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;
|
|
+
|
|
+ /* Open code this_cpu_ptr() without checking migration. */
|
|
+ return per_cpu_ptr(&nbcon_pcpu_emergency_nesting, raw_smp_processor_id());
|
|
+}
|
|
+
|
|
/**
|
|
* nbcon_get_default_prio - The appropriate nbcon priority to use for nbcon
|
|
* printing on the current CPU
|
|
@@ -981,13 +1011,20 @@ static bool nbcon_emit_next_record(struc
|
|
* context for printing.
|
|
*
|
|
* The function is safe for reading per-CPU data in any context because
|
|
- * preemption is disabled if the current CPU is in the panic state.
|
|
+ * preemption is disabled if the current CPU is in the emergency or panic
|
|
+ * state.
|
|
*/
|
|
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;
|
|
}
|
|
|
|
@@ -1247,6 +1284,42 @@ void nbcon_atomic_flush_unsafe(void)
|
|
}
|
|
|
|
/**
|
|
+ * nbcon_cpu_emergency_enter - Enter an emergency section where printk()
|
|
+ * messages for that CPU are flushed directly
|
|
+ *
|
|
+ * Context: Any context. Disables preemption.
|
|
+ *
|
|
+ * When within an emergency section, printk() calls will attempt to flush any
|
|
+ * pending messages in the ringbuffer.
|
|
+ */
|
|
+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
|
|
+ *
|
|
+ * Context: Within an emergency section. Enables preemption.
|
|
+ */
|
|
+void nbcon_cpu_emergency_exit(void)
|
|
+{
|
|
+ unsigned int *cpu_emergency_nesting;
|
|
+
|
|
+ cpu_emergency_nesting = nbcon_get_cpu_emergency_nesting();
|
|
+
|
|
+ if (!WARN_ON_ONCE(*cpu_emergency_nesting == 0))
|
|
+ (*cpu_emergency_nesting)--;
|
|
+
|
|
+ preempt_enable();
|
|
+}
|
|
+
|
|
+/**
|
|
* nbcon_alloc - Allocate and init the nbcon console specific data
|
|
* @con: Console to initialize
|
|
*
|