@@ -156,6 +156,8 @@ static inline int con_debug_leave(void)
156
156
* /dev/kmesg which requires a larger output buffer.
157
157
* @CON_SUSPENDED: Indicates if a console is suspended. If true, the
158
158
* printing callbacks must not be called.
159
+ * @CON_NBCON: Console can operate outside of the legacy style console_lock
160
+ * constraints.
159
161
*/
160
162
enum cons_flags {
161
163
CON_PRINTBUFFER = BIT (0 ),
@@ -166,6 +168,111 @@ enum cons_flags {
166
168
CON_BRL = BIT (5 ),
167
169
CON_EXTENDED = BIT (6 ),
168
170
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 ;
169
276
};
170
277
171
278
/**
@@ -187,6 +294,11 @@ enum cons_flags {
187
294
* @dropped: Number of unreported dropped ringbuffer records
188
295
* @data: Driver private data
189
296
* @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
190
302
*/
191
303
struct console {
192
304
char name [16 ];
@@ -206,6 +318,13 @@ struct console {
206
318
unsigned long dropped ;
207
319
void * data ;
208
320
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 ;
209
328
};
210
329
211
330
#ifdef CONFIG_LOCKDEP
@@ -332,6 +451,16 @@ static inline bool console_is_registered(const struct console *con)
332
451
lockdep_assert_console_list_lock_held(); \
333
452
hlist_for_each_entry(con, &console_list, node)
334
453
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
+
335
464
extern int console_set_on_cmdline ;
336
465
extern struct console * early_console ;
337
466
0 commit comments