Skip to content

Commit 2966bd3

Browse files
committed
Merge branch 'rework/nbcon-base' into for-linus
2 parents 86098bc + 98a0465 commit 2966bd3

File tree

5 files changed

+1263
-50
lines changed

5 files changed

+1263
-50
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)