blob: b96077152f49dd2a2dc416444538360e1b4db78b [file] [log] [blame]
Thomas Gleixner6b93bb42023-09-16 21:26:00 +02061// SPDX-License-Identifier: GPL-2.0-only
2// Copyright (C) 2022 Linutronix GmbH, John Ogness
3// Copyright (C) 2022 Intel, Thomas Gleixner
4
5#include <linux/kernel.h>
6#include <linux/console.h>
Thomas Gleixner3a5bb252023-09-16 21:26:01 +02067#include <linux/delay.h>
Thomas Gleixner5634c902023-09-16 21:26:03 +02068#include <linux/slab.h>
Thomas Gleixner6b93bb42023-09-16 21:26:00 +02069#include "internal.h"
10/*
11 * Printk console printing implementation for consoles which does not depend
12 * on the legacy style console_lock mechanism.
Thomas Gleixner3a5bb252023-09-16 21:26:01 +020613 *
14 * The state of the console is maintained in the "nbcon_state" atomic
15 * variable.
16 *
17 * The console is locked when:
18 *
19 * - The 'prio' field contains the priority of the context that owns the
20 * console. Only higher priority contexts are allowed to take over the
21 * lock. A value of 0 (NBCON_PRIO_NONE) means the console is not locked.
22 *
23 * - The 'cpu' field denotes on which CPU the console is locked. It is used
24 * to prevent busy waiting on the same CPU. Also it informs the lock owner
25 * that it has lost the lock in a more complex scenario when the lock was
26 * taken over by a higher priority context, released, and taken on another
27 * CPU with the same priority as the interrupted owner.
28 *
29 * The acquire mechanism uses a few more fields:
30 *
31 * - The 'req_prio' field is used by the handover approach to make the
32 * current owner aware that there is a context with a higher priority
33 * waiting for the friendly handover.
34 *
35 * - The 'unsafe' field allows to take over the console in a safe way in the
36 * middle of emitting a message. The field is set only when accessing some
37 * shared resources or when the console device is manipulated. It can be
38 * cleared, for example, after emitting one character when the console
39 * device is in a consistent state.
40 *
41 * - The 'unsafe_takeover' field is set when a hostile takeover took the
42 * console in an unsafe state. The console will stay in the unsafe state
43 * until re-initialized.
44 *
45 * The acquire mechanism uses three approaches:
46 *
47 * 1) Direct acquire when the console is not owned or is owned by a lower
48 * priority context and is in a safe state.
49 *
50 * 2) Friendly handover mechanism uses a request/grant handshake. It is used
51 * when the current owner has lower priority and the console is in an
52 * unsafe state.
53 *
54 * The requesting context:
55 *
56 * a) Sets its priority into the 'req_prio' field.
57 *
58 * b) Waits (with a timeout) for the owning context to unlock the
59 * console.
60 *
61 * c) Takes the lock and clears the 'req_prio' field.
62 *
63 * The owning context:
64 *
65 * a) Observes the 'req_prio' field set on exit from the unsafe
66 * console state.
67 *
68 * b) Gives up console ownership by clearing the 'prio' field.
69 *
70 * 3) Unsafe hostile takeover allows to take over the lock even when the
71 * console is an unsafe state. It is used only in panic() by the final
72 * attempt to flush consoles in a try and hope mode.
73 *
Thomas Gleixner5634c902023-09-16 21:26:03 +020674 * Note that separate record buffers are used in panic(). As a result,
75 * the messages can be read and formatted without any risk even after
76 * using the hostile takeover in unsafe state.
77 *
Thomas Gleixner3a5bb252023-09-16 21:26:01 +020678 * The release function simply clears the 'prio' field.
79 *
80 * All operations on @console::nbcon_state are atomic cmpxchg based to
81 * handle concurrency.
82 *
83 * The acquire/release functions implement only minimal policies:
84 *
85 * - Preference for higher priority contexts.
86 * - Protection of the panic CPU.
87 *
88 * All other policy decisions must be made at the call sites:
89 *
90 * - What is marked as an unsafe section.
91 * - Whether to spin-wait if there is already an owner and the console is
92 * in an unsafe state.
93 * - Whether to attempt an unsafe hostile takeover.
94 *
95 * The design allows to implement the well known:
96 *
97 * acquire()
98 * output_one_printk_record()
99 * release()
100 *
101 * The output of one printk record might be interrupted with a higher priority
102 * context. The new owner is supposed to reprint the entire interrupted record
103 * from scratch.
Thomas Gleixner6b93bb42023-09-16 21:26:00 +0206104 */
105
106/**
107 * nbcon_state_set - Helper function to set the console state
108 * @con: Console to update
109 * @new: The new state to write
110 *
111 * Only to be used when the console is not yet or no longer visible in the
112 * system. Otherwise use nbcon_state_try_cmpxchg().
113 */
114static inline void nbcon_state_set(struct console *con, struct nbcon_state *new)
115{
116 atomic_set(&ACCESS_PRIVATE(con, nbcon_state), new->atom);
117}
118
119/**
120 * nbcon_state_read - Helper function to read the console state
121 * @con: Console to read
122 * @state: The state to store the result
123 */
124static inline void nbcon_state_read(struct console *con, struct nbcon_state *state)
125{
126 state->atom = atomic_read(&ACCESS_PRIVATE(con, nbcon_state));
127}
128
129/**
130 * nbcon_state_try_cmpxchg() - Helper function for atomic_try_cmpxchg() on console state
131 * @con: Console to update
132 * @cur: Old/expected state
133 * @new: New state
134 *
135 * Return: True on success. False on fail and @cur is updated.
136 */
137static inline bool nbcon_state_try_cmpxchg(struct console *con, struct nbcon_state *cur,
138 struct nbcon_state *new)
139{
140 return atomic_try_cmpxchg(&ACCESS_PRIVATE(con, nbcon_state), &cur->atom, new->atom);
141}
142
Thomas Gleixnerad56ebd2023-09-16 21:26:05 +0206143#ifdef CONFIG_64BIT
144
145#define __seq_to_nbcon_seq(seq) (seq)
146#define __nbcon_seq_to_seq(seq) (seq)
147
148#else /* CONFIG_64BIT */
149
150#define __seq_to_nbcon_seq(seq) ((u32)seq)
151
152static inline u64 __nbcon_seq_to_seq(u32 nbcon_seq)
153{
154 u64 seq;
155 u64 rb_next_seq;
156
157 /*
158 * The provided sequence is only the lower 32 bits of the ringbuffer
159 * sequence. It needs to be expanded to 64bit. Get the next sequence
160 * number from the ringbuffer and fold it.
161 *
162 * Having a 32bit representation in the console is sufficient.
163 * If a console ever gets more than 2^31 records behind
164 * the ringbuffer then this is the least of the problems.
165 *
166 * Also the access to the ring buffer is always safe.
167 */
168 rb_next_seq = prb_next_seq(prb);
169 seq = rb_next_seq - ((u32)rb_next_seq - nbcon_seq);
170
171 return seq;
172}
173
174#endif /* CONFIG_64BIT */
175
176/**
177 * nbcon_seq_read - Read the current console sequence
178 * @con: Console to read the sequence of
179 *
180 * Return: Sequence number of the next record to print on @con.
181 */
182u64 nbcon_seq_read(struct console *con)
183{
184 unsigned long nbcon_seq = atomic_long_read(&ACCESS_PRIVATE(con, nbcon_seq));
185
186 return __nbcon_seq_to_seq(nbcon_seq);
187}
188
189/**
190 * nbcon_seq_force - Force console sequence to a specific value
191 * @con: Console to work on
192 * @seq: Sequence number value to set
193 *
194 * Only to be used during init (before registration) or in extreme situations
195 * (such as panic with CONSOLE_REPLAY_ALL).
196 */
197void nbcon_seq_force(struct console *con, u64 seq)
198{
199 /*
200 * If the specified record no longer exists, the oldest available record
201 * is chosen. This is especially important on 32bit systems because only
202 * the lower 32 bits of the sequence number are stored. The upper 32 bits
203 * are derived from the sequence numbers available in the ringbuffer.
204 */
205 u64 valid_seq = max_t(u64, seq, prb_first_valid_seq(prb));
206
207 atomic_long_set(&ACCESS_PRIVATE(con, nbcon_seq), __seq_to_nbcon_seq(valid_seq));
208
209 /* Clear con->seq since nbcon consoles use con->nbcon_seq instead. */
210 con->seq = 0;
211}
212
213/**
214 * nbcon_seq_try_update - Try to update the console sequence number
215 * @ctxt: Pointer to an acquire context that contains
216 * all information about the acquire mode
217 * @new_seq: The new sequence number to set
218 *
219 * @ctxt->seq is updated to the new value of @con::nbcon_seq (expanded to
220 * the 64bit value). This could be a different value than @new_seq if
221 * nbcon_seq_force() was used or the current context no longer owns the
222 * console. In the later case, it will stop printing anyway.
223 */
Thomas Gleixnerad56ebd2023-09-16 21:26:05 +0206224static void nbcon_seq_try_update(struct nbcon_context *ctxt, u64 new_seq)
225{
226 unsigned long nbcon_seq = __seq_to_nbcon_seq(ctxt->seq);
227 struct console *con = ctxt->console;
228
229 if (atomic_long_try_cmpxchg(&ACCESS_PRIVATE(con, nbcon_seq), &nbcon_seq,
230 __seq_to_nbcon_seq(new_seq))) {
231 ctxt->seq = new_seq;
232 } else {
233 ctxt->seq = nbcon_seq_read(con);
234 }
235}
236
Thomas Gleixner6b93bb42023-09-16 21:26:00 +0206237/**
Thomas Gleixner3a5bb252023-09-16 21:26:01 +0206238 * nbcon_context_try_acquire_direct - Try to acquire directly
239 * @ctxt: The context of the caller
240 * @cur: The current console state
241 *
242 * Acquire the console when it is released. Also acquire the console when
243 * the current owner has a lower priority and the console is in a safe state.
244 *
245 * Return: 0 on success. Otherwise, an error code on failure. Also @cur
246 * is updated to the latest state when failed to modify it.
247 *
248 * Errors:
249 *
250 * -EPERM: A panic is in progress and this is not the panic CPU.
251 * Or the current owner or waiter has the same or higher
252 * priority. No acquire method can be successful in
253 * this case.
254 *
255 * -EBUSY: The current owner has a lower priority but the console
256 * in an unsafe state. The caller should try using
257 * the handover acquire method.
258 */
259static int nbcon_context_try_acquire_direct(struct nbcon_context *ctxt,
260 struct nbcon_state *cur)
261{
262 unsigned int cpu = smp_processor_id();
263 struct console *con = ctxt->console;
264 struct nbcon_state new;
265
266 do {
267 if (other_cpu_in_panic())
268 return -EPERM;
269
270 if (ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio)
271 return -EPERM;
272
273 if (cur->unsafe)
274 return -EBUSY;
275
276 /*
277 * The console should never be safe for a direct acquire
278 * if an unsafe hostile takeover has ever happened.
279 */
280 WARN_ON_ONCE(cur->unsafe_takeover);
281
282 new.atom = cur->atom;
283 new.prio = ctxt->prio;
284 new.req_prio = NBCON_PRIO_NONE;
285 new.unsafe = cur->unsafe_takeover;
286 new.cpu = cpu;
287
288 } while (!nbcon_state_try_cmpxchg(con, cur, &new));
289
290 return 0;
291}
292
293static bool nbcon_waiter_matches(struct nbcon_state *cur, int expected_prio)
294{
295 /*
296 * The request context is well defined by the @req_prio because:
297 *
298 * - Only a context with a higher priority can take over the request.
299 * - There are only three priorities.
300 * - Only one CPU is allowed to request PANIC priority.
301 * - Lower priorities are ignored during panic() until reboot.
302 *
303 * As a result, the following scenario is *not* possible:
304 *
305 * 1. Another context with a higher priority directly takes ownership.
306 * 2. The higher priority context releases the ownership.
307 * 3. A lower priority context takes the ownership.
308 * 4. Another context with the same priority as this context
309 * creates a request and starts waiting.
310 */
311
312 return (cur->req_prio == expected_prio);
313}
314
315/**
316 * nbcon_context_try_acquire_requested - Try to acquire after having
317 * requested a handover
318 * @ctxt: The context of the caller
319 * @cur: The current console state
320 *
321 * This is a helper function for nbcon_context_try_acquire_handover().
322 * It is called when the console is in an unsafe state. The current
323 * owner will release the console on exit from the unsafe region.
324 *
325 * Return: 0 on success and @cur is updated to the new console state.
326 * Otherwise an error code on failure.
327 *
328 * Errors:
329 *
330 * -EPERM: A panic is in progress and this is not the panic CPU
331 * or this context is no longer the waiter.
332 *
333 * -EBUSY: The console is still locked. The caller should
334 * continue waiting.
335 *
336 * Note: The caller must still remove the request when an error has occurred
337 * except when this context is no longer the waiter.
338 */
339static int nbcon_context_try_acquire_requested(struct nbcon_context *ctxt,
340 struct nbcon_state *cur)
341{
342 unsigned int cpu = smp_processor_id();
343 struct console *con = ctxt->console;
344 struct nbcon_state new;
345
346 /* Note that the caller must still remove the request! */
347 if (other_cpu_in_panic())
348 return -EPERM;
349
350 /*
351 * Note that the waiter will also change if there was an unsafe
352 * hostile takeover.
353 */
354 if (!nbcon_waiter_matches(cur, ctxt->prio))
355 return -EPERM;
356
357 /* If still locked, caller should continue waiting. */
358 if (cur->prio != NBCON_PRIO_NONE)
359 return -EBUSY;
360
361 /*
362 * The previous owner should have never released ownership
363 * in an unsafe region.
364 */
365 WARN_ON_ONCE(cur->unsafe);
366
367 new.atom = cur->atom;
368 new.prio = ctxt->prio;
369 new.req_prio = NBCON_PRIO_NONE;
370 new.unsafe = cur->unsafe_takeover;
371 new.cpu = cpu;
372
373 if (!nbcon_state_try_cmpxchg(con, cur, &new)) {
374 /*
375 * The acquire could fail only when it has been taken
376 * over by a higher priority context.
377 */
378 WARN_ON_ONCE(nbcon_waiter_matches(cur, ctxt->prio));
379 return -EPERM;
380 }
381
382 /* Handover success. This context now owns the console. */
383 return 0;
384}
385
386/**
387 * nbcon_context_try_acquire_handover - Try to acquire via handover
388 * @ctxt: The context of the caller
389 * @cur: The current console state
390 *
391 * The function must be called only when the context has higher priority
392 * than the current owner and the console is in an unsafe state.
393 * It is the case when nbcon_context_try_acquire_direct() returns -EBUSY.
394 *
395 * The function sets "req_prio" field to make the current owner aware of
396 * the request. Then it waits until the current owner releases the console,
397 * or an even higher context takes over the request, or timeout expires.
398 *
399 * The current owner checks the "req_prio" field on exit from the unsafe
400 * region and releases the console. It does not touch the "req_prio" field
401 * so that the console stays reserved for the waiter.
402 *
403 * Return: 0 on success. Otherwise, an error code on failure. Also @cur
404 * is updated to the latest state when failed to modify it.
405 *
406 * Errors:
407 *
408 * -EPERM: A panic is in progress and this is not the panic CPU.
409 * Or a higher priority context has taken over the
410 * console or the handover request.
411 *
412 * -EBUSY: The current owner is on the same CPU so that the hand
413 * shake could not work. Or the current owner is not
414 * willing to wait (zero timeout). Or the console does
415 * not enter the safe state before timeout passed. The
416 * caller might still use the unsafe hostile takeover
417 * when allowed.
418 *
419 * -EAGAIN: @cur has changed when creating the handover request.
420 * The caller should retry with direct acquire.
421 */
422static int nbcon_context_try_acquire_handover(struct nbcon_context *ctxt,
423 struct nbcon_state *cur)
424{
425 unsigned int cpu = smp_processor_id();
426 struct console *con = ctxt->console;
427 struct nbcon_state new;
428 int timeout;
429 int request_err = -EBUSY;
430
431 /*
432 * Check that the handover is called when the direct acquire failed
433 * with -EBUSY.
434 */
435 WARN_ON_ONCE(ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio);
436 WARN_ON_ONCE(!cur->unsafe);
437
438 /* Handover is not possible on the same CPU. */
439 if (cur->cpu == cpu)
440 return -EBUSY;
441
442 /*
443 * Console stays unsafe after an unsafe takeover until re-initialized.
444 * Waiting is not going to help in this case.
445 */
446 if (cur->unsafe_takeover)
447 return -EBUSY;
448
449 /* Is the caller willing to wait? */
450 if (ctxt->spinwait_max_us == 0)
451 return -EBUSY;
452
453 /*
454 * Setup a request for the handover. The caller should try to acquire
455 * the console directly when the current state has been modified.
456 */
457 new.atom = cur->atom;
458 new.req_prio = ctxt->prio;
459 if (!nbcon_state_try_cmpxchg(con, cur, &new))
460 return -EAGAIN;
461
462 cur->atom = new.atom;
463
464 /* Wait until there is no owner and then acquire the console. */
465 for (timeout = ctxt->spinwait_max_us; timeout >= 0; timeout--) {
466 /* On successful acquire, this request is cleared. */
467 request_err = nbcon_context_try_acquire_requested(ctxt, cur);
468 if (!request_err)
469 return 0;
470
471 /*
472 * If the acquire should be aborted, it must be ensured
473 * that the request is removed before returning to caller.
474 */
475 if (request_err == -EPERM)
476 break;
477
478 udelay(1);
479
480 /* Re-read the state because some time has passed. */
481 nbcon_state_read(con, cur);
482 }
483
484 /* Timed out or aborted. Carefully remove handover request. */
485 do {
486 /*
487 * No need to remove request if there is a new waiter. This
488 * can only happen if a higher priority context has taken over
489 * the console or the handover request.
490 */
491 if (!nbcon_waiter_matches(cur, ctxt->prio))
492 return -EPERM;
493
494 /* Unset request for handover. */
495 new.atom = cur->atom;
496 new.req_prio = NBCON_PRIO_NONE;
497 if (nbcon_state_try_cmpxchg(con, cur, &new)) {
498 /*
499 * Request successfully unset. Report failure of
500 * acquiring via handover.
501 */
502 cur->atom = new.atom;
503 return request_err;
504 }
505
506 /*
507 * Unable to remove request. Try to acquire in case
508 * the owner has released the lock.
509 */
510 } while (nbcon_context_try_acquire_requested(ctxt, cur));
511
512 /* Lucky timing. The acquire succeeded while removing the request. */
513 return 0;
514}
515
516/**
517 * nbcon_context_try_acquire_hostile - Acquire via unsafe hostile takeover
518 * @ctxt: The context of the caller
519 * @cur: The current console state
520 *
521 * Acquire the console even in the unsafe state.
522 *
523 * It can be permitted by setting the 'allow_unsafe_takeover' field only
524 * by the final attempt to flush messages in panic().
525 *
526 * Return: 0 on success. -EPERM when not allowed by the context.
527 */
528static int nbcon_context_try_acquire_hostile(struct nbcon_context *ctxt,
529 struct nbcon_state *cur)
530{
531 unsigned int cpu = smp_processor_id();
532 struct console *con = ctxt->console;
533 struct nbcon_state new;
534
535 if (!ctxt->allow_unsafe_takeover)
536 return -EPERM;
537
538 /* Ensure caller is allowed to perform unsafe hostile takeovers. */
539 if (WARN_ON_ONCE(ctxt->prio != NBCON_PRIO_PANIC))
540 return -EPERM;
541
542 /*
543 * Check that try_acquire_direct() and try_acquire_handover() returned
544 * -EBUSY in the right situation.
545 */
546 WARN_ON_ONCE(ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio);
547 WARN_ON_ONCE(cur->unsafe != true);
548
549 do {
550 new.atom = cur->atom;
551 new.cpu = cpu;
552 new.prio = ctxt->prio;
553 new.unsafe |= cur->unsafe_takeover;
554 new.unsafe_takeover |= cur->unsafe;
555
556 } while (!nbcon_state_try_cmpxchg(con, cur, &new));
557
558 return 0;
559}
560
Thomas Gleixner5634c902023-09-16 21:26:03 +0206561static struct printk_buffers panic_nbcon_pbufs;
562
Thomas Gleixner3a5bb252023-09-16 21:26:01 +0206563/**
564 * nbcon_context_try_acquire - Try to acquire nbcon console
565 * @ctxt: The context of the caller
566 *
567 * Return: True if the console was acquired. False otherwise.
568 *
569 * If the caller allowed an unsafe hostile takeover, on success the
570 * caller should check the current console state to see if it is
571 * in an unsafe state. Otherwise, on success the caller may assume
572 * the console is not in an unsafe state.
573 */
574__maybe_unused
575static bool nbcon_context_try_acquire(struct nbcon_context *ctxt)
576{
Thomas Gleixner5634c902023-09-16 21:26:03 +0206577 unsigned int cpu = smp_processor_id();
Thomas Gleixner3a5bb252023-09-16 21:26:01 +0206578 struct console *con = ctxt->console;
579 struct nbcon_state cur;
580 int err;
581
582 nbcon_state_read(con, &cur);
583try_again:
584 err = nbcon_context_try_acquire_direct(ctxt, &cur);
585 if (err != -EBUSY)
586 goto out;
587
588 err = nbcon_context_try_acquire_handover(ctxt, &cur);
589 if (err == -EAGAIN)
590 goto try_again;
591 if (err != -EBUSY)
592 goto out;
593
594 err = nbcon_context_try_acquire_hostile(ctxt, &cur);
595out:
Thomas Gleixner5634c902023-09-16 21:26:03 +0206596 if (err)
597 return false;
598
599 /* Acquire succeeded. */
600
601 /* Assign the appropriate buffer for this context. */
602 if (atomic_read(&panic_cpu) == cpu)
603 ctxt->pbufs = &panic_nbcon_pbufs;
604 else
605 ctxt->pbufs = con->pbufs;
606
Thomas Gleixnerad56ebd2023-09-16 21:26:05 +0206607 /* Set the record sequence for this context to print. */
608 ctxt->seq = nbcon_seq_read(ctxt->console);
609
Thomas Gleixner5634c902023-09-16 21:26:03 +0206610 return true;
Thomas Gleixner3a5bb252023-09-16 21:26:01 +0206611}
612
613static bool nbcon_owner_matches(struct nbcon_state *cur, int expected_cpu,
614 int expected_prio)
615{
616 /*
617 * Since consoles can only be acquired by higher priorities,
618 * owning contexts are uniquely identified by @prio. However,
619 * since contexts can unexpectedly lose ownership, it is
620 * possible that later another owner appears with the same
621 * priority. For this reason @cpu is also needed.
622 */
623
624 if (cur->prio != expected_prio)
625 return false;
626
627 if (cur->cpu != expected_cpu)
628 return false;
629
630 return true;
631}
632
633/**
634 * nbcon_context_release - Release the console
635 * @ctxt: The nbcon context from nbcon_context_try_acquire()
636 */
Thomas Gleixner3a5bb252023-09-16 21:26:01 +0206637static void nbcon_context_release(struct nbcon_context *ctxt)
638{
639 unsigned int cpu = smp_processor_id();
640 struct console *con = ctxt->console;
641 struct nbcon_state cur;
642 struct nbcon_state new;
643
644 nbcon_state_read(con, &cur);
645
646 do {
647 if (!nbcon_owner_matches(&cur, cpu, ctxt->prio))
Thomas Gleixner5634c902023-09-16 21:26:03 +0206648 break;
Thomas Gleixner3a5bb252023-09-16 21:26:01 +0206649
650 new.atom = cur.atom;
651 new.prio = NBCON_PRIO_NONE;
652
653 /*
654 * If @unsafe_takeover is set, it is kept set so that
655 * the state remains permanently unsafe.
656 */
657 new.unsafe |= cur.unsafe_takeover;
658
659 } while (!nbcon_state_try_cmpxchg(con, &cur, &new));
Thomas Gleixner5634c902023-09-16 21:26:03 +0206660
661 ctxt->pbufs = NULL;
662}
663
664/**
Thomas Gleixner4b08d9e2023-09-16 21:26:04 +0206665 * nbcon_context_can_proceed - Check whether ownership can proceed
666 * @ctxt: The nbcon context from nbcon_context_try_acquire()
667 * @cur: The current console state
668 *
669 * Return: True if this context still owns the console. False if
670 * ownership was handed over or taken.
671 *
672 * Must be invoked when entering the unsafe state to make sure that it still
673 * owns the lock. Also must be invoked when exiting the unsafe context
674 * to eventually free the lock for a higher priority context which asked
675 * for the friendly handover.
676 *
677 * It can be called inside an unsafe section when the console is just
678 * temporary in safe state instead of exiting and entering the unsafe
679 * state.
680 *
681 * Also it can be called in the safe context before doing an expensive
682 * safe operation. It does not make sense to do the operation when
683 * a higher priority context took the lock.
684 *
685 * When this function returns false then the calling context no longer owns
686 * the console and is no longer allowed to go forward. In this case it must
687 * back out immediately and carefully. The buffer content is also no longer
688 * trusted since it no longer belongs to the calling context.
689 */
690static bool nbcon_context_can_proceed(struct nbcon_context *ctxt, struct nbcon_state *cur)
691{
692 unsigned int cpu = smp_processor_id();
693
694 /* Make sure this context still owns the console. */
695 if (!nbcon_owner_matches(cur, cpu, ctxt->prio))
696 return false;
697
698 /* The console owner can proceed if there is no waiter. */
699 if (cur->req_prio == NBCON_PRIO_NONE)
700 return true;
701
702 /*
703 * A console owner within an unsafe region is always allowed to
704 * proceed, even if there are waiters. It can perform a handover
705 * when exiting the unsafe region. Otherwise the waiter will
706 * need to perform an unsafe hostile takeover.
707 */
708 if (cur->unsafe)
709 return true;
710
711 /* Waiters always have higher priorities than owners. */
712 WARN_ON_ONCE(cur->req_prio <= cur->prio);
713
714 /*
715 * Having a safe point for take over and eventually a few
716 * duplicated characters or a full line is way better than a
717 * hostile takeover. Post processing can take care of the garbage.
718 * Release and hand over.
719 */
720 nbcon_context_release(ctxt);
721
722 /*
723 * It is not clear whether the waiter really took over ownership. The
724 * outermost callsite must make the final decision whether console
725 * ownership is needed for it to proceed. If yes, it must reacquire
726 * ownership (possibly hostile) before carefully proceeding.
727 *
728 * The calling context no longer owns the console so go back all the
729 * way instead of trying to implement reacquire heuristics in tons of
730 * places.
731 */
732 return false;
733}
734
Thomas Gleixner9757acd2023-09-16 21:26:07 +0206735/**
736 * nbcon_can_proceed - Check whether ownership can proceed
737 * @wctxt: The write context that was handed to the write function
738 *
739 * Return: True if this context still owns the console. False if
740 * ownership was handed over or taken.
741 *
742 * It is used in nbcon_enter_unsafe() to make sure that it still owns the
743 * lock. Also it is used in nbcon_exit_unsafe() to eventually free the lock
744 * for a higher priority context which asked for the friendly handover.
745 *
746 * It can be called inside an unsafe section when the console is just
747 * temporary in safe state instead of exiting and entering the unsafe state.
748 *
749 * Also it can be called in the safe context before doing an expensive safe
750 * operation. It does not make sense to do the operation when a higher
751 * priority context took the lock.
752 *
753 * When this function returns false then the calling context no longer owns
754 * the console and is no longer allowed to go forward. In this case it must
755 * back out immediately and carefully. The buffer content is also no longer
756 * trusted since it no longer belongs to the calling context.
757 */
758bool nbcon_can_proceed(struct nbcon_write_context *wctxt)
759{
760 struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
761 struct console *con = ctxt->console;
762 struct nbcon_state cur;
763
764 nbcon_state_read(con, &cur);
765
766 return nbcon_context_can_proceed(ctxt, &cur);
767}
768EXPORT_SYMBOL_GPL(nbcon_can_proceed);
769
Thomas Gleixner4b08d9e2023-09-16 21:26:04 +0206770#define nbcon_context_enter_unsafe(c) __nbcon_context_update_unsafe(c, true)
771#define nbcon_context_exit_unsafe(c) __nbcon_context_update_unsafe(c, false)
772
773/**
774 * __nbcon_context_update_unsafe - Update the unsafe bit in @con->nbcon_state
775 * @ctxt: The nbcon context from nbcon_context_try_acquire()
776 * @unsafe: The new value for the unsafe bit
777 *
778 * Return: True if the unsafe state was updated and this context still
779 * owns the console. Otherwise false if ownership was handed
780 * over or taken.
781 *
782 * This function allows console owners to modify the unsafe status of the
783 * console.
784 *
785 * When this function returns false then the calling context no longer owns
786 * the console and is no longer allowed to go forward. In this case it must
787 * back out immediately and carefully. The buffer content is also no longer
788 * trusted since it no longer belongs to the calling context.
789 *
790 * Internal helper to avoid duplicated code.
791 */
Thomas Gleixner4b08d9e2023-09-16 21:26:04 +0206792static bool __nbcon_context_update_unsafe(struct nbcon_context *ctxt, bool unsafe)
793{
794 struct console *con = ctxt->console;
795 struct nbcon_state cur;
796 struct nbcon_state new;
797
798 nbcon_state_read(con, &cur);
799
800 do {
801 /*
802 * The unsafe bit must not be cleared if an
803 * unsafe hostile takeover has occurred.
804 */
805 if (!unsafe && cur.unsafe_takeover)
806 goto out;
807
808 if (!nbcon_context_can_proceed(ctxt, &cur))
809 return false;
810
811 new.atom = cur.atom;
812 new.unsafe = unsafe;
813 } while (!nbcon_state_try_cmpxchg(con, &cur, &new));
814
815 cur.atom = new.atom;
816out:
817 return nbcon_context_can_proceed(ctxt, &cur);
818}
819
820/**
Thomas Gleixner9757acd2023-09-16 21:26:07 +0206821 * nbcon_enter_unsafe - Enter an unsafe region in the driver
822 * @wctxt: The write context that was handed to the write function
823 *
824 * Return: True if this context still owns the console. False if
825 * ownership was handed over or taken.
826 *
827 * When this function returns false then the calling context no longer owns
828 * the console and is no longer allowed to go forward. In this case it must
829 * back out immediately and carefully. The buffer content is also no longer
830 * trusted since it no longer belongs to the calling context.
831 */
832bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt)
833{
834 struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
835
836 return nbcon_context_enter_unsafe(ctxt);
837}
838EXPORT_SYMBOL_GPL(nbcon_enter_unsafe);
839
840/**
841 * nbcon_exit_unsafe - Exit an unsafe region in the driver
842 * @wctxt: The write context that was handed to the write function
843 *
844 * Return: True if this context still owns the console. False if
845 * ownership was handed over or taken.
846 *
847 * When this function returns false then the calling context no longer owns
848 * the console and is no longer allowed to go forward. In this case it must
849 * back out immediately and carefully. The buffer content is also no longer
850 * trusted since it no longer belongs to the calling context.
851 */
852bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt)
853{
854 struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
855
856 return nbcon_context_exit_unsafe(ctxt);
857}
858EXPORT_SYMBOL_GPL(nbcon_exit_unsafe);
859
860/**
Thomas Gleixner06653d52023-09-16 21:26:06 +0206861 * nbcon_emit_next_record - Emit a record in the acquired context
862 * @wctxt: The write context that will be handed to the write function
863 *
864 * Return: True if this context still owns the console. False if
865 * ownership was handed over or taken.
866 *
867 * When this function returns false then the calling context no longer owns
868 * the console and is no longer allowed to go forward. In this case it must
869 * back out immediately and carefully. The buffer content is also no longer
870 * trusted since it no longer belongs to the calling context. If the caller
871 * wants to do more it must reacquire the console first.
872 *
873 * When true is returned, @wctxt->ctxt.backlog indicates whether there are
874 * still records pending in the ringbuffer,
875 */
876__maybe_unused
877static bool nbcon_emit_next_record(struct nbcon_write_context *wctxt)
878{
879 struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
880 struct console *con = ctxt->console;
881 bool is_extended = console_srcu_read_flags(con) & CON_EXTENDED;
882 struct printk_message pmsg = {
883 .pbufs = ctxt->pbufs,
884 };
885 unsigned long con_dropped;
886 struct nbcon_state cur;
887 unsigned long dropped;
888 bool done;
889
890 /*
891 * The printk buffers are filled within an unsafe section. This
892 * prevents NBCON_PRIO_NORMAL and NBCON_PRIO_EMERGENCY from
893 * clobbering each other.
894 */
895
896 if (!nbcon_context_enter_unsafe(ctxt))
897 return false;
898
899 ctxt->backlog = printk_get_next_message(&pmsg, ctxt->seq, is_extended, true);
900 if (!ctxt->backlog)
901 return nbcon_context_exit_unsafe(ctxt);
902
903 /*
904 * @con->dropped is not protected in case of an unsafe hostile
905 * takeover. In that situation the update can be racy so
906 * annotate it accordingly.
907 */
908 con_dropped = data_race(READ_ONCE(con->dropped));
909
910 dropped = con_dropped + pmsg.dropped;
911 if (dropped && !is_extended)
912 console_prepend_dropped(&pmsg, dropped);
913
914 if (!nbcon_context_exit_unsafe(ctxt))
915 return false;
916
917 /* For skipped records just update seq/dropped in @con. */
918 if (pmsg.outbuf_len == 0)
919 goto update_con;
920
921 /* Initialize the write context for driver callbacks. */
922 wctxt->outbuf = &pmsg.pbufs->outbuf[0];
923 wctxt->len = pmsg.outbuf_len;
924 nbcon_state_read(con, &cur);
925 wctxt->unsafe_takeover = cur.unsafe_takeover;
926
927 if (con->write_atomic) {
928 done = con->write_atomic(con, wctxt);
929 } else {
930 nbcon_context_release(ctxt);
931 WARN_ON_ONCE(1);
932 done = false;
933 }
934
935 /* If not done, the emit was aborted. */
936 if (!done)
937 return false;
938
939 /*
940 * Since any dropped message was successfully output, reset the
941 * dropped count for the console.
942 */
943 dropped = 0;
944update_con:
945 /*
946 * The dropped count and the sequence number are updated within an
947 * unsafe section. This limits update races to the panic context and
948 * allows the panic context to win.
949 */
950
951 if (!nbcon_context_enter_unsafe(ctxt))
952 return false;
953
954 if (dropped != con_dropped) {
955 /* Counterpart to the READ_ONCE() above. */
956 WRITE_ONCE(con->dropped, dropped);
957 }
958
959 nbcon_seq_try_update(ctxt, pmsg.seq + 1);
960
961 return nbcon_context_exit_unsafe(ctxt);
962}
963
964/**
Thomas Gleixner5634c902023-09-16 21:26:03 +0206965 * nbcon_alloc - Allocate buffers needed by the nbcon console
966 * @con: Console to allocate buffers for
967 *
968 * Return: True on success. False otherwise and the console cannot
969 * be used.
970 *
971 * This is not part of nbcon_init() because buffer allocation must
972 * be performed earlier in the console registration process.
973 */
974bool nbcon_alloc(struct console *con)
975{
976 if (con->flags & CON_BOOT) {
977 /*
978 * Boot console printing is synchronized with legacy console
979 * printing, so boot consoles can share the same global printk
980 * buffers.
981 */
982 con->pbufs = &printk_shared_pbufs;
983 } else {
984 con->pbufs = kmalloc(sizeof(*con->pbufs), GFP_KERNEL);
985 if (!con->pbufs) {
986 con_printk(KERN_ERR, con, "failed to allocate printing buffer\n");
987 return false;
988 }
989 }
990
991 return true;
Thomas Gleixner3a5bb252023-09-16 21:26:01 +0206992}
993
994/**
Thomas Gleixner6b93bb42023-09-16 21:26:00 +0206995 * nbcon_init - Initialize the nbcon console specific data
996 * @con: Console to initialize
Thomas Gleixner5634c902023-09-16 21:26:03 +0206997 *
998 * nbcon_alloc() *must* be called and succeed before this function
999 * is called.
Thomas Gleixnerad56ebd2023-09-16 21:26:05 +02061000 *
1001 * This function expects that the legacy @con->seq has been set.
Thomas Gleixner6b93bb42023-09-16 21:26:00 +02061002 */
1003void nbcon_init(struct console *con)
1004{
1005 struct nbcon_state state = { };
1006
Thomas Gleixner5634c902023-09-16 21:26:03 +02061007 /* nbcon_alloc() must have been called and successful! */
1008 BUG_ON(!con->pbufs);
1009
Thomas Gleixnerad56ebd2023-09-16 21:26:05 +02061010 nbcon_seq_force(con, con->seq);
Thomas Gleixner6b93bb42023-09-16 21:26:00 +02061011 nbcon_state_set(con, &state);
1012}
1013
1014/**
Thomas Gleixner5634c902023-09-16 21:26:03 +02061015 * nbcon_free - Free and cleanup the nbcon console specific data
1016 * @con: Console to free/cleanup nbcon data
Thomas Gleixner6b93bb42023-09-16 21:26:00 +02061017 */
Thomas Gleixner5634c902023-09-16 21:26:03 +02061018void nbcon_free(struct console *con)
Thomas Gleixner6b93bb42023-09-16 21:26:00 +02061019{
1020 struct nbcon_state state = { };
1021
1022 nbcon_state_set(con, &state);
Thomas Gleixner5634c902023-09-16 21:26:03 +02061023
1024 /* Boot consoles share global printk buffers. */
1025 if (!(con->flags & CON_BOOT))
1026 kfree(con->pbufs);
1027
1028 con->pbufs = NULL;
Thomas Gleixner6b93bb42023-09-16 21:26:00 +02061029}