Skip to content

Commit 86e904b

Browse files
authored
Merge pull request #346 from xcp-ng/abo/test-xen-platform-pci-bar-uc-hvmloader-config
hvmloader: check the cache mode of grant-tables
2 parents 773aec1 + c1db7ff commit 86e904b

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import pytest
2+
3+
import logging
4+
import os
5+
import re
6+
7+
# AMD grant-tables cachability parameter tests.
8+
# This file contains 2 tests to check if the hvmloader PCI bar fix is applied or not
9+
# by xenopsd. Tests check the xenopsd configuration and then compare with what is
10+
# seen inside the VM. If the grant-tables are cached, it means the fix is applied.
11+
#
12+
# Requirements:
13+
# - At least one XCP-ng host (>=8.3)
14+
# - A Linux VM
15+
16+
def xen_platform_pci_id(vm):
17+
pci_path = vm.ssh(['ls', '-d', '/sys/bus/pci/drivers/xen-platform-pci/0000:*'])
18+
if pci_path is not None:
19+
return os.path.basename(pci_path)
20+
pytest.fail("'xen-platform-pci' PCI not found")
21+
22+
def xen_platform_pci_io_address(vm, xen_platform_pci_id):
23+
# Find 'xen-platform-pci' IO mem resource address.
24+
pci_resource_output = vm.ssh(
25+
['cat', '/sys/devices/pci0000:00/{}/resource'.format(xen_platform_pci_id)])
26+
27+
# First line is taken by PCI IO port, select 2nd line for IO mem.
28+
address_line = pci_resource_output.splitlines()[1].split()
29+
start_address = int(address_line[0], 16)
30+
return start_address
31+
32+
def mtrr_ranges(vm):
33+
# List and check MTRR ranges.
34+
return vm.ssh(['cat', '/proc/mtrr']).splitlines()
35+
36+
def are_grant_tables_inside_uncachable_mapping(mtrr_ranges_list, pci_io_address):
37+
regexp = r'reg(.*): base=(0x[0-9a-f]*) \(.*\), size=(.*)MB, count=(.*): (.*)'
38+
39+
for mtrr_range in mtrr_ranges_list:
40+
m = re.match(regexp, mtrr_range)
41+
base_address = int(m.group(2), 16)
42+
size = int(m.group(3)) * 1024 * 1024
43+
cache_mode = m.group(5)
44+
45+
# Check that PCI io memory address is inside MTRR configuration.
46+
if pci_io_address >= base_address and \
47+
pci_io_address < base_address + size and cache_mode == "uncachable":
48+
return True
49+
return False
50+
51+
@pytest.mark.usefixtures("host_at_least_8_3")
52+
@pytest.mark.small_vm
53+
@pytest.mark.usefixtures("running_unix_vm")
54+
class TestXenPlatformPciBarUc:
55+
@pytest.fixture
56+
def host_with_xen_platform_pci_bar_uc_set_to_true(self, host):
57+
host.ssh(['echo', 'xen-platform-pci-bar-uc=true', '>', '/etc/xenopsd.conf.d/hvmloader.conf'])
58+
host.restart_toolstack(verify=True)
59+
yield host
60+
host.ssh(['rm', '/etc/xenopsd.conf.d/hvmloader.conf'])
61+
host.restart_toolstack(verify=True)
62+
63+
@pytest.fixture
64+
def vm_with_xen_platform_pci_bar_uc_set_to_true(self, host_with_xen_platform_pci_bar_uc_set_to_true, unix_vm):
65+
if unix_vm.is_running():
66+
unix_vm.shutdown(verify=True)
67+
unix_vm.start(on=host_with_xen_platform_pci_bar_uc_set_to_true.uuid)
68+
unix_vm.wait_for_vm_running_and_ssh_up()
69+
return unix_vm
70+
71+
@pytest.fixture
72+
def host_with_xen_platform_pci_bar_uc_set_to_false(self, host):
73+
host.ssh(['echo', 'xen-platform-pci-bar-uc=false', '>', '/etc/xenopsd.conf.d/hvmloader.conf'])
74+
host.restart_toolstack(verify=True)
75+
yield host
76+
host.ssh(['rm', '/etc/xenopsd.conf.d/hvmloader.conf'])
77+
host.restart_toolstack(verify=True)
78+
79+
@pytest.fixture
80+
def vm_with_xen_platform_pci_bar_uc_set_to_false(self, host_with_xen_platform_pci_bar_uc_set_to_false, unix_vm):
81+
if unix_vm.is_running():
82+
unix_vm.shutdown(verify=True)
83+
unix_vm.start(on=host_with_xen_platform_pci_bar_uc_set_to_false.uuid)
84+
unix_vm.wait_for_vm_running_and_ssh_up()
85+
return unix_vm
86+
87+
# Check the default behavior when 'xen_platform_pci_bar_uc' is true
88+
def test_xen_platform_pci_bar_uc_true(self, host_with_xen_platform_pci_bar_uc_set_to_true,
89+
vm_with_xen_platform_pci_bar_uc_set_to_true):
90+
pci_id = xen_platform_pci_id(vm_with_xen_platform_pci_bar_uc_set_to_true)
91+
pci_io_address = xen_platform_pci_io_address(vm_with_xen_platform_pci_bar_uc_set_to_true, pci_id)
92+
logging.info(f"'xen-platform-pci' PCI IO mem address is 0x{pci_io_address:016X}")
93+
mtrr_ranges_list = mtrr_ranges(vm_with_xen_platform_pci_bar_uc_set_to_true)
94+
95+
if are_grant_tables_inside_uncachable_mapping(mtrr_ranges_list, pci_io_address):
96+
logging.info("Grant-tables are inside the 'uncachable' mapping as expected.")
97+
else:
98+
pytest.fail("Grant_tables are outside of the uncachable MTRR ranges but 'xen-platform-pci-bar-uc' is true")
99+
100+
# Check the alternate behavior when 'xen_platform_pci_bar_uc' is explicitely set to false
101+
def test_xen_platform_pci_bar_uc_false(self, host_with_xen_platform_pci_bar_uc_set_to_false,
102+
vm_with_xen_platform_pci_bar_uc_set_to_false):
103+
pci_id = xen_platform_pci_id(vm_with_xen_platform_pci_bar_uc_set_to_false)
104+
pci_io_address = xen_platform_pci_io_address(vm_with_xen_platform_pci_bar_uc_set_to_false, pci_id)
105+
logging.info(f"'xen-platform-pci' PCI IO mem address is 0x{pci_io_address:016X}")
106+
mtrr_ranges_list = mtrr_ranges(vm_with_xen_platform_pci_bar_uc_set_to_false)
107+
108+
if are_grant_tables_inside_uncachable_mapping(mtrr_ranges_list, pci_io_address):
109+
pytest.fail("Grant-tables are inside of the uncachable MTRR ranges but 'xen-platform-pci-bar-uc' is false.")
110+
else:
111+
logging.info("Grant-tables are outside of the uncachable MTRR ranges as expected.")

0 commit comments

Comments
 (0)