Re: [RFC PATCH v2 0/3] Prefer working VT console over SPCR and device-tree chosen stdout-path

From: Petr Mladek
Date: Wed May 13 2020 - 10:38:04 EST


On Thu 2020-04-30 19:14:34, Alper Nebi Yasak wrote:
> I recently experienced some trouble with setting up an encrypted-root
> system, my Chromebook Plus (rk3399-gru-kevin, ARM64) would appear to
> hang where it should have asked for an encryption passphrase; and I
> eventually figured out that the kernel preferred the serial port
> (inaccessible to me) over the built-in working display/keyboard and was
> probably asking there.
>
> Running plymouth in the initramfs solves that specific problem, but
> both the documentation and tty-related kconfig descriptions imply that
> /dev/console should be tty0 if graphics are working, CONFIG_VT_CONSOLE
> is enabled and no explicit console argument is given in the kernel
> commandline.
>
> However, I'm seeing different behaviour on systems with SPCR (as in QEMU
> aarch64 virtual machines) and/or a device-tree chosen stdout-path node
> (as in most arm/arm64 devices). On these machines, depending on the
> console argument, the contents of the /proc/consoles file are:

I dug many times into the history of the console registration code.
The following table mostly confirms my expectations.


> | "console=tty0" | (no console arg) |
> ------------------+-----------------------+-----------------------+
> QEMU VM | tty0 -WU (EC p ) | ttyAMA0 -W- (EC a) |
> (w/ SPCR) | ttyAMA0 -W- (E a) |
> |

The SPCR handling is inconsistent over architectures, see
https://lkml.kernel.org/r/20180830123849.26163-1-prarit@xxxxxxxxxx

IMHO, arm developers decided that consoles defined by SPCR are always
enabled when existing.

In 1st column: tty0 is the preferred console because it is defined
on the commandline.

In 2nd column: tty0 is not enabled at all because another console was
defined by SPCR. Note that ttySX and ttyX consoles are registered only
as a fallback when there is no other console defined.

The following code is responsible for the fallback, see register_console()

/*
* See if we want to use this console driver. If we
* didn't select a console we take the first one
* that registers here.
*/
if (!has_preferred) {
if (newcon->index < 0)
newcon->index = 0;
if (newcon->setup == NULL ||
newcon->setup(newcon, NULL) == 0) {
newcon->flags |= CON_ENABLED;
if (newcon->device) {
newcon->flags |= CON_CONSDEV;
has_preferred = true;
}
}
}


> ------------------+-----------------------+-----------------------+
> Chromebook Plus | tty0 -WU (EC p ) | ttyS2 -W- (EC p a) |
> (w/ stdout-path) | | tty0 -WU (E ) |

Hmm, of_console_check() explicitly ignores the console defined by
stdout-path when there is a console on the commandline. This explains
1st column.

I am not sure about 2nd column. My guess is that ttyX consoles are
tried first. tty0 is registered as a fallback because there is no
other console at the moment. ttyS2 is tried later and it is
registered because it is in stdout-patch and there is no console
in the command line. It is somehow consistent with CONFIG_VT_CONSOLE
description.

Sadly, it is different logic than with SPCR :-(


> ------------------+-----------------------+-----------------------+
> Chromebook Plus | tty0 -WU (EC p ) | tty0 -WU (EC p ) |
> (w/o either) | | |
> ------------------+-----------------------+-----------------------+

This variant is easy and everyone would probably expect this.


Regarding the description of CONFIG_VT_CONSOLE option. I am afraid
that it was created and true only before SPCR and device tree support
was introduced.


Now, it is really sad that SPCR and device tree have different
behavior even across architectures. But I am afraid that we could
not change it without breaking many setups.

The only common rules are:

+ The last console on the command line should always be the
preferred one when defined.

+ Consoles defined by the device (SPCR, device tree) are used
when there is no commandline.

+ ttyX or ttySX are used as a fallback when nothing else is defined.


My suggestion is:

+ Fix SPCR setting or device tree of your device when the defaults
are not as expected.

+ Use command line to force your value when the defaults are not
as expected and you could not change them.


I am afraid that we could not fix your problem on the kernel side. It
would broke other setups that depend on the existing behavior.

Best Regards,
Petr