[PATCH v2 32/32] tests/functional/x86_64: add functional test to exercise vm fd change on reset

Ani Sinha posted 32 patches 4 weeks ago
[PATCH v2 32/32] tests/functional/x86_64: add functional test to exercise vm fd change on reset
Posted by Ani Sinha 4 weeks ago
A new functional test is added that exercises the code changes related to
closing of the old KVM VM file descriptor and opening a new one upon VM reset.
This normally happens when confidential guests are resetted but for
non-confidential guests, we use a special machine specific debug/test parameter
'x-change-vmfd-on-reset' to enable this behavior.
Only specific code changes related to re-initialization of SEV-ES, SEV-SNP and
TDX platforms are not exercized in this test as they require hardware that
supports running confidential guests.

Signed-off-by: Ani Sinha <anisinha@redhat.com>
---
 MAINTAINERS                                   |  6 ++
 tests/functional/x86_64/meson.build           |  1 +
 .../x86_64/test_vmfd_change_reboot.py         | 75 +++++++++++++++++++
 3 files changed, 82 insertions(+)
 create mode 100755 tests/functional/x86_64/test_vmfd_change_reboot.py

diff --git a/MAINTAINERS b/MAINTAINERS
index 9a55b649e8..11871fdd35 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -150,6 +150,12 @@ F: tools/i386/
 F: tests/functional/i386/
 F: tests/functional/x86_64/
 
+X86 VM file descriptor change on reset test
+M: Ani Sinha <aniisnha@redhat.com>
+M: Paolo Bonzini <pbonzini@redhat.com>
+S: Maintained
+F: tests/functional/x86_64/test_vmfd_change_reboot.py
+
 Guest CPU cores (TCG)
 ---------------------
 Overall TCG CPUs
diff --git a/tests/functional/x86_64/meson.build b/tests/functional/x86_64/meson.build
index f78eec5e6c..784d9791cb 100644
--- a/tests/functional/x86_64/meson.build
+++ b/tests/functional/x86_64/meson.build
@@ -36,4 +36,5 @@ tests_x86_64_system_thorough = [
   'vfio_user_client',
   'virtio_balloon',
   'virtio_gpu',
+  'vmfd_change_reboot',
 ]
diff --git a/tests/functional/x86_64/test_vmfd_change_reboot.py b/tests/functional/x86_64/test_vmfd_change_reboot.py
new file mode 100755
index 0000000000..3b33322880
--- /dev/null
+++ b/tests/functional/x86_64/test_vmfd_change_reboot.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python3
+#
+# KVM VM file descriptor change on reset test
+#
+# Copyright © 2026 Red Hat, Inc.
+#
+# Author:
+#  Ani Sinha <anisinha@redhat.com>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import os
+from qemu.machine import machine
+
+from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern
+from qemu_test import wait_for_console_pattern
+
+class KVMGuest(QemuSystemTest):
+
+    ASSET_UKI = Asset('https://gitlab.com/anisinha/misc-artifacts/'
+                      '-/raw/main/uki.x86-64.efi?ref_type=heads',
+                      'e0f806bd1fa24111312e1fe849d2ee69808d4343930a5'
+                      'dc8c1688da17c65f576')
+    ASSET_OVMF = Asset('https://gitlab.com/anisinha/misc-artifacts/'
+                       '-/raw/main/OVMF.stateless.fd?ref_type=heads',
+                       '58a4275aafa8774bd6b1540adceae4ea434b8db75b476'
+                       '11839ff47be88cfcf22')
+
+    def common_vm_setup(self):
+        self.require_accelerator("kvm")
+
+        self.vm.set_console()
+
+        self.vm.add_args("-accel", "kvm")
+        self.vm.add_args("-smp", "2")
+        self.vm.add_args("-cpu", "host")
+        self.vm.add_args("-m", "2G")
+        self.vm.add_args("-nographic", "-nodefaults")
+
+        self.uki_path = self.ASSET_UKI.fetch()
+        self.ovmf_path = self.ASSET_OVMF.fetch()
+
+    def run_and_check(self):
+        self.vm.add_args('-kernel', self.uki_path)
+        self.vm.add_args("-bios", self.ovmf_path)
+        # enable KVM VMFD change on reset for a non-coco VM
+        self.vm.add_args("-machine", "q35,x-change-vmfd-on-reset=on")
+        # enable tracing
+        self.vm.add_args("-d", "trace:kvm_reset_vmfd")
+
+        try:
+            self.vm.launch()
+        except machine.VMLaunchFailure as e:
+            raise e
+
+        self.log.info('VM launched')
+        console_pattern = 'bash-5.1#'
+        wait_for_console_pattern(self, console_pattern)
+        self.log.info('VM ready with a bash prompt')
+
+        exec_command_and_wait_for_pattern(self, '/usr/sbin/reboot -f',
+                                          'reboot: machine restart')
+        console_pattern = '# --- Hello world ---'
+        wait_for_console_pattern(self, console_pattern)
+        self.vm.shutdown()
+        self.assertRegex(self.vm.get_log(),
+                         r'kvm_reset_vmfd \nINFO: virtual machine accel file '
+                         'descriptor has changed')
+
+    def test_vmfd_change_on_reset(self):
+        self.common_vm_setup()
+        self.run_and_check()
+
+if __name__ == '__main__':
+    QemuSystemTest.main()
-- 
2.42.0


