FreeBSD – How to Activate the Second Console in bhyve

freebsdserial-consolettyuartvirtual machine

Background

I'm running FreeBSD 12.1-RELEASE as a host for bhyve virtual machines.

I have a FreeBSD 12.1-RELEASE guest running inside a VM. I would like to have two TTY-class devices configured for it.

According to the manual page, in order to start the VM with two TTY-class devices I have to start bhyve with command-line options similar to those: -l com1,/dev/nmdm0B -l com2,/dev/nmdm1B. Then I should be able to connect to the guest via those two nullmodem terminals with cu -l /dev/nmdm0A and cu -l /dev/nmdm1A.

Problem

The first command works as expected: cu -l /dev/nmdm0A shows me the main console of the guest.

The second command, however, attaches to the guest, but shows nothing. I would expect to show me a login prompt as if switched to another TTY.

What am I missing?


Additional details

  • The guest is a fresh installation of FreeBSD.

  • The output of dmesg | grep uart on the guest is as follows:

    uart0: <16550 or compatible> port 0x3f8-0x3ff irq 4 flags 0x10 on acpi0
    uart0: console (115200,n,8,1)
    uart1: <16550 or compatible> port 0x2f8-0x2ff irq 3 on acpi0
    
  • I've tried setting hint.uart.1.flags first to 0x10 and then to 0x80 (although this one is for kernel debuggers from what I understand from uart(4)) and rebooted after each change. It didn't work.

References

Best Answer

The solution is to modify /etc/ttys on the guest. On amd64, it has the following defaults:

#
# $FreeBSD: head/sbin/init/ttys.amd64 338454 2018-09-04 15:48:13Z brd $
#   @(#)ttys    5.1 (Berkeley) 4/17/89
#
# This file specifies various information about terminals on the system.
# It is used by several different programs.  Common entries for the
# various columns include:
#
# name  The name of the terminal device.
#
# getty The program to start running on the terminal.  Typically a
#       getty program, as the name implies.  Other common entries
#       include none, when no getty is needed, and xdm, to start the
#       X Window System.
#
# type The initial terminal type for this port.  For hardwired
#      terminal lines, this will contain the type of terminal used.
#      For virtual consoles, the correct type is typically xterm.
#      Other common values include dialup for incoming modem ports, and
#      unknown when the terminal type cannot be predetermined.
#
# status Must be on or off.  If on, init will run the getty program on
#        the specified port.  If the word "secure" appears, this tty
#        allows root login.
#
# name  getty               type    status      comments
#
# If console is marked "insecure", then init will ask for the root password
# when going to single-user mode.
console none                unknown off secure
#
ttyv0   "/usr/libexec/getty Pc"     xterm   onifexists secure
# Virtual terminals
ttyv1   "/usr/libexec/getty Pc"     xterm   onifexists secure
ttyv2   "/usr/libexec/getty Pc"     xterm   onifexists secure
ttyv3   "/usr/libexec/getty Pc"     xterm   onifexists secure
ttyv4   "/usr/libexec/getty Pc"     xterm   onifexists secure
ttyv5   "/usr/libexec/getty Pc"     xterm   onifexists secure
ttyv6   "/usr/libexec/getty Pc"     xterm   onifexists secure
ttyv7   "/usr/libexec/getty Pc"     xterm   onifexists secure
ttyv8   "/usr/local/bin/xdm -nodaemon"  xterm   off secure
# Serial terminals
# The 'dialup' keyword identifies dialin lines to login, fingerd etc.
ttyu0   "/usr/libexec/getty 3wire"  vt100   onifconsole secure
ttyu1   "/usr/libexec/getty 3wire"  vt100   onifconsole secure
ttyu2   "/usr/libexec/getty 3wire"  vt100   onifconsole secure
ttyu3   "/usr/libexec/getty 3wire"  vt100   onifconsole secure
# Dumb console
dcons   "/usr/libexec/getty std.9600"   vt100   off secure

As you can see, the status of every ttyu terminal device is set to onifconsole secure (the secure part is irrelevant here). It means that this those terminal devices are only turned on if they act as a console. In order to make it possible to access those devices from the host we just need to replace onifconsole with onifexists.

In my particular case, I had to replace the following line:

ttyu1   "/usr/libexec/getty 3wire"  vt100   onifconsole secure

with:

ttyu1   "/usr/libexec/getty 3wire"  vt100   ifexists secure

As a result, it is now possible to connect to the guest system using the second console:

# cu -l /dev/nmdm1A
Password:
Connected
 
 
FreeBSD/amd64 (testvm) (ttyu1)
 
login: root
Password:
Last login: Fri Jun 26 19:59:40 on ttyu1
FreeBSD 12.1-RELEASE r354233 GENERIC
 
Welcome to FreeBSD!
Related Question