Daniel On Fri, Jul 17, 2026 at 6:56 PM Daniel Henrique Barboza <[email protected]> wrote: > > > > On 7/14/2026 4:56 AM, Subrahmanya Lingappa wrote: > > Boot an RPMI-enabled RISC-V virt guest and exercise the initial HSM, > > system suspend, and system reset paths. > > > > Signed-off-by: Subrahmanya Lingappa <[email protected]> > > --- > > tests/functional/riscv64/meson.build | 2 + > > tests/functional/riscv64/test_rpmi_virt.py | 172 +++++++++++++++++++++ > > 2 files changed, 174 insertions(+) > > create mode 100644 tests/functional/riscv64/test_rpmi_virt.py > > > > diff --git a/tests/functional/riscv64/meson.build > > b/tests/functional/riscv64/meson.build > > index 5871211e89..619a0735fa 100644 > > --- a/tests/functional/riscv64/meson.build > > +++ b/tests/functional/riscv64/meson.build > > @@ -3,6 +3,7 @@ > > test_riscv64_timeouts = { > > 'boston' : 120, > > 'tuxrun' : 120, > > + 'rpmi_virt' : 300, > > } > > > > tests_riscv64_system_quick = [ > > @@ -15,4 +16,5 @@ tests_riscv64_system_thorough = [ > > 'boston', > > 'sifive_u', > > 'tuxrun', > > + 'rpmi_virt', > > ] > > diff --git a/tests/functional/riscv64/test_rpmi_virt.py > > b/tests/functional/riscv64/test_rpmi_virt.py > > new file mode 100644 > > index 0000000000..c0f96f7d8d > > --- /dev/null > > +++ b/tests/functional/riscv64/test_rpmi_virt.py > > @@ -0,0 +1,172 @@ > > +#!/usr/bin/env python3 > > +# > > +# RISC-V virt RPMI Linux guest integration tests > > +# > > +# Copyright (c) 2026 Ventana Micro Systems Inc. > > We can't add a Ventana copyright dated 2026. Ventana as an entity ceased to > exist December 2025. > > > Everything else LGTM. Thanks, > Daniel > missed it before, Fixed in v4. I dropped the stale Ventana Micro Systems Inc. copyright line from the functional test.
thanks, subbu > > > +# Copyright (c) 2026 Qualcomm Technologies, Inc. > > +# > > +# Author: > > +# Subrahmanya Lingappa <[email protected]> > > +# > > +# SPDX-License-Identifier: GPL-2.0-or-later > > + > > +import os > > +from pathlib import Path > > +import subprocess > > +import time > > + > > +from qemu_test import QemuSystemTest > > +from qemu_test import exec_command > > +from qemu_test import exec_command_and_wait_for_pattern > > +from qemu_test import get_qemu_img > > +from qemu_test import wait_for_console_pattern > > + > > + > > +class RiscvVirtRpmiGuestTest(QemuSystemTest): > > + """Boot Linux and exercise RPMI-backed services through guest APIs. > > + > > + This test intentionally keeps guest artifacts external. Set: > > + > > + QEMU_TEST_RPMI_OPENSBI=/path/to/fw_jump.bin > > + QEMU_TEST_RPMI_KERNEL=/path/to/Image > > + QEMU_TEST_RPMI_ROOTFS=/path/to/rootfs.ext4 > > + > > + Exact RPMI packet command-ID coverage remains in riscv-rpmi qtests. > > This > > + functional test verifies Linux/OpenSBI integration paths visible from a > > + real guest without adding probe hooks to production RPMI sources. > > + """ > > + > > + timeout = 360 > > + PROMPT = 'root@tuxtest:~#' > > + > > + def _require_path(self, env_name): > > + value = os.getenv(env_name) > > + if not value: > > + self.skipTest(f'{env_name} is required') > > + path = Path(value) > > + if not path.exists(): > > + self.skipTest(f'{env_name} does not exist: {path}') > > + return path > > + > > + def setUp(self): > > + super().setUp() > > + self.opensbi = self._require_path('QEMU_TEST_RPMI_OPENSBI') > > + self.kernel = self._require_path('QEMU_TEST_RPMI_KERNEL') > > + self.rootfs = self._require_path('QEMU_TEST_RPMI_ROOTFS') > > + self.qemu_img = get_qemu_img(self) > > + > > + def _create_rootfs_overlay(self): > > + overlay = Path(self.scratch_file('rootfs.qcow2')) > > + subprocess.run([ > > + self.qemu_img, 'create', '-q', '-f', 'qcow2', '-F', 'raw', > > + '-b', str(self.rootfs), str(overlay), > > + ], check=True) > > + return overlay > > + > > + def _boot_guest(self, smp=4): > > + self.set_machine('virt') > > + self.machine = 'virt,rpmi=on,aia=aplic-imsic' > > + rootfs_overlay = self._create_rootfs_overlay() > > + > > + self.vm.set_console() > > + self.vm.add_args( > > + '-cpu', 'rv64', > > + '-smp', str(smp), > > + '-m', '1G', > > + '-bios', str(self.opensbi), > > + '-kernel', str(self.kernel), > > + '-append', 'printk.time=0 root=/dev/vda rw console=ttyS0 ' > > + 'earlycon=sbi loglevel=8 no_console_suspend', > > + '-blockdev', 'driver=qcow2,file.driver=file,' > > + f'file.filename={rootfs_overlay},node-name=hd0', > > + '-device', 'virtio-blk-device,drive=hd0', > > + ) > > + self.vm.launch() > > + > > + def _expect_rpmi_firmware_and_linux(self): > > + patterns = [ > > + 'Platform HSM Device : rpmi-hsm', > > + 'Platform Suspend Device : rpmi-system-suspend', > > + 'Standard SBI Extensions', > > + 'susp', > > + 'tuxtest login:', > > + ] > > + for pattern in patterns: > > + wait_for_console_pattern(self, pattern) > > + exec_command_and_wait_for_pattern(self, 'root', self.PROMPT) > > + > > + def _run_marker_command(self, command, marker, failure_marker=None): > > + out = exec_command_and_wait_for_pattern(self, command, marker, > > + > > failure_message=failure_marker) > > + self.assertIn(marker.encode(), out) > > + return out > > + > > + def _validate_hsm_boot_start(self, online_cpus): > > + self._run_marker_command( > > + 'echo RPMI_LINUX_HSM_START_BEGIN; ' > > + 'cat /sys/devices/system/cpu/present; ' > > + 'online=$(cat /sys/devices/system/cpu/online); ' > > + 'echo "$online"; ' > > + f'if [ "$online" = "{online_cpus}" ]; ' > > + 'then echo RPMI_LINUX_HSM_START_PASS; ' > > + 'else echo RPMI_LINUX_HSM_START_FAIL; fi', > > + 'RPMI_LINUX_HSM_START_PASS', 'RPMI_LINUX_HSM_START_FAIL') > > + > > + def _validate_hsm_stop(self): > > + self._run_marker_command( > > + 'echo RPMI_LINUX_HSM_STOP_BEGIN; ' > > + 'if [ -w /sys/devices/system/cpu/cpu1/online ]; then ' > > + 'echo 0 > /sys/devices/system/cpu/cpu1/online && ' > > + '[ "$(cat /sys/devices/system/cpu/online)" = 0 ] && ' > > + 'echo RPMI_LINUX_HSM_STOP_PASS || echo > > RPMI_LINUX_HSM_STOP_FAIL; ' > > + 'else echo RPMI_LINUX_HSM_STOP_FAIL; fi', > > + 'RPMI_LINUX_HSM_STOP_PASS', 'RPMI_LINUX_HSM_STOP_FAIL') > > + > > + def _validate_system_suspend(self): > > + exec_command( > > + self, > > + 'echo RPMI_LINUX_SUSPEND_BEGIN; ' > > + 'if grep -qw mem /sys/power/state; then ' > > + 'echo mem > /sys/power/state; ' > > + 'else echo RPMI_LINUX_SUSPEND_FAIL; fi') > > + wait_for_console_pattern(self, 'RPMI_LINUX_SUSPEND_BEGIN') > > + wait_for_console_pattern(self, 'PM: suspend entry') > > + self.vm.event_wait('SUSPEND', 10) > > + self.vm.qmp('system_wakeup') > > + self.vm.event_wait('WAKEUP', 10) > > + wait_for_console_pattern(self, 'PM: suspend exit') > > + wait_for_console_pattern(self, self.PROMPT) > > + self._run_marker_command( > > + 'marker=RPMI_LINUX_WAKEUP; echo ${marker}_PASS', > > + 'RPMI_LINUX_WAKEUP_PASS') > > + > > + def _validate_reset_poweroff(self): > > + exec_command(self, 'echo RPMI_LINUX_RESET_POWEROFF_BEGIN; poweroff > > -f') > > + wait_for_console_pattern(self, 'RPMI_LINUX_RESET_POWEROFF_BEGIN') > > + wait_for_console_pattern(self, 'reboot: Power down') > > + self.vm.wait() > > + > > + def test_linux_guest_service_enumeration(self): > > + self._boot_guest(smp=4) > > + self._expect_rpmi_firmware_and_linux() > > + self._validate_hsm_boot_start('0-3') > > + > > + def test_linux_guest_hsm_stop(self): > > + self._boot_guest(smp=2) > > + self._expect_rpmi_firmware_and_linux() > > + self._validate_hsm_boot_start('0-1') > > + self._validate_hsm_stop() > > + > > + def test_linux_guest_suspend(self): > > + self._boot_guest(smp=1) > > + self._expect_rpmi_firmware_and_linux() > > + self._validate_system_suspend() > > + > > + def test_linux_guest_reset_poweroff(self): > > + self._boot_guest(smp=1) > > + self._expect_rpmi_firmware_and_linux() > > + self._validate_reset_poweroff() > > + > > + > > +if __name__ == '__main__': > > + QemuSystemTest.main() >
