Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions qemu/tests/cfg/win_virtio_perf_test.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
- win_virtio_perf_test:
only q35
only ovmf
no RHEL, Win10, Win11
type = win_virtio_perf_test
login_timeout = 720
start_vm = no
auto_cpu_model = yes
clone_master = yes
master_images_clone = image1
force_image_clone = yes
remove_image_image1 = yes
# support nested virtualization
HostCpuVendor.intel:
cpu_model_flags += ',vmx=on'
HostCpuVendor.amd:
cpu_model_flags += ',svm=on'
restore_ovmf_vars = yes
check_secure_boot_enabled_cmd = 'powershell -command "Confirm-SecureBootUEFI"'
dst_path = "C:\dgreadiness"
dgreadiness_path_cmd = "cd ${dst_path}\dgreadiness"
set_ps_policy_cmd = 'powershell -command "Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Force"'
vbs_enable_cmd = 'powershell -command ".\DG_Readiness_Tool_v3.6.ps1 -Enable"'
vbs_disable_cmd = 'powershell -command ".\DG_Readiness_Tool_v3.6.ps1 -Disable"'
vbs_ready_cmd = 'powershell -command ".\DG_Readiness_Tool_v3.6.ps1 -Ready"'
vbs_enable_info = 'Enabling Hyper-V and IOMMU successful'
vbs_disable_info = 'Disabling Hyper-V and IOMMU successful'
vbs_ready_info = 'HVCI, Credential-Guard, and Config-CI are enabled and running'
dg_command = 'powershell -command "Get-CimInstance -ClassName Win32_DeviceGuard'
dg_command += ' -Namespace root/Microsoft/Windows/DeviceGuard"'
# WSL2 commands
wsl_enable_cmd = 'dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart'
vm_platform_cmd = 'dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart'
wsl_set_default_cmd = 'wsl --set-default-version 2'
rhel_install_cmd = 'wsl --install -d RHEL'
wsl_list_cmd = 'wsl --list --verbose'
rhel_distro_name = 'RHEL'
rhel_test_cmd = 'wsl -d RHEL -- uname -a'
# iommu setting, currently qemu only compatible with intel model
variants:
- no_iommu:
- iommu_enable:
only HostCpuVendor.intel
machine_type_extra_params = "kernel-irqchip=split"
# iommu device
intel_iommu = yes
iommu_device_iotlb = on
iommu_eim = off
iommu_intremap = on
iommu_aw_bits = 48
# virtio device
virtio_dev_iommu_platform = on
virtio_dev_filter = '^(?:(?:virtio-)|(?:vhost-))(?!(?:user)|(?:iommu))'
# ats=on parily used with device-iotlb=on
virtio_dev_ats = on
enable_guest_iommu = yes
199 changes: 199 additions & 0 deletions qemu/tests/win_virtio_perf_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
from virttest import data_dir, env_process, error_context


@error_context.context_aware
def run(test, params, env):
"""
Please make sure the guest installed with signed driver
Verify Secure MOR control feature using Device Guard tool in Windows guest:

1) Boot up a guest.
2) Check if Secure Boot is enable.
3) Download DG_Readiness_Tool and copy to guest.
4) Enable Device Guard and check the output.
5) Reboot guest.
6) Check the result of Device Guard.
7) Disable Device Guard and shutdown guest.

:param test: QEMU test object
:param params: Dictionary with the test parameters
:param env: Dictionary with test environment.
"""

def set_powershell_execute_policy():
"""
Set PowerShell execution policy using the provided session.
It is used when creating a new session.

:param cmd: The PowerShell command to set execution policy.
"""
error_context.context("Setting PowerShell execution policy.")
status, output = session.cmd_status_output(executionPolicy_command)
if status != 0:
test.fail("Failed to set PowerShell execution policy: %s" % output)

def check_secure_boot_enabled():
Comment on lines +24 to +35
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix PowerShell policy helper to use the active session

