Skip to content

Commit 2a80532

Browse files
committed
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
2 parents 00657bb + 2966bd3 commit 2a80532

File tree

6 files changed

+1288
-78
lines changed

6 files changed

+1288
-78
lines changed

include/linux/console.h

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ static inline int con_debug_leave(void)
156156
* /dev/kmesg which requires a larger output buffer.
157157
* @CON_SUSPENDED: Indicates if a console is suspended. If true, the
158158
* printing callbacks must not be called.
159+
* @CON_NBCON: Console can operate outside of the legacy style console_lock
160+
* constraints.
159161
*/
160162
enum cons_flags {
161163
CON_PRINTBUFFER = BIT(0),
@@ -166,6 +168,111 @@ enum cons_flags {
166168
CON_BRL = BIT(5),
167169
CON_EXTENDED = BIT(6),
168170
CON_SUSPENDED = BIT(7),
171+
CON_NBCON = BIT(8),
172+
};
173+
174+
/**
175+
* struct nbcon_state - console state for nbcon consoles
176+
* @atom: Compound of the state fields for atomic operations
177+
*
178+
* @req_prio: The priority of a handover request
179+
* @prio: The priority of the current owner
180+
* @unsafe: Console is busy in a non takeover region
181+
* @unsafe_takeover: A hostile takeover in an unsafe state happened in the
182+
* past. The console cannot be safe until re-initialized.
183+
* @cpu: The CPU on which the owner runs
184+
*
185+
* To be used for reading and preparing of the value stored in the nbcon
186+
* state variable @console::nbcon_state.
187+
*
188+
* The @prio and @req_prio fields are particularly important to allow
189+
* spin-waiting to timeout and give up without the risk of a waiter being
190+
* assigned the lock after giving up.
191+
*/
192+
struct nbcon_state {
193+
union {
194+
unsigned int atom;
195+
struct {
196+
unsigned int prio : 2;
197+
unsigned int req_prio : 2;
198+
unsigned int unsafe : 1;
199+
unsigned int unsafe_takeover : 1;
200+
unsigned int cpu : 24;
201+
};
202+
};
203+
};
204+
205+
/*
206+
* The nbcon_state struct is used to easily create and interpret values that
207+
* are stored in the @console::nbcon_state variable. Ensure this struct stays
208+
* within the size boundaries of the atomic variable's underlying type in
209+
* order to avoid any accidental truncation.
210+
*/
211+
static_assert(sizeof(struct nbcon_state) <= sizeof(int));
212+
213+
/**
214+
* nbcon_prio - console owner priority for nbcon consoles
215+
* @NBCON_PRIO_NONE: Unused
216+
* @NBCON_PRIO_NORMAL: Normal (non-emergency) usage
217+
* @NBCON_PRIO_EMERGENCY: Emergency output (WARN/OOPS...)
218+
* @NBCON_PRIO_PANIC: Panic output
219+
* @NBCON_PRIO_MAX: The number of priority levels
220+
*
221+
* A higher priority context can takeover the console when it is
222+
* in the safe state. The final attempt to flush consoles in panic()
223+
* can be allowed to do so even in an unsafe state (Hope and pray).
224+
*/
225+
enum nbcon_prio {
226+
NBCON_PRIO_NONE = 0,
227+
NBCON_PRIO_NORMAL,
228+
NBCON_PRIO_EMERGENCY,
229+
NBCON_PRIO_PANIC,
230+
NBCON_PRIO_MAX,
231+
};
232+
233+
struct console;
234+
struct printk_buffers;
235+
236+
/**
237+
* struct nbcon_context - Context for console acquire/release
238+
* @console: The associated console
239+
* @spinwait_max_us: Limit for spin-wait acquire
240+
* @prio: Priority of the context
241+
* @allow_unsafe_takeover: Allow performing takeover even if unsafe. Can
242+
* be used only with NBCON_PRIO_PANIC @prio. It
243+
* might cause a system freeze when the console
244+
* is used later.
245+
* @backlog: Ringbuffer has pending records
246+
* @pbufs: Pointer to the text buffer for this context
247+
* @seq: The sequence number to print for this context
248+
*/
249+
struct nbcon_context {
250+
/* members set by caller */
251+
struct console *console;
252+
unsigned int spinwait_max_us;
253+
enum nbcon_prio prio;
254+
unsigned int allow_unsafe_takeover : 1;
255+
256+
/* members set by emit */
257+
unsigned int backlog : 1;
258+
259+
/* members set by acquire */
260+
struct printk_buffers *pbufs;
261+
u64 seq;
262+
};
263+
264+
/**
265+
* struct nbcon_write_context - Context handed to the nbcon write callbacks
266+
* @ctxt: The core console context
267+
* @outbuf: Pointer to the text buffer for output
268+
* @len: Length to write
269+
* @unsafe_takeover: If a hostile takeover in an unsafe state has occurred
270+
*/
271+
struct nbcon_write_context {
272+
struct nbcon_context __private ctxt;
273+
char *outbuf;
274+
unsigned int len;
275+
bool unsafe_takeover;
169276
};
170277

171278
/**
@@ -187,6 +294,11 @@ enum cons_flags {
187294
* @dropped: Number of unreported dropped ringbuffer records
188295
* @data: Driver private data
189296
* @node: hlist node for the console list
297+
*
298+
* @write_atomic: Write callback for atomic context
299+
* @nbcon_state: State for nbcon consoles
300+
* @nbcon_seq: Sequence number of the next record for nbcon to print
301+
* @pbufs: Pointer to nbcon private buffer
190302
*/
191303
struct console {
192304
char name[16];
@@ -206,6 +318,13 @@ struct console {
206318
unsigned long dropped;
207319
void *data;
208320
struct hlist_node node;
321+
322+
/* nbcon console specific members */
323+
bool (*write_atomic)(struct console *con,
324+
struct nbcon_write_context *wctxt);
325+
atomic_t __private nbcon_state;
326+
atomic_long_t __private nbcon_seq;
327+
struct printk_buffers *pbufs;
209328
};
210329

211330
#ifdef CONFIG_LOCKDEP
@@ -332,6 +451,16 @@ static inline bool console_is_registered(const struct console *con)
332451
lockdep_assert_console_list_lock_held(); \
333452
hlist_for_each_entry(con, &console_list, node)
334453

454+
#ifdef CONFIG_PRINTK
455+
extern bool nbcon_can_proceed(struct nbcon_write_context *wctxt);
456+
extern bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt);
457+
extern bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt);
458+
#else
459+
static inline bool nbcon_can_proceed(struct nbcon_write_context *wctxt) { return false; }
460+
static inline bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt) { return false; }
461+
static inline bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt) { return false; }
462+
#endif
463+
335464
extern int console_set_on_cmdline;
336465
extern struct console *early_console;
337466

