Ilan Rozen
Ilan Rozen

Reputation: 21

Configure QEMU to test multi-seat operating system (multiple consoles)

as part of an academic course we're implementing a simple OS. We've used QEMU so far to simulate an x86 processor to run our OS on. Now, we've come up with an idea to extend our OS to support multiple users, preferably in such a way that would support simultaneous use of the OS and several of its resources.

My question is if there's any way we could run QEMU in a way that would, for example, open 2 QEMU monitors/consoles/terminals (not sure about the correct term in this case), each representing a different user, and both use a single instance of the OS. Say these two monitors are initialized to run a distinct instance of shell program that we have as a user program in out OS.

A similar ability we've seen so far was to run QEMU while listening on some port for gdb connection, which we're able to connect to through another console by running gdb, thus entering debugging mode. One console would display our OS output, and the other is used for gdb commands.

Has anyone got any idea how can such a thing be done? Thanks!

Upvotes: 2

Views: 1177

Answers (1)

beroal
beroal

Reputation: 397

Yes, there is a way. As Peter Cordes said, you need to configure a multi-seat VM. A seat is a set of human interface devices which commonly includes a monitor, a keyboard, and a mouse. The difficulty isn't as much in hardware configuration as in software configuration. The circle of Linux users building multi-seat (physical) computers is small, so software support is scarce and buggy. Below I described a hardware configuration which I run in a VM.

Hardware

An example command line creating a VM with two seats:

qemu-system-x86_64 -display gtk -enable-kvm -cpu host -monitor stdio\
    -nodefaults\
    -machine q35,accel=kvm -m 1G\
    -drive if=pflash,format=raw,readonly=on,file=/usr/share/edk2-ovmf/x64/OVMF_CODE.fd -drive if=pflash,format=raw,file=OVMF_VARS.fd\
    -device virtio-blk-pci,addr=01.0,drive=root-fs -drive id=root-fs,file="$HOME/temp/qemu/ata.qcow2",if=none\
    -device virtio-gpu-pci,id=seat0-video,addr=08.0,xres=1024,yres=768\
    -device virtio-keyboard-pci,addr=09.0,display=seat0-video\
    -device virtio-tablet-pci,addr=0a.0,display=seat0-video\
    -device virtio-gpu-pci,id=seat1-video,addr=0c.0,xres=600,yres=800\
    -device virtio-keyboard-pci,addr=0d.0,display=seat1-video\
    -device virtio-tablet-pci,addr=0e.0,display=seat1-video

The output of lspci -tv in the VM should be:

-[0000:00]-+-00.0  Intel Corporation 82G33/G31/P35/P31 Express DRAM Controller
           +-01.0  Red Hat, Inc. Virtio block device
           +-08.0  Red Hat, Inc. Virtio GPU
           +-09.0  Red Hat, Inc. Virtio input
           +-0a.0  Red Hat, Inc. Virtio input
           +-0c.0  Red Hat, Inc. Virtio GPU
           +-0d.0  Red Hat, Inc. Virtio input
           +-0e.0  Red Hat, Inc. Virtio input
           +-1f.0  Intel Corporation 82801IB (ICH9) LPC Interface Controller
           +-1f.2  Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode]
           \-1f.3  Intel Corporation 82801I (ICH9 Family) SMBus Controller

PCI devices 08.0, 09.0, and 0a.0 are intended for seat0. PCI devices 0c.0, 0d.0, and 0e.0 are intended for seat1. tablet is actually a mouse. A GPU is the main device of a seat. The display parameter of a non-main device belonging to a seat should be the identifier of the main device of that seat so QEMU GUI shows seats properly.

This hardware topology is simplified comparing to topologies of physical computers with PCI Express. In this VM, all devices are on the same PCI bus, while a physical computer with PCI Express have a PCI bus for every physical device. If this topology doesn't work, try to imitate physical topology more closely as described in “PCI EXPRESS GUIDELINES” of QEMU.

In the QEMU GUI window that shows GPU output and receives mouse and keyboard events, click on the main menu View → Show Tabs. There should be a tab for every GPU.

OVMF is needed because this VM runs a UEFI BIOS. $HOME/temp/qemu/ata.qcow2 is a block device containing a root file system of Linux.

udev

Abstractly, you need to communicate device identifiers to programs implementing UI. Usual GUI programs like the Xorg server and the Weston server get this information from udev. A sysadmin should attach devices to seats by setting the ID_SEAT variable of a device to the name of the seat this device belongs to. Then UI programs should be started with a command line option telling which seat the program should work on.

ID_SEAT is a udev ENV variable. It can be set depending on the device's properties and place in the hardware topology with udev rules. If a device has no ID_SEAT, it's assumed to belong to the seat called seat0.

The udev daemon executes rules in “/etc/udev/rules.d/”. An example rules file “/etc/udev/rules.d/97-seat.rules” which sets ID_SEAT:

TAG=="seat", ENV{DEVPATH}=="/devices/pci0000:00/0000:00:0[cdef].0", ENV{ID_SEAT}="seat1"
TAG=="seat", ENV{DEVPATH}=="/devices/pci0000:00/0000:00:0[cdef].0/*", ENV{ID_SEAT}="seat1"

The meaning of a rule above is to set ID_SEAT of a device whose DEVPATH variable matches the specified regular expression and whose TAGS variable contains the string seat. The DEVPATH variable of a device stores the path to that device in the sys file system. The asterisk in the rule matches strict descendants of /devices/pci0000:00/0000:00:0[cdef].0, but doesn't match this device itself. This is why two rules are needed. The command udevadm info $DEV_PATH shows ENV variables of the device referred by $DEV_PATH. For example, udevadm info /sys/devices/pci0000:00/0000:00:0c.0/virtio5/drm/card1 should output:

P: /devices/pci0000:00/0000:00:0c.0/virtio5/drm/card1
N: dri/card1
L: 0
S: dri/by-path/pci-0000:00:0c.0-card
E: DEVPATH=/devices/pci0000:00/0000:00:0c.0/virtio5/drm/card1
E: DEVNAME=/dev/dri/card1
E: DEVTYPE=drm_minor
E: MAJOR=226
E: MINOR=1
E: SUBSYSTEM=drm
E: USEC_INITIALIZED=1661999
E: ID_PATH=pci-0000:00:0c.0
E: ID_PATH_TAG=pci-0000_00_0c_0
E: ID_FOR_SEAT=drm-pci-0000_00_0c_0
E: ID_SEAT=seat1
E: DEVLINKS=/dev/dri/by-path/pci-0000:00:0c.0-card
E: TAGS=:master-of-seat:uaccess:seat:
E: CURRENT_TAGS=:master-of-seat:uaccess:seat:

Display server

As was said, UI programs should be started with a seat command line option. For the Xorg server, this option is called -seat. Display servers like the Xorg server are more often started via a display manager. I know only one display manager that supports multi-seat, LightDM. There is an indication that SDDM supports multi-seat too. LightDM presents user login forms on all seats (that have a GPU). Unfortunately, there is no way to make LightDM to ignore a seat.

Upvotes: 1

Related Questions