After the WSL reboot we create new_session, but set_powershell_execute_policy() still dereferences the old session captured from the outer scope. That handle is already invalid once the guest reboots, so the execution-policy command either fails outright or silently never updates the new session, breaking the rest of the workflow. Pass the live session object into the helper so that every call (including the one right after the reboot) runs against the correct connection.

@@
-    def set_powershell_execute_policy():
-        """
-        Set PowerShell execution policy using the provided session.
-        It is used when creating a new session.
-
-        :param cmd: The PowerShell command to set execution policy.
-        """
+    def set_powershell_execute_policy(current_session):
+        """
+        Set PowerShell execution policy on the given session.
+        """
@@
-        status, output = session.cmd_status_output(executionPolicy_command)
+        status, output = current_session.cmd_status_output(executionPolicy_command)
@@
-        set_powershell_execute_policy()
+        set_powershell_execute_policy(session)
@@
-            set_powershell_execute_policy()
+            set_powershell_execute_policy(session)
@@
-        set_powershell_execute_policy()
+        set_powershell_execute_policy(new_session)

Also applies to: 111-114, 174-183

🤖 Prompt for AI Agents
In qemu/tests/win_virtio_perf_test.py around lines 24-35 (also apply same change
at 111-114 and 174-183), the helper set_powershell_execute_policy() closes over
the old session variable so after WSL reboot it uses a stale/invalid session;
change the helper signature to accept a session parameter and use that passed-in
session for session.cmd_status_output(executionPolicy_command) (and update all
callers to pass the current/live session, including immediately after creating
new_session) so the execution policy runs against the active connection.

"""
Checks if Secure Boot is enabled in the guest.
"""
error_context.context("Checking if Secure Boot is enabled in the guest")
output = session.cmd_output(check_cmd)
if "false" in output.lower():
test.fail("Secure Boot is not enabled: %s" % output)

def copy_dg_readiness_tool():
"""
Copies the Device Guard Readiness tool from the host to the guest VM.
"""
dgreadiness_host_path = data_dir.get_deps_dir("dgreadiness")
dst_path = params["dst_path"]
test.log.info("Copy Device Guard tool to guest.")
s, o = session.cmd_status_output("mkdir %s" % dst_path)
if s and "already exists" not in o:
test.error(
"Could not create Device Guard directory in "
"VM '%s', detail: '%s'" % (vm.name, o)
)
vm.copy_files_to(dgreadiness_host_path, dst_path)

def check_vbs_ready():
"""
Check the status of Virtualization-Based Security (VBS) using the provided
session.

:return: True if VBS is enabled, False otherwise.
"""
status, output = session.cmd_status_output(ready_command)
if status != 0:
test.fail("Failed to check VBS status: %s" % output)
if vbs_ready_info in output:
test.log.info("VBS is already enabled, and guest boot up successfully")
return True
else:
test.log.info(
"VBS is not enabled or the expected info was not found in the output"
)
return False

def run_device_guard_tool(cmd, expect_info):
"""
Executes the Device Guard Readiness Tool command in the guest to enable
or disable Virtualization-Based Security (VBS).

:param cmd: The command to enable or disable VBS.
"""
error_context.context("running device guard readiness tool with %s" % cmd)
output = session.cmd_output(cmd, 360)
if expect_info not in output:
test.fail("Failed to enable VBS: %s" % output)

def install_wsl2_and_rhel():
"""
Install WSL2 and start RHEL distribution in Windows VM.
This function is called after VBS verification (step 5).
"""
error_context.context("Installing WSL2 and RHEL distribution")

# Enable WSL feature
test.log.info("Enabling WSL feature...")
status, output = session.cmd_status_output(wsl_enable_cmd, timeout=300)
if status != 0:
test.fail("Failed to enable WSL feature: %s" % output)