Re: [PATCH v2 32/32] tests/functional/x86_64: add functional test to exercise vm fd change on reset
Posted by Daniel P. Berrangé 4 weeks ago
On Mon, Jan 12, 2026 at 06:52:45PM +0530, Ani Sinha wrote:
> A new functional test is added that exercises the code changes related to
> closing of the old KVM VM file descriptor and opening a new one upon VM reset.
> This normally happens when confidential guests are resetted but for
> non-confidential guests, we use a special machine specific debug/test parameter
> 'x-change-vmfd-on-reset' to enable this behavior.
> Only specific code changes related to re-initialization of SEV-ES, SEV-SNP and
> TDX platforms are not exercized in this test as they require hardware that
> supports running confidential guests.
> 
> Signed-off-by: Ani Sinha <anisinha@redhat.com>
> ---
>  MAINTAINERS                                   |  6 ++
>  tests/functional/x86_64/meson.build           |  1 +
>  .../x86_64/test_vmfd_change_reboot.py         | 75 +++++++++++++++++++
>  3 files changed, 82 insertions(+)
>  create mode 100755 tests/functional/x86_64/test_vmfd_change_reboot.py


> diff --git a/tests/functional/x86_64/test_vmfd_change_reboot.py b/tests/functional/x86_64/test_vmfd_change_reboot.py
> new file mode 100755
> index 0000000000..3b33322880
> --- /dev/null
> +++ b/tests/functional/x86_64/test_vmfd_change_reboot.py
> @@ -0,0 +1,75 @@
> +#!/usr/bin/env python3
> +#
> +# KVM VM file descriptor change on reset test
> +#
> +# Copyright © 2026 Red Hat, Inc.
> +#
> +# Author:
> +#  Ani Sinha <anisinha@redhat.com>
> +#
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +
> +import os
> +from qemu.machine import machine
> +
> +from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern
> +from qemu_test import wait_for_console_pattern
> +
> +class KVMGuest(QemuSystemTest):
> +
> +    ASSET_UKI = Asset('https://gitlab.com/anisinha/misc-artifacts/'
> +                      '-/raw/main/uki.x86-64.efi?ref_type=heads',
> +                      'e0f806bd1fa24111312e1fe849d2ee69808d4343930a5'
> +                      'dc8c1688da17c65f576')
> +    ASSET_OVMF = Asset('https://gitlab.com/anisinha/misc-artifacts/'
> +                       '-/raw/main/OVMF.stateless.fd?ref_type=heads',
> +                       '58a4275aafa8774bd6b1540adceae4ea434b8db75b476'
> +                       '11839ff47be88cfcf22')

What is the source of these two binaries - the repo doesn't show any
source code or references ?  Is there no way we can use standard distro
images for this test ?

