Skip to content

Commit a3d38af

Browse files
debox1jwrdegoede
authored andcommitted
selftests: sdsi: test sysfs setup
Tests file configuration and error handling of the Intel Software Defined Silicon sysfs ABI. Signed-off-by: David E. Box <david.e.box@linux.intel.com> Link: https://lore.kernel.org/r/20220225012457.1661574-2-david.e.box@linux.intel.com Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
1 parent f6d92cf commit a3d38af

3 files changed

Lines changed: 252 additions & 0 deletions

File tree

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9882,6 +9882,7 @@ M: David E. Box <david.e.box@linux.intel.com>
98829882
S: Supported
98839883
F: drivers/platform/x86/intel/sdsi.c
98849884
F: tools/arch/x86/intel_sdsi/
9885+
F: tools/testing/selftests/drivers/sdsi/
98859886

98869887
INTEL SKYLAKE INT3472 ACPI DEVICE DRIVER
98879888
M: Daniel Scally <djrscally@gmail.com>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/bin/sh
2+
# SPDX-License-Identifier: GPL-2.0
3+
# Runs tests for the intel_sdsi driver
4+
5+
if ! command -v python3 > /dev/null 2>&1; then
6+
echo "drivers/sdsi: [SKIP] python3 not installed"
7+
exit 77
8+
fi
9+
10+
if ! python3 -c "import pytest" > /dev/null 2>&1; then
11+
echo "drivers/sdsi: [SKIP] pytest module not installed"
12+
exit 77
13+
fi
14+
15+
if ! /sbin/modprobe -q -r intel_sdsi; then
16+
echo "drivers/sdsi: [SKIP]"
17+
exit 77
18+
fi
19+
20+
if /sbin/modprobe -q intel_sdsi && python3 -m pytest sdsi_test.py; then
21+
echo "drivers/sdsi: [OK]"
22+
else
23+
echo "drivers/sdsi: [FAIL]"
24+
exit 1
25+
fi
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
#!/usr/bin/env python3
2+
# SPDX-License-Identifier: GPL-2.0
3+
4+
from struct import pack
5+
from time import sleep
6+
7+
import errno
8+
import glob
9+
import os
10+
import subprocess
11+
12+
try:
13+
import pytest
14+
except ImportError:
15+
print("Unable to import pytest python module.")
16+
print("\nIf not already installed, you may do so with:")
17+
print("\t\tpip3 install pytest")
18+
exit(1)
19+
20+
SOCKETS = glob.glob('/sys/bus/auxiliary/devices/intel_vsec.sdsi.*')
21+
NUM_SOCKETS = len(SOCKETS)
22+
23+
MODULE_NAME = 'intel_sdsi'
24+
DEV_PREFIX = 'intel_vsec.sdsi'
25+
CLASS_DIR = '/sys/bus/auxiliary/devices'
26+
GUID = "0x6dd191"
27+
28+
def read_bin_file(file):
29+
with open(file, mode='rb') as f:
30+
content = f.read()
31+
return content
32+
33+
def get_dev_file_path(socket, file):
34+
return CLASS_DIR + '/' + DEV_PREFIX + '.' + str(socket) + '/' + file
35+
36+
def kmemleak_enabled():
37+
kmemleak = "/sys/kernel/debug/kmemleak"
38+
return os.path.isfile(kmemleak)
39+
40+
class TestSDSiDriver:
41+
def test_driver_loaded(self):
42+
lsmod_p = subprocess.Popen(('lsmod'), stdout=subprocess.PIPE)
43+
result = subprocess.check_output(('grep', '-q', MODULE_NAME), stdin=lsmod_p.stdout)
44+
45+
@pytest.mark.parametrize('socket', range(0, NUM_SOCKETS))
46+
class TestSDSiFilesClass:
47+
48+
def read_value(self, file):
49+
f = open(file, "r")
50+
value = f.read().strip("\n")
51+
return value
52+
53+
def get_dev_folder(self, socket):
54+
return CLASS_DIR + '/' + DEV_PREFIX + '.' + str(socket) + '/'
55+
56+
def test_sysfs_files_exist(self, socket):
57+
folder = self.get_dev_folder(socket)
58+
print (folder)
59+
assert os.path.isfile(folder + "guid") == True
60+
assert os.path.isfile(folder + "provision_akc") == True
61+
assert os.path.isfile(folder + "provision_cap") == True
62+
assert os.path.isfile(folder + "state_certificate") == True
63+
assert os.path.isfile(folder + "registers") == True
64+
65+
def test_sysfs_file_permissions(self, socket):
66+
folder = self.get_dev_folder(socket)
67+
mode = os.stat(folder + "guid").st_mode & 0o777
68+
assert mode == 0o444 # Read all
69+
mode = os.stat(folder + "registers").st_mode & 0o777
70+
assert mode == 0o400 # Read owner
71+
mode = os.stat(folder + "provision_akc").st_mode & 0o777
72+
assert mode == 0o200 # Read owner
73+
mode = os.stat(folder + "provision_cap").st_mode & 0o777
74+
assert mode == 0o200 # Read owner
75+
mode = os.stat(folder + "state_certificate").st_mode & 0o777
76+
assert mode == 0o400 # Read owner
77+
78+
def test_sysfs_file_ownership(self, socket):
79+
folder = self.get_dev_folder(socket)
80+
81+
st = os.stat(folder + "guid")
82+
assert st.st_uid == 0
83+
assert st.st_gid == 0
84+
85+
st = os.stat(folder + "registers")
86+
assert st.st_uid == 0
87+
assert st.st_gid == 0
88+
89+
st = os.stat(folder + "provision_akc")
90+
assert st.st_uid == 0
91+
assert st.st_gid == 0
92+
93+
st = os.stat(folder + "provision_cap")
94+
assert st.st_uid == 0
95+
assert st.st_gid == 0
96+
97+
st = os.stat(folder + "state_certificate")
98+
assert st.st_uid == 0
99+
assert st.st_gid == 0
100+
101+
def test_sysfs_file_sizes(self, socket):
102+
folder = self.get_dev_folder(socket)
103+
104+
if self.read_value(folder + "guid") == GUID:
105+
st = os.stat(folder + "registers")
106+
assert st.st_size == 72
107+
108+
st = os.stat(folder + "provision_akc")
109+
assert st.st_size == 1024
110+
111+
st = os.stat(folder + "provision_cap")
112+
assert st.st_size == 1024
113+
114+
st = os.stat(folder + "state_certificate")
115+
assert st.st_size == 4096
116+
117+
def test_no_seek_allowed(self, socket):
118+
folder = self.get_dev_folder(socket)
119+
rand_file = bytes(os.urandom(8))
120+
121+
f = open(folder + "provision_cap", "wb", 0)
122+
f.seek(1)
123+
with pytest.raises(OSError) as error:
124+
f.write(rand_file)
125+
assert error.value.errno == errno.ESPIPE
126+
f.close()
127+
128+
f = open(folder + "provision_akc", "wb", 0)
129+
f.seek(1)
130+
with pytest.raises(OSError) as error:
131+
f.write(rand_file)
132+
assert error.value.errno == errno.ESPIPE
133+
f.close()
134+
135+
def test_registers_seek(self, socket):
136+
folder = self.get_dev_folder(socket)
137+
138+
# Check that the value read from an offset of the entire
139+
# file is none-zero and the same as the value read
140+
# from seeking to the same location
141+
f = open(folder + "registers", "rb")
142+
data = f.read()
143+
f.seek(64)
144+
id = f.read()
145+
assert id != bytes(0)
146+
assert data[64:] == id
147+
f.close()
148+
149+
@pytest.mark.parametrize('socket', range(0, NUM_SOCKETS))
150+
class TestSDSiMailboxCmdsClass:
151+
def test_provision_akc_eoverflow_1017_bytes(self, socket):
152+
153+
# The buffer for writes is 1k, of with 8 bytes must be
154+
# reserved for the command, leaving 1016 bytes max.
155+
# Check that we get an overflow error for 1017 bytes.
156+
node = get_dev_file_path(socket, "provision_akc")
157+
rand_file = bytes(os.urandom(1017))
158+
159+
f = open(node, 'wb', 0)
160+
with pytest.raises(OSError) as error:
161+
f.write(rand_file)
162+
assert error.value.errno == errno.EOVERFLOW
163+
f.close()
164+
165+
@pytest.mark.parametrize('socket', range(0, NUM_SOCKETS))
166+
class TestSdsiDriverLocksClass:
167+
def test_enodev_when_pci_device_removed(self, socket):
168+
node = get_dev_file_path(socket, "provision_akc")
169+
dev_name = DEV_PREFIX + '.' + str(socket)
170+
driver_dir = CLASS_DIR + '/' + dev_name + "/driver/"
171+
rand_file = bytes(os.urandom(8))
172+
173+
f = open(node, 'wb', 0)
174+
g = open(node, 'wb', 0)
175+
176+
with open(driver_dir + 'unbind', 'w') as k:
177+
print(dev_name, file = k)
178+
179+
with pytest.raises(OSError) as error:
180+
f.write(rand_file)
181+
assert error.value.errno == errno.ENODEV
182+
183+
with pytest.raises(OSError) as error:
184+
g.write(rand_file)
185+
assert error.value.errno == errno.ENODEV
186+
187+
f.close()
188+
g.close()
189+
190+
# Short wait needed to allow file to close before pulling driver
191+
sleep(1)
192+
193+
p = subprocess.Popen(('modprobe', '-r', 'intel_sdsi'))
194+
p.wait()
195+
p = subprocess.Popen(('modprobe', '-r', 'intel_vsec'))
196+
p.wait()
197+
p = subprocess.Popen(('modprobe', 'intel_vsec'))
198+
p.wait()
199+
200+
# Short wait needed to allow driver time to get inserted
201+
# before continuing tests
202+
sleep(1)
203+
204+
def test_memory_leak(self, socket):
205+
if not kmemleak_enabled():
206+
pytest.skip("kmemleak not enabled in kernel")
207+
208+
dev_name = DEV_PREFIX + '.' + str(socket)
209+
driver_dir = CLASS_DIR + '/' + dev_name + "/driver/"
210+
211+
with open(driver_dir + 'unbind', 'w') as k:
212+
print(dev_name, file = k)
213+
214+
sleep(1)
215+
216+
subprocess.check_output(('modprobe', '-r', 'intel_sdsi'))
217+
subprocess.check_output(('modprobe', '-r', 'intel_vsec'))
218+
219+
with open('/sys/kernel/debug/kmemleak', 'w') as f:
220+
print('scan', file = f)
221+
sleep(5)
222+
223+
assert os.stat('/sys/kernel/debug/kmemleak').st_size == 0
224+
225+
subprocess.check_output(('modprobe', 'intel_vsec'))
226+
sleep(1)

0 commit comments

Comments
 (0)