diff options
Diffstat (limited to '')
-rw-r--r-- | debian/patches-rt/0075-printk-Add-non-BKL-nbcon-console-basic-infrastructur.patch | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/debian/patches-rt/0075-printk-Add-non-BKL-nbcon-console-basic-infrastructur.patch b/debian/patches-rt/0075-printk-Add-non-BKL-nbcon-console-basic-infrastructur.patch new file mode 100644 index 0000000000..00f7850c36 --- /dev/null +++ b/debian/patches-rt/0075-printk-Add-non-BKL-nbcon-console-basic-infrastructur.patch @@ -0,0 +1,261 @@ +From: Thomas Gleixner <tglx@linutronix.de> +Date: Sat, 16 Sep 2023 21:26:00 +0206 +Subject: [PATCH 075/134] printk: Add non-BKL (nbcon) console basic + infrastructure +Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz + +The current console/printk subsystem is protected by a Big Kernel Lock, +(aka console_lock) which has ill defined semantics and is more or less +stateless. This puts severe limitations on the console subsystem and +makes forced takeover and output in emergency and panic situations a +fragile endeavour that is based on try and pray. + +The goal of non-BKL (nbcon) consoles is to break out of the console lock +jail and to provide a new infrastructure that avoids the pitfalls and +also allows console drivers to be gradually converted over. + +The proposed infrastructure aims for the following properties: + + - Per console locking instead of global locking + - Per console state that allows to make informed decisions + - Stateful handover and takeover + +As a first step, state is added to struct console. The per console state +is an atomic_t using a 32bit bit field. + +Reserve state bits, which will be populated later in the series. Wire +it up into the console register/unregister functionality. + +It was decided to use a bitfield because using a plain u32 with +mask/shift operations resulted in uncomprehensible code. + +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> +Signed-off-by: Petr Mladek <pmladek@suse.com> +Link: https://lore.kernel.org/r/20230916192007.608398-2-john.ogness@linutronix.de +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +--- + include/linux/console.h | 31 ++++++++++++++++++++ + kernel/printk/Makefile | 2 - + kernel/printk/internal.h | 8 +++++ + kernel/printk/nbcon.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++ + kernel/printk/printk.c | 13 ++++++-- + 5 files changed, 120 insertions(+), 4 deletions(-) + create mode 100644 kernel/printk/nbcon.c + +--- a/include/linux/console.h ++++ b/include/linux/console.h +@@ -156,6 +156,8 @@ static inline int con_debug_leave(void) + * /dev/kmesg which requires a larger output buffer. + * @CON_SUSPENDED: Indicates if a console is suspended. If true, the + * printing callbacks must not be called. ++ * @CON_NBCON: Console can operate outside of the legacy style console_lock ++ * constraints. + */ + enum cons_flags { + CON_PRINTBUFFER = BIT(0), +@@ -166,9 +168,33 @@ enum cons_flags { + CON_BRL = BIT(5), + CON_EXTENDED = BIT(6), + CON_SUSPENDED = BIT(7), ++ CON_NBCON = BIT(8), + }; + + /** ++ * struct nbcon_state - console state for nbcon consoles ++ * @atom: Compound of the state fields for atomic operations ++ * ++ * To be used for reading and preparing of the value stored in the nbcon ++ * state variable @console::nbcon_state. ++ */ ++struct nbcon_state { ++ union { ++ unsigned int atom; ++ struct { ++ }; ++ }; ++}; ++ ++/* ++ * The nbcon_state struct is used to easily create and interpret values that ++ * are stored in the @console::nbcon_state variable. Ensure this struct stays ++ * within the size boundaries of the atomic variable's underlying type in ++ * order to avoid any accidental truncation. ++ */ ++static_assert(sizeof(struct nbcon_state) <= sizeof(int)); ++ ++/** + * struct console - The console descriptor structure + * @name: The name of the console driver + * @write: Write callback to output messages (Optional) +@@ -187,6 +213,8 @@ enum cons_flags { + * @dropped: Number of unreported dropped ringbuffer records + * @data: Driver private data + * @node: hlist node for the console list ++ * ++ * @nbcon_state: State for nbcon consoles + */ + struct console { + char name[16]; +@@ -206,6 +234,9 @@ struct console { + unsigned long dropped; + void *data; + struct hlist_node node; ++ ++ /* nbcon console specific members */ ++ atomic_t __private nbcon_state; + }; + + #ifdef CONFIG_LOCKDEP +--- a/kernel/printk/Makefile ++++ b/kernel/printk/Makefile +@@ -1,6 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0-only + obj-y = printk.o +-obj-$(CONFIG_PRINTK) += printk_safe.o ++obj-$(CONFIG_PRINTK) += printk_safe.o nbcon.o + obj-$(CONFIG_A11Y_BRAILLE_CONSOLE) += braille.o + obj-$(CONFIG_PRINTK_INDEX) += index.o + +--- a/kernel/printk/internal.h ++++ b/kernel/printk/internal.h +@@ -3,6 +3,7 @@ + * internal.h - printk internal definitions + */ + #include <linux/percpu.h> ++#include <linux/console.h> + + #if defined(CONFIG_PRINTK) && defined(CONFIG_SYSCTL) + void __init printk_sysctl_init(void); +@@ -61,6 +62,10 @@ void defer_console_output(void); + + u16 printk_parse_prefix(const char *text, int *level, + enum printk_info_flags *flags); ++ ++void nbcon_init(struct console *con); ++void nbcon_cleanup(struct console *con); ++ + #else + + #define PRINTK_PREFIX_MAX 0 +@@ -76,6 +81,9 @@ u16 printk_parse_prefix(const char *text + #define printk_safe_exit_irqrestore(flags) local_irq_restore(flags) + + static inline bool printk_percpu_data_ready(void) { return false; } ++static inline void nbcon_init(struct console *con) { } ++static inline void nbcon_cleanup(struct console *con) { } ++ + #endif /* CONFIG_PRINTK */ + + /** +--- /dev/null ++++ b/kernel/printk/nbcon.c +@@ -0,0 +1,70 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++// Copyright (C) 2022 Linutronix GmbH, John Ogness ++// Copyright (C) 2022 Intel, Thomas Gleixner ++ ++#include <linux/kernel.h> ++#include <linux/console.h> ++#include "internal.h" ++/* ++ * Printk console printing implementation for consoles which does not depend ++ * on the legacy style console_lock mechanism. ++ */ ++ ++/** ++ * nbcon_state_set - Helper function to set the console state ++ * @con: Console to update ++ * @new: The new state to write ++ * ++ * Only to be used when the console is not yet or no longer visible in the ++ * system. Otherwise use nbcon_state_try_cmpxchg(). ++ */ ++static inline void nbcon_state_set(struct console *con, struct nbcon_state *new) ++{ ++ atomic_set(&ACCESS_PRIVATE(con, nbcon_state), new->atom); ++} ++ ++/** ++ * nbcon_state_read - Helper function to read the console state ++ * @con: Console to read ++ * @state: The state to store the result ++ */ ++static inline void nbcon_state_read(struct console *con, struct nbcon_state *state) ++{ ++ state->atom = atomic_read(&ACCESS_PRIVATE(con, nbcon_state)); ++} ++ ++/** ++ * nbcon_state_try_cmpxchg() - Helper function for atomic_try_cmpxchg() on console state ++ * @con: Console to update ++ * @cur: Old/expected state ++ * @new: New state ++ * ++ * Return: True on success. False on fail and @cur is updated. ++ */ ++static inline bool nbcon_state_try_cmpxchg(struct console *con, struct nbcon_state *cur, ++ struct nbcon_state *new) ++{ ++ return atomic_try_cmpxchg(&ACCESS_PRIVATE(con, nbcon_state), &cur->atom, new->atom); ++} ++ ++/** ++ * nbcon_init - Initialize the nbcon console specific data ++ * @con: Console to initialize ++ */ ++void nbcon_init(struct console *con) ++{ ++ struct nbcon_state state = { }; ++ ++ nbcon_state_set(con, &state); ++} ++ ++/** ++ * nbcon_cleanup - Cleanup the nbcon console specific data ++ * @con: Console to cleanup ++ */ ++void nbcon_cleanup(struct console *con) ++{ ++ struct nbcon_state state = { }; ++ ++ nbcon_state_set(con, &state); ++} +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -3326,9 +3326,10 @@ static void try_enable_default_console(s + newcon->flags |= CON_CONSDEV; + } + +-#define con_printk(lvl, con, fmt, ...) \ +- printk(lvl pr_fmt("%sconsole [%s%d] " fmt), \ +- (con->flags & CON_BOOT) ? "boot" : "", \ ++#define con_printk(lvl, con, fmt, ...) \ ++ printk(lvl pr_fmt("%s%sconsole [%s%d] " fmt), \ ++ (con->flags & CON_NBCON) ? "" : "legacy ", \ ++ (con->flags & CON_BOOT) ? "boot" : "", \ + con->name, con->index, ##__VA_ARGS__) + + static void console_init_seq(struct console *newcon, bool bootcon_registered) +@@ -3488,6 +3489,9 @@ void register_console(struct console *ne + newcon->dropped = 0; + console_init_seq(newcon, bootcon_registered); + ++ if (newcon->flags & CON_NBCON) ++ nbcon_init(newcon); ++ + /* + * Put this console in the list - keep the + * preferred driver at the head of the list. +@@ -3579,6 +3583,9 @@ static int unregister_console_locked(str + */ + synchronize_srcu(&console_srcu); + ++ if (console->flags & CON_NBCON) ++ nbcon_cleanup(console); ++ + console_sysfs_notify(); + + if (console->exit) |