diff mbox series

tests/functional/ppc64: add pseries migration and powernv NVMe tests

Message ID 77e89fea-0284-4e19-8ee7-04b900b13749@linux.ibm.com
State New
Headers show
Series tests/functional/ppc64: add pseries migration and powernv NVMe tests | expand

Commit Message

Aniket Sahu Aug. 30, 2026, 5:52 p.m. UTC
Add two new groups of functional tests that cover scenarios currently
missing from the ppc64 test suite:

1. pseries live migration (pseries machine type)
    - Extends the quick migration suite (already covering mac99) with
      tcp-localhost, UNIX socket, and exec (socat) migration tests for
      the pseries machine type.  This complements the existing
      test_ppc64_linux_migration test in test_pseries.py (which boots a
      full kernel) by providing lightweight no-boot migration smoke tests
      that run quickly.

2. PowerNV NVMe + network device boot (powernv machine type)
    - The existing do_test_ppc64_powernv() helper in test_powernv.py
      already boots a rootfs from NVMe for P8/P9/P10/P11.  This patch
      adds a complementary test that also verifies the e1000e network
      adapter and USB xHCI controller are probed successfully by Linux -
      previously these were present in the device args but no console
      check was made for them.
    - Adds test_powernv10_rainier() for the powernv10-rainier variant
      that models the IBM Rainier system board.

Signed-off-by: Aniket Sahu <asahu1x@linux.ibm.com>

--
2.53.0

Comments

Thomas Huth Sept. 7, 2026, 11:38 a.m. UTC | #1
On 30/08/2026 19.52, Aniket Sahu wrote:
> Add two new groups of functional tests that cover scenarios currently
> missing from the ppc64 test suite:
> 
> 1. pseries live migration (pseries machine type)
>     - Extends the quick migration suite (already covering mac99) with
>       tcp-localhost, UNIX socket, and exec (socat) migration tests for
>       the pseries machine type.  This complements the existing
>       test_ppc64_linux_migration test in test_pseries.py (which boots a
>       full kernel) by providing lightweight no-boot migration smoke tests
>       that run quickly.

Is this worth the effort? If we already have a full migration test with a 
booted kernel, what do we really gain by testing again without a kernel?

Also, you are adding two completely different tests with one patch here. I'd 
suggest to split this into two separate patches instead.