kernel/printk/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22
obj-y = printk.o
3-
obj-$(CONFIG_PRINTK) += printk_safe.o
3+
obj-$(CONFIG_PRINTK) += printk_safe.o nbcon.o
44
obj-$(CONFIG_A11Y_BRAILLE_CONSOLE) += braille.o
55
obj-$(CONFIG_PRINTK_INDEX) += index.o
66

kernel/printk/internal.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* internal.h - printk internal definitions
44
*/
55
#include <linux/percpu.h>
6+
#include <linux/console.h>
7+
#include "printk_ringbuffer.h"
68

79
#if defined(CONFIG_PRINTK) && defined(CONFIG_SYSCTL)
810
void __init printk_sysctl_init(void);
@@ -12,6 +14,12 @@ int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write,
1214
#define printk_sysctl_init() do { } while (0)
1315
#endif
1416

17+
#define con_printk(lvl, con, fmt, ...) \
18+
printk(lvl pr_fmt("%s%sconsole [%s%d] " fmt), \
19+
(con->flags & CON_NBCON) ? "" : "legacy ", \
20+
(con->flags & CON_BOOT) ? "boot" : "", \
21+
con->name, con->index, ##__VA_ARGS__)
22+
1523
#ifdef CONFIG_PRINTK
1624

1725
#ifdef CONFIG_PRINTK_CALLER
@@ -35,6 +43,8 @@ enum printk_info_flags {
3543
LOG_CONT = 8, /* text is a fragment of a continuation line */
3644
};
3745

46+
extern struct printk_ringbuffer *prb;
47+
3848
__printf(4, 0)
3949
int vprintk_store(int facility, int level,
4050
const struct dev_printk_info *dev_info,
@@ -61,6 +71,13 @@ void defer_console_output(void);
6171

6272
u16 printk_parse_prefix(const char *text, int *level,
6373
enum printk_info_flags *flags);
74+
75+
u64 nbcon_seq_read(struct console *con);
76+
void nbcon_seq_force(struct console *con, u64 seq);
77+
bool nbcon_alloc(struct console *con);
78+
void nbcon_init(struct console *con);
79+
void nbcon_free(struct console *con);
80+
6481
#else
6582

6683
#define PRINTK_PREFIX_MAX 0
@@ -76,8 +93,16 @@ u16 printk_parse_prefix(const char *text, int *level,
7693
#define printk_safe_exit_irqrestore(flags) local_irq_restore(flags)
7794

7895
static inline bool printk_percpu_data_ready(void) { return false; }
96+
static inline u64 nbcon_seq_read(struct console *con) { return 0; }
97+
static inline void nbcon_seq_force(struct console *con, u64 seq) { }
98+
static inline bool nbcon_alloc(struct console *con) { return false; }
99+
static inline void nbcon_init(struct console *con) { }
100+
static inline void nbcon_free(struct console *con) { }
101+
79102
#endif /* CONFIG_PRINTK */
80103

104+
extern struct printk_buffers printk_shared_pbufs;
105+
81106
/**
82107
* struct printk_buffers - Buffers to read/format/output printk messages.
83108
* @outbuf: After formatting, contains text to output.
@@ -105,3 +130,9 @@ struct printk_message {
105130
};
106131

107132
bool other_cpu_in_panic(void);
133+
bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
134+
bool is_extended, bool may_supress);
135+
136+
#ifdef CONFIG_PRINTK
137+
void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped);
138+
#endif

0 commit comments

Comments
 (0)