Skip to content

Commit b4ce123

Browse files
committed
xen: Add test-ring0 tests
Signed-off-by: Tu Dinh <[email protected]>
1 parent 9020b5d commit b4ce123

File tree

3 files changed

+154
-1
lines changed

3 files changed

+154
-1
lines changed

jobs.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -367,9 +367,13 @@
367367
"description": "Testing of the Xen hypervisor itself",
368368
"requirements": [
369369
"A host with HVM FEP enabled (`hvm_fep` Xen command line parameter).",
370+
"A small VM that can be imported on the SRs.",
371+
"The host will be rebooted by the tests.",
370372
],
371373
"nb_pools": 1,
372-
"params": {},
374+
"params": {
375+
"--vm": "single/small_vm",
376+
},
373377
"paths": ["tests/xen"],
374378
},
375379
"vtpm": {

tests/xen/conftest.py

+9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from packaging import version
55

6+
from lib.host import Host
67
# Explicitly import package-scoped fixtures (see explanation in pkgfixtures.py)
78
from pkgfixtures import host_with_saved_yum_state
89

@@ -65,3 +66,11 @@ def host_with_dom0_tests(host_with_saved_yum_state):
6566
host = host_with_saved_yum_state
6667
host.yum_install(['xen-dom0-tests'])
6768
yield host
69+
70+
@pytest.fixture(scope="package")
71+
def host_with_ring0_tests(host_with_saved_yum_state: Host):
72+
host = host_with_saved_yum_state
73+
host.yum_install(['test-ring0'])
74+
yield host
75+
# clean up the loaded test modules and test states at the end
76+
host.reboot(verify=True)

tests/xen/test_ring0.py

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import logging
2+
import pytest
3+
import secrets
4+
import time
5+
from typing import Optional
6+
7+
from lib.host import Host
8+
from lib.vm import VM
9+
10+
# Requirements:
11+
# From --hosts parameter:
12+
# - host: XCP-ng host >= 8.2, reboots after test
13+
# From --vm parameter:
14+
# - A VM to import
15+
# Only XST tests with pass/fail results, and that don't crash the host were included.
16+
17+
18+
def do_execute_xst(host: Host, modname: str, testname: Optional[str] = None):
19+
if testname is None:
20+
testname = modname
21+
host.ssh(f"modprobe xst_{modname}")
22+
try:
23+
host.ssh(f"echo 1 > /sys/kernel/debug/xst/{testname}/run")
24+
host.ssh(f"grep -q 'status: pass' /sys/kernel/debug/xst/{testname}/results")
25+
finally:
26+
host.ssh(f"modprobe -r xst_{modname}", check=False)
27+
28+
29+
@pytest.mark.reboot # host_with_ring0_tests
30+
@pytest.mark.usefixtures("host_with_ring0_tests")
31+
class TestRing0Tests:
32+
def test_privcmd_restrict(self, host: Host):
33+
host.ssh("/usr/bin/privcmd-restrict_test")
34+
35+
def test_xst_alloc_balloon(self, host: Host):
36+
do_execute_xst(host, "alloc_balloon")
37+
38+
def test_xst_big_module(self, host: Host):
39+
do_execute_xst(host, "big_module")
40+
41+
def test_xst_evtchn_latency(self, host: Host):
42+
do_execute_xst(host, "evtchn_latency", "evtchn_lat")
43+
44+
@pytest.mark.skip("only makes sense for 2l evtchn")
45+
def test_xst_evtchn_limit(self, host: Host):
46+
do_execute_xst(host, "evtchn_limit")
47+
48+
def test_xst_evtchn_stress(self, host: Host):
49+
do_execute_xst(host, "evtchn_stress")
50+
51+
@pytest.mark.skip("leaks event channels infinitely")
52+
def test_xst_evtchn_unbind(self, host: Host):
53+
do_execute_xst(host, "evtchn_unbind")
54+
55+
def test_xst_get_user_pages(self, host: Host):
56+
host.ssh("modprobe xst_get_user_pages")
57+
try:
58+
host.ssh("/usr/bin/gup_test")
59+
finally:
60+
host.ssh("modprobe -r xst_get_user_pages", check=False)
61+
62+
def test_xst_grant_copy_perf(self, host: Host):
63+
do_execute_xst(host, "grant_copy_perf", "gntcpy_perf")
64+
65+
@pytest.mark.small_vm
66+
def test_xst_ioemu_msi(self, host: Host, running_unix_vm: VM):
67+
# TODO: validate MSI reception in guest
68+
vm = running_unix_vm
69+
domid = vm.param_get("dom-id")
70+
host.ssh("modprobe xst_ioemu_msi")
71+
try:
72+
host.ssh(f"echo {domid} > /sys/kernel/debug/xst/ioemu_msi/domid")
73+
host.ssh("echo 1 > /sys/kernel/debug/xst/ioemu_msi/data")
74+
host.ssh("echo 1 > /sys/kernel/debug/xst/ioemu_msi/run")
75+
host.ssh("grep -q 'status: pass' /sys/kernel/debug/xst/ioemu_msi/results")
76+
finally:
77+
host.ssh("modprobe -r xst_ioemu_msi", check=False)
78+
79+
def test_xst_livepatch(self, host: Host):
80+
"""
81+
This test loads a `livepatch_testee` module, whose test functions are
82+
updated by loading `livepatch_tester`. Distinguish between unpatched
83+
and patch functions using printk output, delimited by a random marker.
84+
85+
`livepatch_tester` also, strangely enough, causes the patched
86+
`test_function_crash` to crash the host (instead of the other way
87+
around). So don't test that.
88+
"""
89+
if host.ssh_with_result("lsmod | grep -wq livepatch_tester").returncode == 0:
90+
pytest.fail("livepatch_tester already loaded, host needs reboot")
91+
92+
try:
93+
host.ssh("modprobe livepatch_testee")
94+
95+
marker = secrets.token_hex()
96+
logging.debug(f"using pre-patch marker {marker}")
97+
host.ssh(f"echo {marker} > /dev/kmsg")
98+
host.ssh("echo 1 > /proc/livepatch_testee/cmd")
99+
host.ssh(f"dmesg | grep -A 9999 {marker} | grep -q test_function_default_old")
100+
101+
host.ssh("modprobe livepatch_tester")
102+
103+
marker = secrets.token_hex()
104+
logging.debug(f"using post-patch marker {marker}")
105+
host.ssh(f"echo {marker} > /dev/kmsg")
106+
host.ssh("echo 1 > /proc/livepatch_testee/cmd")
107+
host.ssh(f"dmesg | grep -A 9999 {marker} | grep -q test_function_default_new")
108+
finally:
109+
host.ssh("modprobe -r livepatch_testee", check=False)
110+
111+
def test_xst_memory_leak(self, host: Host):
112+
if not host.file_exists("/sys/kernel/debug/kmemleak"):
113+
pytest.skip("CONFIG_DEBUG_KMEMLEAK is not set")
114+
115+
host.ssh("modprobe xst_memory_leak")
116+
117+
try:
118+
host.ssh("echo clear > /sys/kernel/debug/kmemleak")
119+
host.ssh("echo 1 > /sys/kernel/debug/xst/memleak/run")
120+
host.ssh("modprobe -r xst_memory_leak")
121+
host.ssh("echo scan > /sys/kernel/debug/kmemleak")
122+
# scan twice with a delay inbetween, otherwise the leak may not show up
123+
time.sleep(5)
124+
host.ssh("echo scan > /sys/kernel/debug/kmemleak")
125+
host.ssh("grep -q unreferenced /sys/kernel/debug/kmemleak")
126+
finally:
127+
host.ssh("modprobe -r xst_memory_leak", check=False)
128+
129+
def test_xst_pte_set_clear_flags(self, host: Host):
130+
do_execute_xst(host, "pte_set_clear_flags")
131+
132+
def test_xst_ptwr_xchg(self, host: Host):
133+
do_execute_xst(host, "ptwr_xchg")
134+
135+
def test_xst_set_memory_uc(self, host: Host):
136+
do_execute_xst(host, "set_memory_uc")
137+
138+
@pytest.mark.skip("crashes the host, disabled by default")
139+
def test_xst_soft_lockup(self, host: Host):
140+
do_execute_xst(host, "soft_lockup")

0 commit comments

Comments
 (0)