> +
> +    def common_vm_setup(self):
> +        self.require_accelerator("kvm")
> +
> +        self.vm.set_console()
> +
> +        self.vm.add_args("-accel", "kvm")
> +        self.vm.add_args("-smp", "2")
> +        self.vm.add_args("-cpu", "host")
> +        self.vm.add_args("-m", "2G")
> +        self.vm.add_args("-nographic", "-nodefaults")
> +
> +        self.uki_path = self.ASSET_UKI.fetch()
> +        self.ovmf_path = self.ASSET_OVMF.fetch()
> +
> +    def run_and_check(self):
> +        self.vm.add_args('-kernel', self.uki_path)
> +        self.vm.add_args("-bios", self.ovmf_path)
> +        # enable KVM VMFD change on reset for a non-coco VM
> +        self.vm.add_args("-machine", "q35,x-change-vmfd-on-reset=on")
> +        # enable tracing
> +        self.vm.add_args("-d", "trace:kvm_reset_vmfd")
> +
> +        try:
> +            self.vm.launch()
> +        except machine.VMLaunchFailure as e:
> +            raise e
> +
> +        self.log.info('VM launched')
> +        console_pattern = 'bash-5.1#'
> +        wait_for_console_pattern(self, console_pattern)
> +        self.log.info('VM ready with a bash prompt')
> +
> +        exec_command_and_wait_for_pattern(self, '/usr/sbin/reboot -f',
> +                                          'reboot: machine restart')
> +        console_pattern = '# --- Hello world ---'
> +        wait_for_console_pattern(self, console_pattern)
> +        self.vm.shutdown()
> +        self.assertRegex(self.vm.get_log(),
> +                         r'kvm_reset_vmfd \nINFO: virtual machine accel file '
> +                         'descriptor has changed')
> +
> +    def test_vmfd_change_on_reset(self):
> +        self.common_vm_setup()
> +        self.run_and_check()
> +
> +if __name__ == '__main__':
> +    QemuSystemTest.main()
> -- 
> 2.42.0
> 
> 

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|


Re: [PATCH v2 32/32] tests/functional/x86_64: add functional test to exercise vm fd change on reset
Posted by Ani Sinha 3 weeks, 6 days ago
On Mon, Jan 12, 2026 at 8:06 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> On Mon, Jan 12, 2026 at 06:52:45PM +0530, Ani Sinha wrote:
> > A new functional test is added that exercises the code changes related to
> > closing of the old KVM VM file descriptor and opening a new one upon VM reset.
> > This normally happens when confidential guests are resetted but for
> > non-confidential guests, we use a special machine specific debug/test parameter
> > 'x-change-vmfd-on-reset' to enable this behavior.
> > Only specific code changes related to re-initialization of SEV-ES, SEV-SNP and
> > TDX platforms are not exercized in this test as they require hardware that
> > supports running confidential guests.
> >
> > Signed-off-by: Ani Sinha <anisinha@redhat.com>
> > ---
> >  MAINTAINERS                                   |  6 ++
> >  tests/functional/x86_64/meson.build           |  1 +
> >  .../x86_64/test_vmfd_change_reboot.py         | 75 +++++++++++++++++++
> >  3 files changed, 82 insertions(+)
> >  create mode 100755 tests/functional/x86_64/test_vmfd_change_reboot.py
>
>
> > diff --git a/tests/functional/x86_64/test_vmfd_change_reboot.py b/tests/functional/x86_64/test_vmfd_change_reboot.py
> > new file mode 100755
> > index 0000000000..3b33322880
> > --- /dev/null
> > +++ b/tests/functional/x86_64/test_vmfd_change_reboot.py
> > @@ -0,0 +1,75 @@
> > +#!/usr/bin/env python3
> > +#
> > +# KVM VM file descriptor change on reset test
> > +#
> > +# Copyright © 2026 Red Hat, Inc.
> > +#
> > +# Author:
> > +#  Ani Sinha <anisinha@redhat.com>
> > +#
> > +# SPDX-License-Identifier: GPL-2.0-or-later
> > +
> > +import os
> > +from qemu.machine import machine
> > +
> > +from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern
> > +from qemu_test import wait_for_console_pattern
> > +
> > +class KVMGuest(QemuSystemTest):
> > +
> > +    ASSET_UKI = Asset('https://gitlab.com/anisinha/misc-artifacts/'
> > +                      '-/raw/main/uki.x86-64.efi?ref_type=heads',
> > +                      'e0f806bd1fa24111312e1fe849d2ee69808d4343930a5'
> > +                      'dc8c1688da17c65f576')
> > +    ASSET_OVMF = Asset('https://gitlab.com/anisinha/misc-artifacts/'
> > +                       '-/raw/main/OVMF.stateless.fd?ref_type=heads',
> > +                       '58a4275aafa8774bd6b1540adceae4ea434b8db75b476'
> > +                       '11839ff47be88cfcf22')
>
> What is the source of these two binaries - the repo doesn't show any
> source code or references ?

