STRUCT CONSOLE(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’– struct console(9) πŸ’–

okay so bestie, welcome to struct console(9) from the Kernel API Manual β€” this is THE console descriptor structure, like the blueprint of every console driver in the kernel, and honestly? it's giving main character energy. let's get into it 🫢


✨ NAME ✨

struct console β€” the console descriptor structure. that's it, that's the vibe. πŸ‘‘


🌈 SYNOPSIS 🌈

struct console {
    char name[16];
    void (*write)(struct console *co, const char *s, unsigned int
count);
    int (*read)(struct console *co, char *s, unsigned int count);
    struct tty_driver       *(*device)(struct console *co, int *index);
    void (*unblank)(void);
    int (*setup)(struct console *co, char *options);
    int (*exit)(struct console *co);
    int (*match)(struct console *co, char *name, int idx, char
*options);
    short flags;
    short index;
    int cflag;
    uint ispeed;
    uint ospeed;
    u64 seq;
    unsigned long           dropped;
    void *data;
    struct hlist_node       node;
    void (*write_atomic)(struct console *con, struct nbcon_write_context
*wctxt);
    void (*write_thread)(struct console *con, struct nbcon_write_context
*wctxt);
    void (*device_lock)(struct console *con, unsigned long *flags);
    void (*device_unlock)(struct console *con, unsigned long flags);
    atomic_t nbcon_state;
    atomic_long_t nbcon_seq;
    struct nbcon_context    nbcon_device_ctxt;
    atomic_long_t nbcon_prev_seq;
    struct printk_buffers   *pbufs;
    struct task_struct      *kthread;
    struct rcuwait          rcuwait;
    struct irq_work         irq_work;
 };

no cap, that's the whole struct. now let's read every single field together πŸ’…


πŸŽ€ MEMBERS πŸŽ€

  • name β€” the name of the console driver. yes, a whole char name[16], iconic ✨
  • write β€” legacy write callback to output messages (Optional)
  • read β€” read callback for console input (Optional)
  • device β€” the underlying TTY device driver (Optional)
  • unblank β€” callback to unblank the console (Optional)
  • setup β€” callback for initializing the console (Optional)
  • exit β€” callback for teardown of the console (Optional)
  • match β€” callback for matching a console (Optional)
  • flags β€” console flags. see enum cons_flags
  • index β€” console index, e.g. port number
  • cflag β€” TTY control mode flags
  • ispeed β€” TTY input speed
  • ospeed β€” TTY output speed
  • seq β€” sequence number of the next ringbuffer record to print
  • dropped β€” number of unreported dropped ringbuffer records 😭 (rip those messages)
  • data β€” driver private data
  • node β€” hlist node for the console list

πŸ”₯ write_atomic πŸ”₯

NBCON callback to write out text in any context. (Optional)

okay this one is highkey important so read carefully bestie 😀

this callback is called with the console already acquired. however, a higher priority context is allowed to take it over by default.

the callback must call nbcon_enter_unsafe and nbcon_exit_unsafe around any code where the takeover is not safe β€” for example, when manipulating the serial port registers.

nbcon_enter_unsafe will fail if the context has lost the console ownership in the meantime. in this case, the callback is no longer allowed to go forward. it must back out immediately and carefully. the buffer content is also no longer trusted since it no longer belongs to the context. πŸ’€

the callback should allow the takeover whenever it is safe. it increases the chance to see messages when the system is in trouble. if the driver must reacquire ownership in order to finalize or revert hardware changes, nbcon_reacquire_nobuf can be used. however, on reacquire the buffer content is no longer available. a reacquire cannot be used to resume printing. πŸ™ˆ

the callback can be called from any context (including NMI). therefore it must avoid usage of any locking and instead rely on the console ownership for synchronization. like, no locks, periodt.


πŸ’œ write_thread πŸ’œ

NBCON callback to write out text in task context.

this callback must be called only in task context with both device_lock and the nbcon console acquired with NBCON_PRIO_NORMAL.

the same rules for console ownership verification and unsafe sections handling applies as with write_atomic.

the console ownership handling is necessary for synchronization against write_atomic which is synchronized only via the context.

the device_lock provides the primary serialization for operations on the device. it might be as relaxed (mutex)[*] or as tight (disabled preemption and interrupts) as needed. it allows the kthread to operate in the least restrictive mode[**]. πŸ¦‹

[*] standalone nbcon_context_try_acquire is not safe with the preemption enabled, see nbcon_owner_matches. but it can be safe when always called in the preemptive context under the device_lock.
[**] the device_lock makes sure that nbcon_context_try_acquire would never need to spin, which is important especially with PREEMPT_RT.

🌸 device_lock 🌸

NBCON callback to begin synchronization with driver code.

console drivers typically must deal with access to the hardware via user input/output (such as an interactive login shell) and output of kernel messages via printk calls. this callback is called by the printk-subsystem whenever it needs to synchronize with hardware access by the driver. it should be implemented to use whatever synchronization mechanism the driver is using for itself (for example, the port lock for uart serial consoles).

the callback is always called from task context. it may use any synchronization method required by the driver.

IMPORTANT: the callback MUST disable migration. the console driver may be using a synchronization mechanism that already takes care of this (such as spinlocks). otherwise this function must explicitly call migrate_disable.

the flags argument is provided as a convenience to the driver. it will be passed again to device_unlock. it can be ignored if the driver does not need it.


⭐ device_unlock ⭐

NBCON callback to finish synchronization with driver code.

it is the counterpart to device_lock.

this callback is always called from task context. it must appropriately re-enable migration (depending on how device_lock disabled migration).

the flags argument is the value of the same variable that was passed to device_lock.


🧚 the rest of the squad 🧚

  • nbcon_state β€” state for nbcon consoles
  • nbcon_seq β€” sequence number of the next record for nbcon to print
  • nbcon_device_ctxt β€” context available for non-printing operations
  • nbcon_prev_seq β€” seq num the previous nbcon owner was assigned to print
  • pbufs β€” pointer to nbcon private buffer
  • kthread β€” printer kthread for this console
  • rcuwait β€” RCU-safe wait object for kthread waking
  • irq_work β€” defer kthread waking to IRQ work context

πŸ¦‹ SEE ALSO πŸ¦‹

kernel file ./include/linux/console.h, struct consw(9), enum cons_flags(9), struct nbcon_state(9), enum nbcon_prio(9), struct nbcon_context(9), struct nbcon_write_context(9), console_srcu_read_flags(9), console_srcu_write_flags(9), for_each_console_srcu(9), for_each_console(9)

go read those too, iykyk πŸ“š


mwah πŸ’‹ that's the whole page bestie β€” brought to you by ./include/linux, dated October 2026, and yeah it's still called struct console(9) in case you forgot already πŸ˜­πŸ’–

πŸ“¦ where this page comes from