diff options
author | Linus Torvalds | 2023-11-03 07:24:22 -1000 |
---|---|---|
committer | Linus Torvalds | 2023-11-03 07:24:22 -1000 |
commit | 2a80532c0745e140852e6b579bbe8371332bb45d (patch) | |
tree | 07dec9596c21e8ada353c571308ddb40889b156b /include | |
parent | 00657bb3dbecee324336e1da1ad71b670b6aee60 (diff) | |
parent | 2966bd3698451a2172a57e7e97eebb4adbfc48a2 (diff) |
Merge tag 'printk-for-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux
Pull printk updates from Petr Mladek:
- Another preparation step for introducing printk kthreads. The main
piece is a per-console lock with several features:
- Support three priorities: normal, emergency, and panic. They will
be defined by a context where the lock is taken. A context with a
higher priority is allowed to take over the lock from a context
with a lower one.
The plan is to use the emergency context for Oops and WARN()
messages, and also by watchdogs.
The panic() context will be used on panic CPU.
- The owner might enter/exit regions where it is not safe to take
over the lock. It allows the take over the lock a safe way in the
middle of a message.
For example, serial drivers emit characters one by one. And the
serial port is in a safe state in between.
Only the final console_flush_in_panic() will be allowed to take
over the lock even in the unsafe state (last chance, pray, and
hope).
- A higher priority context might busy wait with a timeout. The
current owner is informed about the waiter and releases the lock
on exit from the unsafe state.
- The new lock is safe even in atomic contexts, including NMI.
Another change is a safe manipulation of per-console sequence number
counter under the new lock.
- simple_strntoull() micro-optimization
- Reduce pr_flush() pooling time.
- Calm down false warning about possible buffer invalid access to
console buffers when CONFIG_PRINTK is disabled.
[ .. and Thomas Gleixner wants to point out that while several of the
commits are attributed to him, he only authored the early versions of
said commits, and that John Ogness and Petr Mladek have been the ones
who sorted out the details and really should be those who get the
credit - Linus ]
* tag 'printk-for-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux:
vsprintf: uninline simple_strntoull(), reorder arguments
printk: printk: Remove unnecessary statements'len = 0;'
printk: Reduce pr_flush() pooling time
printk: fix illegal pbufs access for !CONFIG_PRINTK
printk: nbcon: Allow drivers to mark unsafe regions and check state
printk: nbcon: Add emit function and callback function for atomic printing
printk: nbcon: Add sequence handling
printk: nbcon: Add ownership state functions
printk: nbcon: Add buffer management
printk: Make static printk buffers available to nbcon
printk: nbcon: Add acquire/release logic
printk: Add non-BKL (nbcon) console basic infrastructure
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/console.h | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/include/linux/console.h b/include/linux/console.h index 7de11c763eb3..e4fc6f7c1496 100644 --- 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,6 +168,111 @@ 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 + * + * @req_prio: The priority of a handover request + * @prio: The priority of the current owner + * @unsafe: Console is busy in a non takeover region + * @unsafe_takeover: A hostile takeover in an unsafe state happened in the + * past. The console cannot be safe until re-initialized. + * @cpu: The CPU on which the owner runs + * + * To be used for reading and preparing of the value stored in the nbcon + * state variable @console::nbcon_state. + * + * The @prio and @req_prio fields are particularly important to allow + * spin-waiting to timeout and give up without the risk of a waiter being + * assigned the lock after giving up. + */ +struct nbcon_state { + union { + unsigned int atom; + struct { + unsigned int prio : 2; + unsigned int req_prio : 2; + unsigned int unsafe : 1; + unsigned int unsafe_takeover : 1; + unsigned int cpu : 24; + }; + }; +}; + +/* + * 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)); + +/** + * nbcon_prio - console owner priority for nbcon consoles + * @NBCON_PRIO_NONE: Unused + * @NBCON_PRIO_NORMAL: Normal (non-emergency) usage + * @NBCON_PRIO_EMERGENCY: Emergency output (WARN/OOPS...) + * @NBCON_PRIO_PANIC: Panic output + * @NBCON_PRIO_MAX: The number of priority levels + * + * A higher priority context can takeover the console when it is + * in the safe state. The final attempt to flush consoles in panic() + * can be allowed to do so even in an unsafe state (Hope and pray). + */ +enum nbcon_prio { + NBCON_PRIO_NONE = 0, + NBCON_PRIO_NORMAL, + NBCON_PRIO_EMERGENCY, + NBCON_PRIO_PANIC, + NBCON_PRIO_MAX, +}; + +struct console; +struct printk_buffers; + +/** + * struct nbcon_context - Context for console acquire/release + * @console: The associated console + * @spinwait_max_us: Limit for spin-wait acquire + * @prio: Priority of the context + * @allow_unsafe_takeover: Allow performing takeover even if unsafe. Can + * be used only with NBCON_PRIO_PANIC @prio. It + * might cause a system freeze when the console + * is used later. + * @backlog: Ringbuffer has pending records + * @pbufs: Pointer to the text buffer for this context + * @seq: The sequence number to print for this context + */ +struct nbcon_context { + /* members set by caller */ + struct console *console; + unsigned int spinwait_max_us; + enum nbcon_prio prio; + unsigned int allow_unsafe_takeover : 1; + + /* members set by emit */ + unsigned int backlog : 1; + + /* members set by acquire */ + struct printk_buffers *pbufs; + u64 seq; +}; + +/** + * struct nbcon_write_context - Context handed to the nbcon write callbacks + * @ctxt: The core console context + * @outbuf: Pointer to the text buffer for output + * @len: Length to write + * @unsafe_takeover: If a hostile takeover in an unsafe state has occurred + */ +struct nbcon_write_context { + struct nbcon_context __private ctxt; + char *outbuf; + unsigned int len; + bool unsafe_takeover; }; /** @@ -187,6 +294,11 @@ enum cons_flags { * @dropped: Number of unreported dropped ringbuffer records * @data: Driver private data * @node: hlist node for the console list + * + * @write_atomic: Write callback for atomic context + * @nbcon_state: State for nbcon consoles + * @nbcon_seq: Sequence number of the next record for nbcon to print + * @pbufs: Pointer to nbcon private buffer */ struct console { char name[16]; @@ -206,6 +318,13 @@ struct console { unsigned long dropped; void *data; struct hlist_node node; + + /* nbcon console specific members */ + bool (*write_atomic)(struct console *con, + struct nbcon_write_context *wctxt); + atomic_t __private nbcon_state; + atomic_long_t __private nbcon_seq; + struct printk_buffers *pbufs; }; #ifdef CONFIG_LOCKDEP @@ -332,6 +451,16 @@ static inline bool console_is_registered(const struct console *con) lockdep_assert_console_list_lock_held(); \ hlist_for_each_entry(con, &console_list, node) +#ifdef CONFIG_PRINTK +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 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; } +#endif + extern int console_set_on_cmdline; extern struct console *early_console; |