diff --git a/app/qemu.go b/app/qemu.go index 1b20e37..a21a52c 100644 --- a/app/qemu.go +++ b/app/qemu.go @@ -66,6 +66,11 @@ func buildQemuArgs(cfg *config, cmdline string) []string { "-device", "virtio-keyboard-pci", "-device", "virtio-tablet-pci", "-device", "virtio-net-pci,netdev=n0", "-netdev", netdevArg(cfg.forwards), "-device", "virtio-rng-pci", + // The guest must not sleep: a suspended VM leaves the window frozen + // with no way back from the keyboard, and Omarchy's power menu + // offers suspend whenever the kernel advertises it. With S3 and S4 + // off the kernel reports no such state and systemd refuses cleanly. + "-global", "ICH9-LPC.disable_s3=1", "-global", "ICH9-LPC.disable_s4=1", // The backend must be explicit: with no audiodev the guest's PipeWire // stalls on virtio-snd control messages and the whole session hangs. // cfg.audio is dsound normally; "none" on machines where DirectSound diff --git a/app/qemu_nonwindows_test.go b/app/qemu_nonwindows_test.go index 4015752..004eb93 100644 --- a/app/qemu_nonwindows_test.go +++ b/app/qemu_nonwindows_test.go @@ -353,3 +353,13 @@ func TestBuildQemuArgsTellsTheGuestTheRenderingPath(t *testing.T) { t.Fatalf("cpu marker missing: %s", args) } } + +func TestBuildQemuArgsDisablesGuestSleepStates(t *testing.T) { + for _, gpu := range []bool{true, false} { + cfg := &config{vmDir: "/vm", guestDir: "/guest", disk: "/vm/disk.raw", diskFormat: "raw", memMiB: 4096, audio: "none", useGpu: gpu} + args := strings.Join(buildQemuArgs(cfg, "root=/dev/vda"), " ") + if !strings.Contains(args, "-global ICH9-LPC.disable_s3=1 -global ICH9-LPC.disable_s4=1") { + t.Fatalf("gpu=%v: sleep states not disabled: %s", gpu, args) + } + } +}