For ASSET_UKI, it was built using
https://gitlab.com/kraxel/edk2-tests/-/blob/unittest/tools/make-supermin.sh
Maybe I can add a comment in the test as such.

ASSET_OVMF is a little more complicated ...

> Is there no way we can use standard distro
> images for this test ?

ASSET_OVMF comes from /usr/share/edk2/ovmf/OVMF.stateless.fd of a fc43
VM. It comes from edk2-ovmf-20251119-3.fc43.noarch rpm.
This rpm must be installed in the container where the test is run. I
checked that CI images we use do not have this rpm or the edk2 binary.
In fact, we do not have OVMF.amdsev.fd or its TDX variant or any of
OVMF_CODE.secboot.fd etc either. OVMF packages are simply not in the
container images generated.

There are two reasons why I did it this way -
a) I know the long path to adding a package into all CI container
images and I wanted to avoid doing that just as yet since ...
b) as we spoke offline, even if we did add the package, since /dev/kvm
is not available, this test will be skipped and not run in CI.

So for this test to run successfully, we must enable kvm tests in CI
(have /dev/kvm available). Then we can add the above package and
remove this. Also skip the test where OVMF.stateless.fd is not
available.

For now, I wanted to make sure at least everyone can run this test
manually where kvm is available even if they do not have the package
installed or if the package is not available for their host OS (for
example RHEL-9.6 does not have the stateless variant).


>
> > +
> > +    def common_vm_setup(self):
> > +        self.require_accelerator("kvm")
> > +
> > +        self.vm.set_console()
> > +
> > +        self.vm.add_args("-accel", "kvm")
> > +        self.vm.add_args("-smp", "2")
> > +        self.vm.add_args("-cpu", "host")
> > +        self.vm.add_args("-m", "2G")
> > +        self.vm.add_args("-nographic", "-nodefaults")
> > +
> > +        self.uki_path = self.ASSET_UKI.fetch()
> > +        self.ovmf_path = self.ASSET_OVMF.fetch()
> > +
> > +    def run_and_check(self):
> > +        self.vm.add_args('-kernel', self.uki_path)
> > +        self.vm.add_args("-bios", self.ovmf_path)
> > +        # enable KVM VMFD change on reset for a non-coco VM
> > +        self.vm.add_args("-machine", "q35,x-change-vmfd-on-reset=on")
> > +        # enable tracing
> > +        self.vm.add_args("-d", "trace:kvm_reset_vmfd")
> > +
> > +        try:
> > +            self.vm.launch()
> > +        except machine.VMLaunchFailure as e:
> > +            raise e
> > +
> > +        self.log.info('VM launched')
> > +        console_pattern = 'bash-5.1#'
> > +        wait_for_console_pattern(self, console_pattern)
> > +        self.log.info('VM ready with a bash prompt')
> > +
> > +        exec_command_and_wait_for_pattern(self, '/usr/sbin/reboot -f',
> > +                                          'reboot: machine restart')
> > +        console_pattern = '# --- Hello world ---'
> > +        wait_for_console_pattern(self, console_pattern)
> > +        self.vm.shutdown()
> > +        self.assertRegex(self.vm.get_log(),
> > +                         r'kvm_reset_vmfd \nINFO: virtual machine accel file '
> > +                         'descriptor has changed')
> > +
> > +    def test_vmfd_change_on_reset(self):
> > +        self.common_vm_setup()
> > +        self.run_and_check()
> > +
> > +if __name__ == '__main__':
> > +    QemuSystemTest.main()
> > --
> > 2.42.0
> >
> >
>
> With regards,
> Daniel
> --
> |: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
> |: https://libvirt.org         -o-            https://fstop138.berrange.com :|
> |: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|
>