Skip to content

Commit 9757acd

Browse files
KAGA-KOKOpmladek
authored andcommitted
printk: nbcon: Allow drivers to mark unsafe regions and check state
For the write_atomic callback, the console driver may have unsafe regions that need to be appropriately marked. Provide functions that accept the nbcon_write_context struct to allow for the driver to enter and exit unsafe regions. Also provide a function for drivers to check if they are still the owner of the console. Co-developed-by: John Ogness <john.ogness@linutronix.de> Signed-off-by: John Ogness <john.ogness@linutronix.de> Signed-off-by: Thomas Gleixner (Intel) <tglx@linutronix.de> Reviewed-by: Petr Mladek <pmladek@suse.com> Signed-off-by: Petr Mladek <pmladek@suse.com> Link: https://lore.kernel.org/r/20230916192007.608398-9-john.ogness@linutronix.de
1 parent 06653d5 commit 9757acd

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed

include/linux/console.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,16 @@ static inline bool console_is_registered(const struct console *con)
451451
lockdep_assert_console_list_lock_held(); \
452452
hlist_for_each_entry(con, &console_list, node)
453453

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+
454464
extern int console_set_on_cmdline;
455465
extern struct console *early_console;
456466

kernel/printk/nbcon.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,41 @@ static bool nbcon_context_can_proceed(struct nbcon_context *ctxt, struct nbcon_s
732732
return false;
733733
}
734734

735+
/**
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+
*/
758+
bool 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+
}
768+
EXPORT_SYMBOL_GPL(nbcon_can_proceed);
769+
735770
#define nbcon_context_enter_unsafe(c) __nbcon_context_update_unsafe(c, true)
736771
#define nbcon_context_exit_unsafe(c) __nbcon_context_update_unsafe(c, false)
737772

@@ -782,6 +817,46 @@ static bool __nbcon_context_update_unsafe(struct nbcon_context *ctxt, bool unsaf
782817
return nbcon_context_can_proceed(ctxt, &cur);
783818
}
784819

820+
/**
821+
* 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+
*/
832+
bool 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+
}
838+
EXPORT_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+
*/
852+
bool 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+
}
858+
EXPORT_SYMBOL_GPL(nbcon_exit_unsafe);
859+
785860
/**
786861
* nbcon_emit_next_record - Emit a record in the acquired context
787862
* @wctxt: The write context that will be handed to the write function

0 commit comments

Comments
 (0)