diff mbox series

[2/2] systemd: use getty generators by default

Message ID 20250130175901.938043-2-ross.burton@arm.com
State New
Headers show
Series [1/2] systemd-serialgetty: add comments explaining use | expand

Commit Message

Ross Burton Jan. 30, 2025, 5:59 p.m. UTC
systemd can automatically create getty service units at boot time by
probing the hardware: if will check for a list of known hypervisor
consoles and also spawn a getty on every active console.

However in a historical attempt to change as little behaviour as
possible, we disabled this and instead wrote hard-coded units at build
time that respect the SERIAL_CONSOLES variable.

This variable may be acceptable for fixed known platforms, but is not
usable for generic machines. The genericarm64 machine for example lists
a number of potential consoles:

- ttyAMA0: physical ARM PL011 uarts
- hvc0: hypervisor virtual console
- ttyS0-2: physical uarts

We have to list multiple ttyS? names because different platforms use
different devices: specifically on the BeaglePlay the Linux console is
ttyS2, with S0 and S1 being the uarts connecting the expansion port.

However, it's not ideal to randomly open ports and hope for the best:
with kernel 6.7 onwards a power management/tty bug results in system
hangs if a getty is sitting on ttyS1 (see #15704).

A better solution is to just use the getty generator in systemd: this
will automatically spawn gettys on any hypervisor consoles found and all
of the consoles that Linux is aware of. On the BeaglePlay this means
it puts a getty on just ttyS2, as expected.

The fixed configuration recipe is still present for people who wish to
have absolute control by simply disabling the serial-getty-generator
PACKAGECONFIG.

Signed-off-by: Ross Burton <ross.burton@arm.com>
---
 meta/recipes-core/systemd/systemd_257.1.bb | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

Comments

Mikko Rapeli Jan. 31, 2025, 7:25 a.m. UTC | #1
Hi,

On Thu, Jan 30, 2025 at 05:59:01PM +0000, Ross Burton via lists.openembedded.org wrote:
> systemd can automatically create getty service units at boot time by
> probing the hardware: if will check for a list of known hypervisor
> consoles and also spawn a getty on every active console.
> 
> However in a historical attempt to change as little behaviour as
> possible, we disabled this and instead wrote hard-coded units at build
> time that respect the SERIAL_CONSOLES variable.
> 
> This variable may be acceptable for fixed known platforms, but is not
> usable for generic machines. The genericarm64 machine for example lists
> a number of potential consoles:
> 
> - ttyAMA0: physical ARM PL011 uarts
> - hvc0: hypervisor virtual console
> - ttyS0-2: physical uarts
> 
> We have to list multiple ttyS? names because different platforms use
> different devices: specifically on the BeaglePlay the Linux console is
> ttyS2, with S0 and S1 being the uarts connecting the expansion port.
> 
> However, it's not ideal to randomly open ports and hope for the best:
> with kernel 6.7 onwards a power management/tty bug results in system
> hangs if a getty is sitting on ttyS1 (see #15704).
> 
> A better solution is to just use the getty generator in systemd: this
> will automatically spawn gettys on any hypervisor consoles found and all
> of the consoles that Linux is aware of. On the BeaglePlay this means
> it puts a getty on just ttyS2, as expected.
> 
> The fixed configuration recipe is still present for people who wish to
> have absolute control by simply disabling the serial-getty-generator
> PACKAGECONFIG.

ACK, we have also found that systemd and udev handle serial consoles
correctly when supporting multiple devices like rockpi4b, synquacer,
AMD KV260, zcu102, AVA, qemu etc from a single build. 

systemd-serialgetty did not work so well.

Cheers,

-Mikko
Ross Burton Jan. 31, 2025, 4:21 p.m. UTC | #2
On 31 Jan 2025, at 07:25, Mikko Rapeli <mikko.rapeli@linaro.org> wrote:
> ACK, we have also found that systemd and udev handle serial consoles
> correctly when supporting multiple devices like rockpi4b, synquacer,
> AMD KV260, zcu102, AVA, qemu etc from a single build.

The challenge is doing the same for sysvinit…

Sharing for the wider community: genericarm64 defines SERIAL_CONSOLES to hvc0 (if its inside a qemu), ttyAMA0 (hardware using the Arm PL011 uart), and ttyS[0-2] (other hardware using serial ports).  It has to be the first three serial ports because hardware is different: specifically the BeaglePlay has the Linux console on ttyS2 as two internal uarts that connect to the expansion port are 0 and 1.  However, throwing a getty on ttyS1 doesn’t go well, but there doesn’t appear to be a good way to know that from userspace.

My current best idea is to replicate the logic in systemd inside syvinit somehow, but that’s… not trivial.  Possibly a shell wrapper that init starts and it forks off gettys, respawning them as needed? It’s almost easier to extend sysvinit so that it can start inittab lines dynamically.

Ross
diff mbox series

Patch

diff --git a/meta/recipes-core/systemd/systemd_257.1.bb b/meta/recipes-core/systemd/systemd_257.1.bb
index cdf72a50157..f464b979b07 100644
--- a/meta/recipes-core/systemd/systemd_257.1.bb
+++ b/meta/recipes-core/systemd/systemd_257.1.bb
@@ -92,6 +92,7 @@  PACKAGECONFIG ??= " \
     quotacheck \
     randomseed \
     resolved \
+    serial-getty-generator \
     set-time-epoch \
     sysusers \
     timedated \
@@ -126,7 +127,7 @@  TARGET_CC_ARCH:append:libc-musl = " -D__UAPI_DEF_ETHHDR=0 -D_LARGEFILE64_SOURCE"
 
 # Use the upstream systemd serial-getty@.service and rely on
 # systemd-getty-generator instead of using the OE-core specific
-# systemd-serialgetty.bb - not enabled by default.
+# systemd-serialgetty.bb
 PACKAGECONFIG[serial-getty-generator] = ""
 
 PACKAGECONFIG[acl] = "-Dacl=enabled,-Dacl=disabled,acl"
@@ -287,8 +288,10 @@  do_install() {
 		fi
 	fi
 	install -d ${D}/${base_sbindir}
+
 	if ${@bb.utils.contains('PACKAGECONFIG', 'serial-getty-generator', 'false', 'true', d)}; then
-		# Provided by a separate recipe
+		# Remove the serial-getty generator and instead use explicit services
+		# created by the systemd-serialgetty recipe
 		rm ${D}${systemd_system_unitdir}/serial-getty* -f
 	fi