[PATCH printk v4 00/27] wire up write_atomic() printing

From: John Ogness
Date: Tue Apr 02 2024 - 18:11:56 EST


Hi,

This is v4 of a series to wire up the nbcon consoles so that
they actually perform printing using their write_atomic()
callback. v3 is here [0]. For information about the motivation
of the atomic consoles, please read the cover letter of v1 [1].

The main focus of this series:

- For nbcon consoles, always call write_atomic() directly from
printk() caller context for the panic CPU.

- For nbcon consoles, call write_atomic() when unlocking the
console lock.

- Only perform the console lock/unlock dance if legacy or boot
consoles are registered.

- For legacy consoles, if nbcon consoles are registered, do not
attempt to print from printk() caller context for the panic
CPU until nbcon consoles have had a chance to print the most
significant messages.

- Mark emergency sections. In these sections printk() calls
will only store the messages. Upon exiting the emergency
section, nbcon consoles are flushed directly and legacy
console flushing is triggered via irq_work.

This series does _not_ include threaded printing or nbcon
drivers. Those features will be added in separate follow-up
series.

Note: With this series, a system with _only_ nbcon consoles
registered will not perform console printing unless the
console lock is used (for synchronization), or when
exiting emergency sections, or on panic. This is on
purpose. When nbcon kthreads are introduced, they will
fill the gaps.

The changes since v3:

- Modify the documentation of console_srcu_read_flags() to
clarify that it is needed anytime a console _might_ be
registered and the caller is not holding the
console_list_lock. Hopefully this makes it clear when this
helper function is needed.

- Create a function uart_port_set_cons() for setting @cons of
struct uart_port. It modifies @cons under the port lock to
avoid possible races within the port lock wrapper. All (5)
code sites are modified to use the new function.

- Introduce 2 new required nbcon console callbacks
device_lock()/device_unlock() to implement any internal
locking required by the driver. (For example, for uart serial
consoles it is locking/unlocking the port lock.) This is used
during console registration to ensure that the hardware is
not in use while the console transitions to registered. This
avoids the risk that the port lock wrappers do not lock the
nbcon console lock while the console was being registered on
another CPU. These callbacks also will be used later by the
printing kthreads.

- Introduce struct nbcon_drvdata to track ownership state when
using the port lock wrappers. This provides a race-free
alternative to the @nbcon_locked_port flag used in v3.

- Split the functionality of uart_nbcon_acquire() and
uart_nbcon_release() into driver-specific and generic parts.
The generic functions are named nbcon_driver_acquire() and
nbcon_driver_release(). The driver-specific part is moved
into serial_core.h into the new helper functions
__uart_port_nbcon_acquire() and __uart_port_nbcon_release().

- Rename nbcon_atomic_flush_all() to
nbcon_atomic_flush_pending() to emphasize that it only prints
up to the latest record at the time of the call. Also, flush
all the pending records of a console (without releasing
ownership in between) before flushing the next nbcon console.
This allows the full emergency block to be printed on at
least one atomic console before trying the next.

- Flush nbcon consoles directly in the caller context when
exiting an emergency section.

- If a CPU is in EMERGENCY context, do not trigger printing
of legacy consoles via irq_work.

- In panic, allow synchronous legacy printing before calling
the panic handlers. Attempt to flush there in the panic
context as well.

- Remove the return value for the nbcon console atomic_write()
callback. If ownership has not been lost, it is assumed the
printing was successful.

- Add a WARN_ON_ONCE if nbcon_emit_next_record() is called for
a console that has not provided a write_atomic() callback.

- Change the meaning of the return value of
nbcon_atomic_emit_one() to allow
nbcon_legacy_emit_next_record() to have the same return value
meaning as console_emit_next_record().

- Remove all legacy @seq handling from nbcon.c. For nbcon
consoles, printk.c handles the transfer and resetting of the
legacy @seq value to @nbcon_seq.

- Add a compiler barrier in __pr_flush() to ensure the compiler
does not optimize out a local variable by replacing it with
a racy read of multiple global variables.

- Let __wake_up_klogd() remove unnecessary flags before
possibly queuing irq_work.

- Eliminate header proxying in nbcon.c.

- Mark _all_ lockdep output blocks as emergency sections.

- Mark _all_ rcu stall blocks as emergency sections.

- Remove "(Optional)" in the documentation of the
write_atomic() callback. Once threads are available, it will
be optional. But at this point in the rework it is not.

John Ogness

[0] https://lore.kernel.org/lkml/20240218185726.1994771-1-john.ogness@xxxxxxxxxxxxx
[1] https://lore.kernel.org/lkml/20230302195618.156940-1-john.ogness@xxxxxxxxxxxxx

John Ogness (23):
printk: Add notation to console_srcu locking
printk: Properly deal with nbcon consoles on seq init
printk: nbcon: Remove return value for write_atomic()
printk: nbcon: Add detailed doc for write_atomic()
printk: nbcon: Add callbacks to synchronize with driver
printk: nbcon: Use driver synchronization while registering
serial: core: Provide low-level functions to lock port
printk: nbcon: Implement processing in port->lock wrapper
printk: nbcon: Do not rely on proxy headers
printk: nbcon: Fix kerneldoc for enums
printk: Make console_is_usable() available to nbcon
printk: Let console_is_usable() handle nbcon
printk: Add @flags argument for console_is_usable()
printk: Track registered boot consoles
printk: nbcon: Use nbcon consoles in console_flush_all()
printk: nbcon: Assign priority based on CPU state
printk: nbcon: Add unsafe flushing on panic
printk: Avoid console_lock dance if no legacy or boot consoles
printk: Track nbcon consoles
printk: Coordinate direct printing in panic
panic: Mark emergency section in oops
rcu: Mark emergency section in rcu stalls
lockdep: Mark emergency sections in lockdep splats

Sebastian Andrzej Siewior (1):
printk: Check printk_deferred_enter()/_exit() usage

Thomas Gleixner (3):
printk: nbcon: Provide function to flush using write_atomic()
printk: nbcon: Implement emergency sections
panic: Mark emergency section in warn

drivers/tty/serial/8250/8250_core.c | 6 +-
drivers/tty/serial/amba-pl011.c | 2 +-
drivers/tty/serial/serial_core.c | 2 +-
include/linux/console.h | 138 ++++++++--
include/linux/printk.h | 32 ++-
include/linux/serial_core.h | 116 ++++++++-
kernel/locking/lockdep.c | 91 ++++++-
kernel/panic.c | 9 +
kernel/printk/internal.h | 56 +++-
kernel/printk/nbcon.c | 382 ++++++++++++++++++++++++++--
kernel/printk/printk.c | 287 ++++++++++++++++-----
kernel/printk/printk_ringbuffer.h | 2 +
kernel/printk/printk_safe.c | 12 +
kernel/rcu/tree_exp.h | 7 +
kernel/rcu/tree_stall.h | 9 +
15 files changed, 1038 insertions(+), 113 deletions(-)


base-commit: a2b4cab9da7746c42f87c13721d305baf0085a20
--
2.39.2