# Enable Virtual Machine Platform
test.log.info("Enabling Virtual Machine Platform...")
status, output = session.cmd_status_output(vm_platform_cmd, timeout=300)
if status != 0:
test.fail("Failed to enable VM Platform: %s" % output)

# Reboot to apply WSL2 features
test.log.info("Rebooting to apply WSL2 features...")
vm.reboot(timeout=login_timeout)
new_session = vm.wait_for_serial_login(timeout=login_timeout)
set_powershell_execute_policy()
new_session.cmd(dgreadiness_path_command)

# Set WSL2 as default
test.log.info("Setting WSL2 as default version...")
status, output = new_session.cmd_status_output(wsl_set_default_cmd, timeout=60)
if status != 0:
test.fail("Failed to set WSL2 default: %s" % output)

# Install RHEL distribution
test.log.info("Installing RHEL distribution...")
status, output = new_session.cmd_status_output(rhel_install_cmd, timeout=600)
if status != 0:
test.fail("Failed to install RHEL: %s" % output)

# Verify WSL2 and RHEL installation
test.log.info("Verifying WSL2 and RHEL...")
status, output = new_session.cmd_status_output(wsl_list_cmd, timeout=60)
if status != 0:
test.fail("Failed to list WSL distributions: %s" % output)
if rhel_distro_name not in output:
test.fail("RHEL distribution not found: %s" % output)

# Test RHEL functionality
test.log.info("Testing RHEL in WSL2...")
status, output = new_session.cmd_status_output(rhel_test_cmd, timeout=120)
if status != 0:
test.fail("RHEL test failed: %s" % output)
test.log.info("WSL2 with RHEL installed and verified successfully")
return new_session

login_timeout = int(params.get("login_timeout", 360))
params["ovmf_vars_filename"] = "OVMF_VARS.secboot.fd"

# Force the image name to use the cloned version
vm_name = params["main_vm"]
image_name = params.get("image_name", "image")
cloned_image_name = f"{image_name}_{vm_name}"
params["image_name"] = cloned_image_name

params["start_vm"] = "yes"
env_process.preprocess_vm(test, params, env, params["main_vm"])
vm = env.get_vm(params["main_vm"])
session = vm.wait_for_serial_login(timeout=login_timeout)

check_cmd = params["check_secure_boot_enabled_cmd"]
dgreadiness_path_command = params["dgreadiness_path_cmd"]
executionPolicy_command = params["set_ps_policy_cmd"]
enable_command = params["vbs_enable_cmd"]
disable_command = params["vbs_disable_cmd"]
ready_command = params["vbs_ready_cmd"]
vbs_ready_info = params["vbs_ready_info"]
vbs_enable_info = params["vbs_enable_info"]
vbs_disable_info = params["vbs_disable_info"]
wsl_enable_cmd = params["wsl_enable_cmd"]
vm_platform_cmd = params["vm_platform_cmd"]
wsl_set_default_cmd = params["wsl_set_default_cmd"]
rhel_install_cmd = params["rhel_install_cmd"]
wsl_list_cmd = params["wsl_list_cmd"]
rhel_distro_name = params["rhel_distro_name"]
rhel_test_cmd = params["rhel_test_cmd"]

try:
check_secure_boot_enabled()
copy_dg_readiness_tool()
set_powershell_execute_policy()
session.cmd(dgreadiness_path_command)
if not check_vbs_ready():
run_device_guard_tool(enable_command, vbs_enable_info)
vm.reboot(timeout=login_timeout)
session = vm.wait_for_serial_login(timeout=login_timeout)
session.cmd(dgreadiness_path_command)
set_powershell_execute_policy()
if not check_vbs_ready():
test.fail("VBS is not enabled after reboot.")

session = install_wsl2_and_rhel()
run_device_guard_tool(disable_command, vbs_disable_info)
except Exception as e:
test.fail(f"Test failed: {e}")
else:
test.log.info("Test completed successfully.")
finally:
if vm.is_alive():
vm.destroy()
if session:
session.close()