Skip to content

Commit 3a5bb25

Browse files
KAGA-KOKOpmladek
authored andcommitted
printk: nbcon: Add acquire/release logic
Add per console acquire/release functionality. The state of the console is maintained in the "nbcon_state" atomic variable. The console is locked when: - The 'prio' field contains the priority of the context that owns the console. Only higher priority contexts are allowed to take over the lock. A value of 0 (NBCON_PRIO_NONE) means the console is not locked. - The 'cpu' field denotes on which CPU the console is locked. It is used to prevent busy waiting on the same CPU. Also it informs the lock owner that it has lost the lock in a more complex scenario when the lock was taken over by a higher priority context, released, and taken on another CPU with the same priority as the interrupted owner. The acquire mechanism uses a few more fields: - The 'req_prio' field is used by the handover approach to make the current owner aware that there is a context with a higher priority waiting for the friendly handover. - The 'unsafe' field allows to take over the console in a safe way in the middle of emitting a message. The field is set only when accessing some shared resources or when the console device is manipulated. It can be cleared, for example, after emitting one character when the console device is in a consistent state. - The 'unsafe_takeover' field is set when a hostile takeover took the console in an unsafe state. The console will stay in the unsafe state until re-initialized. The acquire mechanism uses three approaches: 1) Direct acquire when the console is not owned or is owned by a lower priority context and is in a safe state. 2) Friendly handover mechanism uses a request/grant handshake. It is used when the current owner has lower priority and the console is in an unsafe state. The requesting context: a) Sets its priority into the 'req_prio' field. b) Waits (with a timeout) for the owning context to unlock the console. c) Takes the lock and clears the 'req_prio' field. The owning context: a) Observes the 'req_prio' field set on exit from the unsafe console state. b) Gives up console ownership by clearing the 'prio' field. 3) Unsafe hostile takeover allows to take over the lock even when the console is an unsafe state. It is used only in panic() by the final attempt to flush consoles in a try and hope mode. Note that separate record buffers are used in panic(). As a result, the messages can be read and formatted without any risk even after using the hostile takeover in unsafe state. The release function simply clears the 'prio' field. All operations on @Console::nbcon_state are atomic cmpxchg based to handle concurrency. The acquire/release functions implement only minimal policies: - Preference for higher priority contexts. - Protection of the panic CPU. All other policy decisions must be made at the call sites: - What is marked as an unsafe section. - Whether to spin-wait if there is already an owner and the console is in an unsafe state. - Whether to attempt an unsafe hostile takeover. The design allows to implement the well known: acquire() output_one_printk_record() release() The output of one printk record might be interrupted with a higher priority context. The new owner is supposed to reprint the entire interrupted record from scratch. Co-developed-by: John Ogness <[email protected]> Signed-off-by: John Ogness <[email protected]> Signed-off-by: Thomas Gleixner (Intel) <[email protected]> Signed-off-by: Petr Mladek <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 6b93bb4 commit 3a5bb25

File tree

2 files changed

+553
-0
lines changed

2 files changed

+553
-0
lines changed

include/linux/console.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,13 +175,29 @@ enum cons_flags {
175175
* struct nbcon_state - console state for nbcon consoles
176176
* @atom: Compound of the state fields for atomic operations
177177
*
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+
*
178185
* To be used for reading and preparing of the value stored in the nbcon
179186
* 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.
180191
*/
181192
struct nbcon_state {
182193
union {
183194
unsigned int atom;
184195
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;
185201
};
186202
};
187203
};
@@ -194,6 +210,46 @@ struct nbcon_state {
194210
*/
195211
static_assert(sizeof(struct nbcon_state) <= sizeof(int));
196212

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+
235+
/**
236+
* struct nbcon_context - Context for console acquire/release
237+
* @console: The associated console
238+
* @spinwait_max_us: Limit for spin-wait acquire
239+
* @prio: Priority of the context
240+
* @allow_unsafe_takeover: Allow performing takeover even if unsafe. Can
241+
* be used only with NBCON_PRIO_PANIC @prio. It
242+
* might cause a system freeze when the console
243+
* is used later.
244+
*/
245+
struct nbcon_context {
246+
/* members set by caller */
247+
struct console *console;
248+
unsigned int spinwait_max_us;
249+
enum nbcon_prio prio;
250+
unsigned int allow_unsafe_takeover : 1;
251+
};
252+
197253
/**
198254
* struct console - The console descriptor structure
199255
* @name: The name of the console driver

0 commit comments

Comments
 (0)