1# This module allows the test driver to connect to the virtual machine
2# via a root shell attached to port 514.
3
4{ config, lib, pkgs, ... }:
5
6with lib;
7with import ../../lib/qemu-flags.nix { inherit pkgs; };
8
9let
10 kernel = config.boot.kernelPackages.kernel;
11in
12
13{
14
15 # This option is a dummy that if used in conjunction with
16 # modules/virtualisation/qemu-vm.nix gets merged with the same option defined
17 # there and only is declared here because some modules use
18 # test-instrumentation.nix but not qemu-vm.nix.
19 #
20 # One particular example are the boot tests where we want instrumentation
21 # within the images but not other stuff like setting up 9p filesystems.
22 options.virtualisation.qemu.program = mkOption { type = types.path; };
23
24 config = {
25
26 systemd.services.backdoor =
27 { wantedBy = [ "multi-user.target" ];
28 requires = [ "dev-hvc0.device" "dev-${qemuSerialDevice}.device" ];
29 after = [ "dev-hvc0.device" "dev-${qemuSerialDevice}.device" ];
30 script =
31 ''
32 export USER=root
33 export HOME=/root
34 export DISPLAY=:0.0
35
36 source /etc/profile
37
38 # Don't use a pager when executing backdoor
39 # actions. Because we use a tty, commands like systemctl
40 # or nix-store get confused into thinking they're running
41 # interactively.
42 export PAGER=
43
44 cd /tmp
45 exec < /dev/hvc0 > /dev/hvc0
46 while ! exec 2> /dev/${qemuSerialDevice}; do sleep 0.1; done
47 echo "connecting to host..." >&2
48 stty -F /dev/hvc0 raw -echo # prevent nl -> cr/nl conversion
49 echo
50 PS1= exec /bin/sh
51 '';
52 serviceConfig.KillSignal = "SIGHUP";
53 };
54
55 # Prevent agetty from being instantiated on the serial device, since it
56 # interferes with the backdoor (writes to it will randomly fail
57 # with EIO). Likewise for hvc0.
58 systemd.services."serial-getty@${qemuSerialDevice}".enable = false;
59 systemd.services."serial-getty@hvc0".enable = false;
60
61 boot.initrd.preDeviceCommands =
62 ''
63 echo 600 > /proc/sys/kernel/hung_task_timeout_secs
64 '';
65
66 boot.initrd.postDeviceCommands =
67 ''
68 # Using acpi_pm as a clock source causes the guest clock to
69 # slow down under high host load. This is usually a bad
70 # thing, but for VM tests it should provide a bit more
71 # determinism (e.g. if the VM runs at lower speed, then
72 # timeouts in the VM should also be delayed).
73 echo acpi_pm > /sys/devices/system/clocksource/clocksource0/current_clocksource
74 '';
75
76 boot.postBootCommands =
77 ''
78 # Panic on out-of-memory conditions rather than letting the
79 # OOM killer randomly get rid of processes, since this leads
80 # to failures that are hard to diagnose.
81 echo 2 > /proc/sys/vm/panic_on_oom
82
83 # Coverage data is written into /tmp/coverage-data.
84 mkdir -p /tmp/xchg/coverage-data
85 '';
86
87 # If the kernel has been built with coverage instrumentation, make
88 # it available under /proc/gcov.
89 boot.kernelModules = [ "gcov-proc" ];
90
91 # Panic if an error occurs in stage 1 (rather than waiting for
92 # user intervention).
93 boot.kernelParams =
94 [ "console=${qemuSerialDevice}" "panic=1" "boot.panic_on_fail" ];
95
96 # `xwininfo' is used by the test driver to query open windows.
97 environment.systemPackages = [ pkgs.xorg.xwininfo ];
98
99 # Log everything to the serial console.
100 services.journald.extraConfig =
101 ''
102 ForwardToConsole=yes
103 MaxLevelConsole=debug
104 '';
105
106 # Don't clobber the console with duplicate systemd messages.
107 systemd.extraConfig = "ShowStatus=no";
108
109 boot.consoleLogLevel = 7;
110
111 # Prevent tests from accessing the Internet.
112 networking.defaultGateway = mkOverride 150 "";
113 networking.nameservers = mkOverride 150 [ ];
114
115 systemd.globalEnvironment.GCOV_PREFIX = "/tmp/xchg/coverage-data";
116
117 system.requiredKernelConfig = with config.lib.kernelConfig; [
118 (isYes "SERIAL_8250_CONSOLE")
119 (isYes "SERIAL_8250")
120 (isEnabled "VIRTIO_CONSOLE")
121 ];
122
123 networking.usePredictableInterfaceNames = false;
124
125 # Make it easy to log in as root when running the test interactively.
126 users.extraUsers.root.initialHashedPassword = mkOverride 150 "";
127
128 services.xserver.displayManager.job.logToJournal = true;
129 };
130
131}