sdsi_test.py 7.1 KB

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