* [RFC PATCH 1/3] printk: Add function to set console to preferred console's driver
2020-03-23 10:47 [RFC PATCH 0/3] Prefer working VT console over SPCR and device-tree chosen stdout-path Alper Nebi Yasak
@ 2020-03-23 10:48 ` Alper Nebi Yasak
2020-03-23 10:50 ` [RFC PATCH 2/3] vt: Set as preferred console when a non-dummy backend, is bound Alper Nebi Yasak
2020-03-23 10:50 ` [RFC PATCH 3/3] printk: Preset tty0 as a pseudo-preferred console Alper Nebi Yasak
2 siblings, 0 replies; 4+ messages in thread
From: Alper Nebi Yasak @ 2020-03-23 10:48 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Petr Mladek, Sergey Senozhatsky
Cc: Steven Rostedt, linux-kernel, linux-arm-kernel
Currently, add_preferred_console sets a preferred console, but doesn't
actually change /dev/console to match it. That part is handled within
register_device, where a newly registered console driver will be set as
/dev/console if it matches the preferred console.
However, if the relevant driver is already registered, the only way to
set it as /dev/console is by un-registering and re-registering it. An
example is the xenfb_make_preferred_console() function:
console_lock();
for_each_console(c) {
if (!strcmp(c->name, "tty") && c->index == 0)
break;
}
console_unlock();
if (c) {
unregister_console(c);
c->flags |= CON_CONSDEV;
c->flags &= ~CON_PRINTBUFFER; /* don't print again */
register_console(c);
}
The code above was introduced in commit 9e124fe16ff2. In short, it's aim
is to set VT as the preferred console only after a working framebuffer
is registered and thus VT is not the dummy device.
This patch introduces an update_console_to_preferred function that
handles the necessary /dev/console change. With this change, the example
above can be replaced with:
console_lock();
add_preferred_console("tty", 0, NULL);
update_console_to_preferred();
console_unlock();
More importantly, these two calls can be moved to vt.c in order to bump
its priority when a non-dummy backend for it is introduced, solving that
problem in general.
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
---
include/linux/console.h | 1 +
kernel/printk/printk.c | 56 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+)
diff --git a/include/linux/console.h b/include/linux/console.h
index 75dd20650fb..4b3fa34be24 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -172,6 +172,7 @@ enum con_flush_mode {
};
extern int add_preferred_console(char *name, int idx, char *options);
+extern int update_console_to_preferred(void);
extern void register_console(struct console *);
extern int unregister_console(struct console *);
extern struct console *console_drivers;
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index ad460623454..6b16c973587 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2212,12 +2212,68 @@ __setup("console=", console_setup);
* be used by arch-specific code either to override the user or more
* commonly to provide a default console (ie from PROM variables) when
* the user has not supplied one.
+ *
+ * Preferences set by this function don't take effect until the next
+ * time a matching driver for the preferred console is registered. If a
+ * matching driver was already registered, @update_console_to_preferred
+ * function can be used to set that as the preferred console driver.
*/
int add_preferred_console(char *name, int idx, char *options)
{
return __add_preferred_console(name, idx, options, NULL, false);
}
+/**
+ * update_console_to_preferred - set console to the preferred console's driver.
+ *
+ * Updates console_drivers and CON_CONSDEV flags so that an already
+ * registered and enabled console driver matching the preferred console
+ * is used as /dev/console.
+ *
+ * Must be called within console_lock();.
+ */
+int update_console_to_preferred(void)
+{
+ struct console_cmdline *c = NULL;
+ struct console *con = NULL;
+ struct console *tmp = NULL;
+
+ if (preferred_console >= 0)
+ c = &console_cmdline[preferred_console];
+
+ if (!c || !c->name[0])
+ return 0;
+
+ for_each_console(con) {
+ if (!con->next || !(con->next->flags & CON_ENABLED))
+ continue;
+ if (strcmp(c->name, con->next->name) != 0)
+ continue;
+ if (con->next->index >= 0 &&
+ con->next->index != c->index)
+ continue;
+ break;
+ }
+
+ if (!con)
+ return -ENODEV;
+
+ pr_info("switching to console [%s%d]\n",
+ con->next->name, con->next->index);
+
+ tmp = con->next;
+ con->next = con->next->next;
+ tmp->next = console_drivers;
+ console_drivers = tmp;
+
+ if (console_drivers->next)
+ console_drivers->next->flags &= ~CON_CONSDEV;
+ console_drivers->flags |= CON_CONSDEV;
+ has_preferred_console = true;
+
+ return 0;
+}
+
bool console_suspend_enabled = true;
EXPORT_SYMBOL(console_suspend_enabled);
--
2.26.0.rc2
^ permalink raw reply [flat|nested] 4+ messages in thread* [RFC PATCH 2/3] vt: Set as preferred console when a non-dummy backend, is bound
2020-03-23 10:47 [RFC PATCH 0/3] Prefer working VT console over SPCR and device-tree chosen stdout-path Alper Nebi Yasak
2020-03-23 10:48 ` [RFC PATCH 1/3] printk: Add function to set console to preferred console's driver Alper Nebi Yasak
@ 2020-03-23 10:50 ` Alper Nebi Yasak
2020-03-23 10:50 ` [RFC PATCH 3/3] printk: Preset tty0 as a pseudo-preferred console Alper Nebi Yasak
2 siblings, 0 replies; 4+ messages in thread
From: Alper Nebi Yasak @ 2020-03-23 10:50 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Petr Mladek, Sergey Senozhatsky
Cc: Steven Rostedt, linux-kernel, linux-arm-kernel
When a machine's device-tree has a "chosen" node with a "stdout-path"
property that specified console is added as the preferred console by
of_console_check via an add_preferred_console call. The property is
quite common in kernel device-tree definitions. As far as I can tell, it
is set to provide a reasonable default value for earlycon, and the
(usually serial) console is set as preferred to avoid output going to
VT's dummy backend instead of a working console.
However, a chosen stdout-path property is included even in device-trees
of systems that are designed to be used with a built-in display, e.g.
several ARM Chromebooks. In these cases where CONFIG_VT_CONSOLE is
enabled and no console argument is given on the kernel commandline, tty0
is still registered (presumably based on the order of of_console_check
and vt's register_console calls) but ends up not being the preferred
console.
As a result, it is possible for early userspace prompts (encryption
passphrase requests, emergency shells) to end up in a console that the
user doesn't expect or even have access to.
This patch tries to set tty0 as the /dev/console whenever a non-dummy
backend tries to register as its default, unless the preferred console
was set from the kernel commandline arguments.
On a Samsung Chromebook Plus (Google Kevin, rk3399-gru-kevin.dts), boot
messages are still visible on the framebuffer without this patch, but it
isn't the preferred console due to the device-tree having a stdout-path
property (from rk3399-gru.dtsi):
$ sudo dmesg | grep -i "console\|printk"
[ 0.000000] printk: bootconsole [uart0] enabled
[ 0.010232] Console: colour dummy device 80x25
[ 0.015107] printk: console [tty0] enabled
[ 0.019601] printk: bootconsole [uart0] disabled
[ 7.145478] printk: console [ttyS2] enabled
[ 9.316094] Console: switching to colour frame buffer device 300x100
$ cat /proc/consoles
ttyS2 -W- (EC p a) 4:66
tty0 -WU (E ) 4:7
And on the same machine, with this patch:
$ sudo dmesg | grep -i "console\|printk"
[ 0.000000] printk: bootconsole [uart0] enabled
[ 0.010257] Console: colour dummy device 80x25
[ 0.015132] printk: console [tty0] enabled
[ 0.019626] printk: bootconsole [uart0] disabled
[ 4.741120] printk: console [ttyS2] enabled
[ 6.779994] Console: switching to colour frame buffer device 300x100
[ 6.836117] printk: switching to console [tty0]
$ cat /proc/consoles
tty0 -WU (EC ) 4:7
ttyS2 -W- (E p a) 4:66
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
---
drivers/tty/vt/vt.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index bbc26d73209..0fc462ae8b2 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -3566,6 +3566,13 @@ static int do_bind_con_driver(const struct consw *csw, int first, int last,
pr_cont("to %s\n", desc);
}
+#ifdef CONFIG_VT_CONSOLE
+ if (!console_set_on_cmdline && deflt && conswitchp != &dummy_con) {
+ add_preferred_console("tty", 0, NULL);
+ update_console_to_preferred();
+ }
+#endif
+
retval = 0;
err:
module_put(owner);
--
2.26.0.rc2
^ permalink raw reply [flat|nested] 4+ messages in thread* [RFC PATCH 3/3] printk: Preset tty0 as a pseudo-preferred console
2020-03-23 10:47 [RFC PATCH 0/3] Prefer working VT console over SPCR and device-tree chosen stdout-path Alper Nebi Yasak
2020-03-23 10:48 ` [RFC PATCH 1/3] printk: Add function to set console to preferred console's driver Alper Nebi Yasak
2020-03-23 10:50 ` [RFC PATCH 2/3] vt: Set as preferred console when a non-dummy backend, is bound Alper Nebi Yasak
@ 2020-03-23 10:50 ` Alper Nebi Yasak
2 siblings, 0 replies; 4+ messages in thread
From: Alper Nebi Yasak @ 2020-03-23 10:50 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Petr Mladek, Sergey Senozhatsky
Cc: Steven Rostedt, linux-kernel, linux-arm-kernel
The ACPI SPCR (Serial Port Console Redirection) table from a machine's
firmware can specify a serial console which can be used for earlycon.
However, in at least ARM64 systems the same device is also set up as the
preferred console. Presumably due to the order of acpi_parse_spcr and
VT's register_device calls, setting the specified console as the
preferred one can prevent registering VT as a console.
This might look appropriate for machines which do not have or need
working graphics and whose users most likely have access to a serial
port. However, the use of SPCR tables may not be limited these. For
example, ARM64 QEMU virtual machines include a SPCR table regardless of
the existence of a graphics output or even the nonexistence of a serial
console. Or server hardware which has a SPCR table can be repurposed
into a workstation with the addition of a graphics card. As a result,
boot messages and early userspace prompts can go to an unexpected
console.
This patch presets tty0 as a pseudo-preferred console at compile-time to
ensure that CONFIG_VT_CONSOLE always results in the VT console getting
registered. With this, VT can get registered, these other consoles are
preferred when VT is a dummy, but we can also bump up VTs preference
when working graphics are available.
Without this patch, an ARM64 QEMU virtual machine has roughly the
following order of console events and consoles:
$ sudo dmesg | grep -i "console\|printk"
[ 0.000000] ACPI: SPCR: console: pl011,mmio,0x9000000,9600
[ 0.000000] printk: bootconsole [pl11] enabled
[ 0.004890] Console: colour dummy device 80x25
[ 0.412252] printk: console [ttyAMA0] enabled
[ 0.416173] printk: bootconsole [pl11] disabled
[ 3.940510] Console: switching to colour frame buffer device 128x48
$ cat /proc/consoles
ttyAMA0 -W- (EC a) 204:64
In addition, boot messages aren't printed to the framebuffer (as tty0 is
not registered). With this patch, boot messages are visible on the
framebuffer and the information above becomes:
$ sudo dmesg | grep -i "console\|printk"
[ 0.000000] ACPI: SPCR: console: pl011,mmio,0x9000000,9600
[ 0.000000] printk: bootconsole [pl11] enabled
[ 0.002768] Console: colour dummy device 80x25
[ 0.004371] printk: console [tty0] enabled
[ 0.380166] printk: console [ttyAMA0] enabled
[ 0.387337] printk: bootconsole [pl11] disabled
[ 4.695030] Console: switching to colour frame buffer device 128x48
[ 4.709759] printk: switching to console [tty0]
$ cat /proc/consoles
tty0 -WU (EC p ) 4:7
ttyAMA0 -W- (E a) 204:64
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
---
kernel/printk/printk.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 6b16c973587..4b05779ab69 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -277,7 +277,19 @@ static struct console *exclusive_console;
#define MAX_CMDLINECONSOLES 8
+/*
+ * The preferred_console and has_preferred_console variables are
+ * intentionally not modified to reflect this so that the first
+ * registered console is still used as the preferred console.
+ */
+#ifdef CONFIG_VT_CONSOLE
+static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES] = {
+ [0].name = "tty",
+ [0].index = 0,
+};
+#elif
static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
+#endif
static int preferred_console = -1;
static bool has_preferred_console;
--
2.26.0.rc2
^ permalink raw reply [flat|nested] 4+ messages in thread