> 2. PowerNV NVMe + network device boot (powernv machine type)
>     - The existing do_test_ppc64_powernv() helper in test_powernv.py
>       already boots a rootfs from NVMe for P8/P9/P10/P11.  This patch
>       adds a complementary test that also verifies the e1000e network
>       adapter and USB xHCI controller are probed successfully by Linux -
>       previously these were present in the device args but no console
>       check was made for them.
>     - Adds test_powernv10_rainier() for the powernv10-rainier variant
>       that models the IBM Rainier system board.
> 
> Signed-off-by: Aniket Sahu <asahu1x@linux.ibm.com>
> 
> diff --git a/tests/functional/ppc64/meson.build b/tests/functional/ppc64/ 
> meson.build
> index cb3c745624..19c32c8b67 100644
> --- a/tests/functional/ppc64/meson.build
> +++ b/tests/functional/ppc64/meson.build
> @@ -1,6 +1,8 @@
>   # SPDX-License-Identifier: GPL-2.0-or-later
> 
>   test_ppc64_timeouts = {
> +  'pseries_migrate' : 60,

Default timeout for the tests is 90, please don't add something with lower 
values, ie. simply drop the above line.

...
> diff --git a/tests/functional/ppc64/test_powernv_devices.py b/tests/ 
> functional/ppc64/test_powernv_devices.py
> new file mode 100644
> index 0000000000..6135855612
> --- /dev/null
> +++ b/tests/functional/ppc64/test_powernv_devices.py
> @@ -0,0 +1,151 @@
> +#!/usr/bin/env python3
> +#
> +# Functional tests that boot Linux on powernv machines and explicitly
> +# verify that PCIe-attached devices (NVMe, e1000e, xHCI USB) are
> +# detected by the guest kernel.  Also covers the powernv10-rainier
> +# board variant.
> +#
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +
> +from qemu_test import LinuxKernelTest, Asset
> +
> +
> +class PowerNVDevicesTest(LinuxKernelTest):
> +    """
> +    Boot Linux on powernv variants and verify that PCIe devices are
> +    detected by the guest.
> +
> +    The existing test_powernv.py::do_test_ppc64_powernv() attaches an
> +    NVMe drive, an e1000e NIC, and an xHCI USB controller, but only
> +    waits for the CPU-generation string and the init process. This
> +    test adds explicit console pattern checks for each device so that
> +    regressions in device enumeration or PCI/PCIe topology are caught.
> +
> +    An additional test covers powernv10-rainier (the IBM Rainier system
> +    board variant) which has a slightly different PHB topology.
> +    """
> +
> +    timeout = 480
> +
> +    ASSET_KERNEL = Asset(
> + ('https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/'
> +         'buildroot/qemu_ppc64le_powernv8-2025.02/vmlinux'),
> + '6fd29aff9ad4362511ea5d0acbb510667c7031928e97d64ec15bbc5daf4b8151')
> +
> +    ASSET_INITRD = Asset(
> + ('https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/'
> +         'buildroot/qemu_ppc64le_powernv8-2025.02/rootfs.ext2'),
> + 'aee2192b692077c4bde31cb56ce474424b358f17cec323d5c94af3970c9aada2')
> +
> +    def setUp(self):
> +        super().setUp()
> +        self.require_accelerator('tcg')
> +
> +    def _do_test_powernv_pcie_devices(self, machine):
> +        """
> +        Boot *machine* and verify NVMe, e1000e, and xHCI are detected.
> +
> +        Device topology (matches the existing do_test_ppc64_powernv helper):
> +          pcie.2  → NVMe drive (boot device, rootfs)
> +          bridge1 → e1000e NIC (addr 0x3)
> +          bridge1 → nec-usb-xhci (addr 0x2)
> +
> +        Expected kernel log patterns checked:
> +          * "nvme nvme0" — NVMe controller probe
> +          * "e1000e"     — Intel e1000e NIC probe
> +          * "xhci_hcd"   — USB xHCI host controller probe
> +          * "Run /sbin/init as init process" — reached userland
> +        """
> +        kernel_path = self.ASSET_KERNEL.fetch()
> +        initrd_path = self.ASSET_INITRD.fetch()
> +
> +        self.set_machine(machine)
> +        self.vm.set_console()
> +        self.vm.add_args(
> +            '-kernel', kernel_path,
> +            '-drive',
> + f'file={initrd_path},format=raw,if=none,id=drive0,readonly=on',
> +            '-append', 'root=/dev/nvme0n1 console=tty0 console=hvc0',
> +            '-device', 'pcie-pci-bridge,id=bridge1,bus=pcie.1,addr=0x0',
> +            '-device', 'nvme,drive=drive0,bus=pcie.2,addr=0x0,serial=1234',
> +            '-device', 'e1000e,bus=bridge1,addr=0x3',
> +            '-device', 'nec-usb-xhci,bus=bridge1,addr=0x2',
> +        )
> +        self.vm.launch()
> +
> +        # NVMe controller should be detected first (it is the boot disk).
> +        self.wait_for_console_pattern('nvme nvme0')
> +
> +        # e1000e NIC detection.
> +        self.wait_for_console_pattern('e1000e')
> +
> +        # USB xHCI host controller detection.
> +        self.wait_for_console_pattern('xhci_hcd')
> +
> +        # System reached userland — final sanity check.
> +        self.wait_for_console_pattern('Run /sbin/init as init process')
> +
> +    def test_powernv8_pcie_devices(self):
> +        """powernv8 (P8): NVMe + e1000e + xHCI detected."""
> +        self._do_test_powernv_pcie_devices('powernv8')
> +
> +    def test_powernv9_pcie_devices(self):
> +        """powernv9 (P9): NVMe + e1000e + xHCI detected."""
> +        self._do_test_powernv_pcie_devices('powernv9')
> +
> +    def test_powernv10_pcie_devices(self):
> +        """powernv10 (P10): NVMe + e1000e + xHCI detected."""
> +        self._do_test_powernv_pcie_devices('powernv10')
> +
> +    def test_powernv11_pcie_devices(self):
> +        """powernv11 (P11): NVMe + e1000e + xHCI detected."""
> +        self._do_test_powernv_pcie_devices('powernv11')

Booting a kernel always takes a lot of time. So please don't add new test 
for this. If you feel like we really should check for those PCIe devices, 
please extend the existing test in tests/functional/ppc64/test_powernv.py 
instead.

  Thanks,
   Thomas
Aniket Sahu Sept. 8, 2026, 6:44 a.m. UTC | #2
Hi Thomas,

Thanks for reviewing my patch!

On 07/09/26 5:08 PM, Thomas Huth wrote:
> On 30/08/2026 19.52, Aniket Sahu wrote:
>> Add two new groups of functional tests that cover scenarios currently
>> missing from the ppc64 test suite:
>>
>> 1. pseries live migration (pseries machine type)
>>     - Extends the quick migration suite (already covering mac99) with
>>       tcp-localhost, UNIX socket, and exec (socat) migration tests for
>>       the pseries machine type.  This complements the existing
>>       test_ppc64_linux_migration test in test_pseries.py (which boots a
>>       full kernel) by providing lightweight no-boot migration smoke 
>> tests
>>       that run quickly.
>
> Is this worth the effort? If we already have a full migration test 
> with a booted kernel, what do we really gain by testing again without 
> a kernel?
The full migration tests are longer and part of the thorough execution 
cycle. Moreover, the full migration test only exercises migration with 
TCP-localhost. The tests defined add a quick TCP-localhost test, along 
with UNIX socket and socat migration tests. The idea was I saw these 
tests were covered for mac99 in tests/functional/ppc64/test_migration.py 
and I wanted to add those for powervm and powernv too. These would run 
within a few seconds and will be covered in the quick cycle, acting as 
smoke tests for all the migration paths. Perhaps we can consider keeping 
these tests as a quick regression check, or remove the no boot tests 
entirely while also expanding the full-boot tests with UNIX socket and 
socat migration path tests?
>
> Also, you are adding two completely different tests with one patch 
> here. I'd suggest to split this into two separate patches instead.
Ack, will address in V2 series.
>
>> 2. PowerNV NVMe + network device boot (powernv machine type)
>>     - The existing do_test_ppc64_powernv() helper in test_powernv.py
>>       already boots a rootfs from NVMe for P8/P9/P10/P11.  This patch
>>       adds a complementary test that also verifies the e1000e network
>>       adapter and USB xHCI controller are probed successfully by Linux -
>>       previously these were present in the device args but no console
>>       check was made for them.
>>     - Adds test_powernv10_rainier() for the powernv10-rainier variant
>>       that models the IBM Rainier system board.
>>
>> Signed-off-by: Aniket Sahu <asahu1x@linux.ibm.com>
>>
>> diff --git a/tests/functional/ppc64/meson.build 
>> b/tests/functional/ppc64/ meson.build
>> index cb3c745624..19c32c8b67 100644
>> --- a/tests/functional/ppc64/meson.build
>> +++ b/tests/functional/ppc64/meson.build
>> @@ -1,6 +1,8 @@
>>   # SPDX-License-Identifier: GPL-2.0-or-later
>>
>>   test_ppc64_timeouts = {
>> +  'pseries_migrate' : 60,
>
> Default timeout for the tests is 90, please don't add something with 
> lower values, ie. simply drop the above line.
Ack. Will address in V2
>
> ...
>> diff --git a/tests/functional/ppc64/test_powernv_devices.py b/tests/ 
>> functional/ppc64/test_powernv_devices.py
>> new file mode 100644
>> index 0000000000..6135855612
>> --- /dev/null
>> +++ b/tests/functional/ppc64/test_powernv_devices.py
>> @@ -0,0 +1,151 @@
>> +#!/usr/bin/env python3
>> +#
>> +# Functional tests that boot Linux on powernv machines and explicitly
>> +# verify that PCIe-attached devices (NVMe, e1000e, xHCI USB) are
>> +# detected by the guest kernel.  Also covers the powernv10-rainier
>> +# board variant.
>> +#
>> +# SPDX-License-Identifier: GPL-2.0-or-later
>> +
>> +from qemu_test import LinuxKernelTest, Asset
>> +
>> +
>> +class PowerNVDevicesTest(LinuxKernelTest):
>> +    """
>> +    Boot Linux on powernv variants and verify that PCIe devices are
>> +    detected by the guest.
>> +
>> +    The existing test_powernv.py::do_test_ppc64_powernv() attaches an
>> +    NVMe drive, an e1000e NIC, and an xHCI USB controller, but only
>> +    waits for the CPU-generation string and the init process. This
>> +    test adds explicit console pattern checks for each device so that
>> +    regressions in device enumeration or PCI/PCIe topology are caught.
>> +
>> +    An additional test covers powernv10-rainier (the IBM Rainier system
>> +    board variant) which has a slightly different PHB topology.
>> +    """
>> +
>> +    timeout = 480
>> +
>> +    ASSET_KERNEL = Asset(
>> + ('https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/'
>> +         'buildroot/qemu_ppc64le_powernv8-2025.02/vmlinux'),
>> + '6fd29aff9ad4362511ea5d0acbb510667c7031928e97d64ec15bbc5daf4b8151')
>> +
>> +    ASSET_INITRD = Asset(
>> + ('https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/'
>> +  'buildroot/qemu_ppc64le_powernv8-2025.02/rootfs.ext2'),
>> + 'aee2192b692077c4bde31cb56ce474424b358f17cec323d5c94af3970c9aada2')
>> +
>> +    def setUp(self):
>> +        super().setUp()
>> +        self.require_accelerator('tcg')
>> +
>> +    def _do_test_powernv_pcie_devices(self, machine):
>> +        """
>> +        Boot *machine* and verify NVMe, e1000e, and xHCI are detected.
>> +
>> +        Device topology (matches the existing do_test_ppc64_powernv 
>> helper):
>> +          pcie.2  → NVMe drive (boot device, rootfs)
>> +          bridge1 → e1000e NIC (addr 0x3)
>> +          bridge1 → nec-usb-xhci (addr 0x2)
>> +
>> +        Expected kernel log patterns checked:
>> +          * "nvme nvme0" — NVMe controller probe
>> +          * "e1000e"     — Intel e1000e NIC probe
>> +          * "xhci_hcd"   — USB xHCI host controller probe
>> +          * "Run /sbin/init as init process" — reached userland
>> +        """
>> +        kernel_path = self.ASSET_KERNEL.fetch()
>> +        initrd_path = self.ASSET_INITRD.fetch()
>> +
>> +        self.set_machine(machine)
>> +        self.vm.set_console()
>> +        self.vm.add_args(
>> +            '-kernel', kernel_path,
>> +            '-drive',
>> + f'file={initrd_path},format=raw,if=none,id=drive0,readonly=on',
>> +            '-append', 'root=/dev/nvme0n1 console=tty0 console=hvc0',
>> +            '-device', 
>> 'pcie-pci-bridge,id=bridge1,bus=pcie.1,addr=0x0',
>> +            '-device', 
>> 'nvme,drive=drive0,bus=pcie.2,addr=0x0,serial=1234',
>> +            '-device', 'e1000e,bus=bridge1,addr=0x3',
>> +            '-device', 'nec-usb-xhci,bus=bridge1,addr=0x2',
>> +        )
>> +        self.vm.launch()
>> +
>> +        # NVMe controller should be detected first (it is the boot 
>> disk).
>> +        self.wait_for_console_pattern('nvme nvme0')
>> +
>> +        # e1000e NIC detection.
>> +        self.wait_for_console_pattern('e1000e')
>> +
>> +        # USB xHCI host controller detection.
>> +        self.wait_for_console_pattern('xhci_hcd')
>> +
>> +        # System reached userland — final sanity check.
>> +        self.wait_for_console_pattern('Run /sbin/init as init process')
>> +
>> +    def test_powernv8_pcie_devices(self):
>> +        """powernv8 (P8): NVMe + e1000e + xHCI detected."""
>> +        self._do_test_powernv_pcie_devices('powernv8')
>> +
>> +    def test_powernv9_pcie_devices(self):
>> +        """powernv9 (P9): NVMe + e1000e + xHCI detected."""
>> +        self._do_test_powernv_pcie_devices('powernv9')
>> +
>> +    def test_powernv10_pcie_devices(self):
>> +        """powernv10 (P10): NVMe + e1000e + xHCI detected."""
>> +        self._do_test_powernv_pcie_devices('powernv10')
>> +
>> +    def test_powernv11_pcie_devices(self):
>> +        """powernv11 (P11): NVMe + e1000e + xHCI detected."""
>> +        self._do_test_powernv_pcie_devices('powernv11')
>
> Booting a kernel always takes a lot of time. So please don't add new 
> test for this. If you feel like we really should check for those PCIe 
> devices, please extend the existing test in 
> tests/functional/ppc64/test_powernv.py instead.

Ack, it seems the devices are already covered in test_powernv.py, the 
only difference being the console checks are not done, as udev probing 
is not reliable according to the comments left by you.

 > +    def test_powernv10_rainier_pcie_devices(self):
 > +        """
 > +        powernv10-rainier: NVMe + e1000e + xHCI detected.
 > +
 > +        The Rainier board variant maps PCIe root ports slightly
 > +        differently from the default powernv10 topology. Verify that
 > +        the same device set is enumerated successfully.
 > +        """
 > + self._do_test_powernv_pcie_devices('powernv10-rainier')

However, the rainier variant test is a new addition. Will raise a patch 
as part of V2 series adding just this test to test_powernv.py.

Thanks and Regards,
Aniket.
diff mbox series

Patch

diff --git a/tests/functional/ppc64/meson.build 
b/tests/functional/ppc64/meson.build
index cb3c745624..19c32c8b67 100644
--- a/tests/functional/ppc64/meson.build
+++ b/tests/functional/ppc64/meson.build
@@ -1,6 +1,8 @@ 
  # SPDX-License-Identifier: GPL-2.0-or-later

  test_ppc64_timeouts = {
+  'pseries_migrate' : 60,
+  'powernv_devices' : 480,
    'fadump' : 480,
    'hv' : 1000,
    'mac99' : 120,
@@ -14,12 +16,14 @@  test_ppc64_timeouts = {
  tests_ppc64_system_quick = [
    'migration',
    'vmstate',
+  'pseries_migrate',
  ]

  tests_ppc64_system_thorough = [
    'e500',
    'fadump',
    'hv',
+  'powernv_devices',
    'mac99',
    'openbsd',
    'powernv',
diff --git a/tests/functional/ppc64/test_powernv_devices.py 
b/tests/functional/ppc64/test_powernv_devices.py
new file mode 100644
index 0000000000..6135855612
--- /dev/null
+++ b/tests/functional/ppc64/test_powernv_devices.py
@@ -0,0 +1,151 @@ 
+#!/usr/bin/env python3
+#
+# Functional tests that boot Linux on powernv machines and explicitly
+# verify that PCIe-attached devices (NVMe, e1000e, xHCI USB) are
+# detected by the guest kernel.  Also covers the powernv10-rainier
+# board variant.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import LinuxKernelTest, Asset
+
+
+class PowerNVDevicesTest(LinuxKernelTest):
+    """
+    Boot Linux on powernv variants and verify that PCIe devices are
+    detected by the guest.
+
+    The existing test_powernv.py::do_test_ppc64_powernv() attaches an
+    NVMe drive, an e1000e NIC, and an xHCI USB controller, but only
+    waits for the CPU-generation string and the init process. This
+    test adds explicit console pattern checks for each device so that
+    regressions in device enumeration or PCI/PCIe topology are caught.
+
+    An additional test covers powernv10-rainier (the IBM Rainier system
+    board variant) which has a slightly different PHB topology.
+    """
+
+    timeout = 480
+
+    ASSET_KERNEL = Asset(
+ ('https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/'
+         'buildroot/qemu_ppc64le_powernv8-2025.02/vmlinux'),
+ '6fd29aff9ad4362511ea5d0acbb510667c7031928e97d64ec15bbc5daf4b8151')
+
+    ASSET_INITRD = Asset(
+ ('https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/'
+         'buildroot/qemu_ppc64le_powernv8-2025.02/rootfs.ext2'),
+ 'aee2192b692077c4bde31cb56ce474424b358f17cec323d5c94af3970c9aada2')
+
+    def setUp(self):
+        super().setUp()
+        self.require_accelerator('tcg')
+
+    def _do_test_powernv_pcie_devices(self, machine):
+        """
+        Boot *machine* and verify NVMe, e1000e, and xHCI are detected.
+
+        Device topology (matches the existing do_test_ppc64_powernv 
helper):
+          pcie.2  → NVMe drive (boot device, rootfs)
+          bridge1 → e1000e NIC (addr 0x3)
+          bridge1 → nec-usb-xhci (addr 0x2)
+
+        Expected kernel log patterns checked:
+          * "nvme nvme0" — NVMe controller probe
+          * "e1000e"     — Intel e1000e NIC probe
+          * "xhci_hcd"   — USB xHCI host controller probe
+          * "Run /sbin/init as init process" — reached userland
+        """
+        kernel_path = self.ASSET_KERNEL.fetch()
+        initrd_path = self.ASSET_INITRD.fetch()
+
+        self.set_machine(machine)
+        self.vm.set_console()
+        self.vm.add_args(
+            '-kernel', kernel_path,
+            '-drive',
+ f'file={initrd_path},format=raw,if=none,id=drive0,readonly=on',
+            '-append', 'root=/dev/nvme0n1 console=tty0 console=hvc0',
+            '-device', 'pcie-pci-bridge,id=bridge1,bus=pcie.1,addr=0x0',
+            '-device', 'nvme,drive=drive0,bus=pcie.2,addr=0x0,serial=1234',
+            '-device', 'e1000e,bus=bridge1,addr=0x3',
+            '-device', 'nec-usb-xhci,bus=bridge1,addr=0x2',
+        )
+        self.vm.launch()
+
+        # NVMe controller should be detected first (it is the boot disk).
+        self.wait_for_console_pattern('nvme nvme0')
+
+        # e1000e NIC detection.
+        self.wait_for_console_pattern('e1000e')
+
+        # USB xHCI host controller detection.
+        self.wait_for_console_pattern('xhci_hcd')
+
+        # System reached userland — final sanity check.
+        self.wait_for_console_pattern('Run /sbin/init as init process')
+
+    def test_powernv8_pcie_devices(self):
+        """powernv8 (P8): NVMe + e1000e + xHCI detected."""
+        self._do_test_powernv_pcie_devices('powernv8')
+
+    def test_powernv9_pcie_devices(self):
+        """powernv9 (P9): NVMe + e1000e + xHCI detected."""
+        self._do_test_powernv_pcie_devices('powernv9')
+
+    def test_powernv10_pcie_devices(self):
+        """powernv10 (P10): NVMe + e1000e + xHCI detected."""
+        self._do_test_powernv_pcie_devices('powernv10')
+
+    def test_powernv11_pcie_devices(self):
+        """powernv11 (P11): NVMe + e1000e + xHCI detected."""
+        self._do_test_powernv_pcie_devices('powernv11')
+
+    def test_powernv10_rainier_pcie_devices(self):
+        """
+        powernv10-rainier: NVMe + e1000e + xHCI detected.
+
+        The Rainier board variant maps PCIe root ports slightly
+        differently from the default powernv10 topology.  Verify that
+        the same device set is enumerated successfully.
+        """
+        self._do_test_powernv_pcie_devices('powernv10-rainier')
+
+    def test_powernv9_hpt_pcie_devices(self):
+        """
+        powernv9 booted with disable_radix (HPT mode): verify devices.
+
+        Radix MMU is the default on P9.  Force the HPT (Hash Page Table)
+        MMU path to exercise an alternative translation code path while
+        still ensuring PCI devices are enumerated correctly.
+        """
+        kernel_path = self.ASSET_KERNEL.fetch()
+        initrd_path = self.ASSET_INITRD.fetch()
+
+        self.set_machine('powernv9')
+        self.vm.set_console()
+        self.vm.add_args(
+            '-kernel', kernel_path,
+            '-drive',
+ f'file={initrd_path},format=raw,if=none,id=drive0,readonly=on',
+            '-append',
+            'root=/dev/nvme0n1 console=tty0 console=hvc0 disable_radix',
+            '-device', 'pcie-pci-bridge,id=bridge1,bus=pcie.1,addr=0x0',
+            '-device', 'nvme,drive=drive0,bus=pcie.2,addr=0x0,serial=1234',
+            '-device', 'e1000e,bus=bridge1,addr=0x3',
+            '-device', 'nec-usb-xhci,bus=bridge1,addr=0x2',
+        )
+        self.vm.launch()
+
+        # HPT-specific boot message.
+        self.wait_for_console_pattern('hash-mmu: Initializing hash mmu')
+
+        # Device checks same as the radix path.
+        self.wait_for_console_pattern('nvme nvme0')
+        self.wait_for_console_pattern('e1000e')
+        self.wait_for_console_pattern('xhci_hcd')
+        self.wait_for_console_pattern('Run /sbin/init as init process')
+
+
+if __name__ == '__main__':
+    PowerNVDevicesTest.main()
diff --git a/tests/functional/ppc64/test_pseries_migrate.py 
b/tests/functional/ppc64/test_pseries_migrate.py
new file mode 100644
index 0000000000..0cb929e35f
--- /dev/null
+++ b/tests/functional/ppc64/test_pseries_migrate.py
@@ -0,0 +1,57 @@ 
+#!/usr/bin/env python3
+#
+# Lightweight (no-boot) migration smoke tests for the pseries machine type.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from migration import MigrationTest
+
+
+class PseriesMigrationTest(MigrationTest):
+    """
+    Lightweight migration smoke tests for pseries.
+
+    No kernel is booted — QEMU is launched with -nodefaults and
+    immediately migrated so the tests run in a few seconds.  This
+    catches regressions in the pseries vmstate save/restore path
+    without the overhead of a full kernel boot.
+
+    These complement the existing test_ppc64_linux_migration test in
+    test_pseries.py which exercises migration mid-boot.
+    """
+
+    timeout = 60
+
+    def test_pseries_migration_with_tcp_localhost(self):
+        """Basic TCP-localhost migration for pseries."""
+        self.set_machine('pseries')
+        self.migration_with_tcp_localhost()
+
+    def test_pseries_migration_with_unix(self):
+        """UNIX socket migration for pseries."""
+        self.set_machine('pseries')
+        self.migration_with_unix()
+
+    def test_pseries_migration_with_exec(self):
+        """exec (socat) migration for pseries."""
+        self.set_machine('pseries')
+        self.migration_with_exec()
+
+    def test_powernv_migration_with_tcp_localhost(self):
+        """Basic TCP-localhost migration for powernv."""
+        self.set_machine('powernv')
+        self.migration_with_tcp_localhost()
+
+    def test_powernv_migration_with_unix(self):
+        """UNIX socket migration for powernv."""
+        self.set_machine('powernv')
+        self.migration_with_unix()
+
+    def test_powernv_migration_with_exec(self):
+        """exec (socat) migration for powernv."""
+        self.set_machine('powernv')
+        self.migration_with_exec()
+
+
+if __name__ == '__main__':
+    MigrationTest.main()