iommufd_utils.h 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES */
  3. #ifndef __SELFTEST_IOMMUFD_UTILS
  4. #define __SELFTEST_IOMMUFD_UTILS
  5. #include <unistd.h>
  6. #include <stddef.h>
  7. #include <sys/fcntl.h>
  8. #include <sys/ioctl.h>
  9. #include <stdint.h>
  10. #include <assert.h>
  11. #include <poll.h>
  12. #include "kselftest_harness.h"
  13. #include "../../../../drivers/iommu/iommufd/iommufd_test.h"
  14. /* Hack to make assertions more readable */
  15. #define _IOMMU_TEST_CMD(x) IOMMU_TEST_CMD
  16. /* Imported from include/asm-generic/bitops/generic-non-atomic.h */
  17. #define BITS_PER_BYTE 8
  18. #define BITS_PER_LONG __BITS_PER_LONG
  19. #define BIT_MASK(nr) (1UL << ((nr) % __BITS_PER_LONG))
  20. #define BIT_WORD(nr) ((nr) / __BITS_PER_LONG)
  21. enum {
  22. IOPT_PAGES_ACCOUNT_NONE = 0,
  23. IOPT_PAGES_ACCOUNT_USER = 1,
  24. IOPT_PAGES_ACCOUNT_MM = 2,
  25. };
  26. #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
  27. static inline void set_bit(unsigned int nr, unsigned long *addr)
  28. {
  29. unsigned long mask = BIT_MASK(nr);
  30. unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
  31. *p |= mask;
  32. }
  33. static inline bool test_bit(unsigned int nr, unsigned long *addr)
  34. {
  35. return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG - 1)));
  36. }
  37. static void *buffer;
  38. static unsigned long BUFFER_SIZE;
  39. static void *mfd_buffer;
  40. static int mfd;
  41. static unsigned long PAGE_SIZE;
  42. #define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER))
  43. #define offsetofend(TYPE, MEMBER) \
  44. (offsetof(TYPE, MEMBER) + sizeof_field(TYPE, MEMBER))
  45. #define test_err_mmap(_errno, length, offset) \
  46. EXPECT_ERRNO(_errno, (long)mmap(NULL, length, PROT_READ | PROT_WRITE, \
  47. MAP_SHARED, self->fd, offset))
  48. static inline void *memfd_mmap(size_t length, int prot, int flags, int *mfd_p)
  49. {
  50. int mfd_flags = (flags & MAP_HUGETLB) ? MFD_HUGETLB : 0;
  51. int mfd = memfd_create("buffer", mfd_flags);
  52. void *buf = MAP_FAILED;
  53. if (mfd <= 0)
  54. return MAP_FAILED;
  55. if (ftruncate(mfd, length))
  56. goto out;
  57. *mfd_p = mfd;
  58. buf = mmap(0, length, prot, flags, mfd, 0);
  59. out:
  60. if (buf == MAP_FAILED)
  61. close(mfd);
  62. return buf;
  63. }
  64. /*
  65. * Have the kernel check the refcount on pages. I don't know why a freshly
  66. * mmap'd anon non-compound page starts out with a ref of 3
  67. */
  68. #define check_refs(_ptr, _length, _refs) \
  69. ({ \
  70. struct iommu_test_cmd test_cmd = { \
  71. .size = sizeof(test_cmd), \
  72. .op = IOMMU_TEST_OP_MD_CHECK_REFS, \
  73. .check_refs = { .length = _length, \
  74. .uptr = (uintptr_t)(_ptr), \
  75. .refs = _refs }, \
  76. }; \
  77. ASSERT_EQ(0, \
  78. ioctl(self->fd, \
  79. _IOMMU_TEST_CMD(IOMMU_TEST_OP_MD_CHECK_REFS), \
  80. &test_cmd)); \
  81. })
  82. static int _test_cmd_mock_domain(int fd, unsigned int ioas_id, __u32 *stdev_id,
  83. __u32 *hwpt_id, __u32 *idev_id)
  84. {
  85. struct iommu_test_cmd cmd = {
  86. .size = sizeof(cmd),
  87. .op = IOMMU_TEST_OP_MOCK_DOMAIN,
  88. .id = ioas_id,
  89. .mock_domain = {},
  90. };
  91. int ret;
  92. ret = ioctl(fd, IOMMU_TEST_CMD, &cmd);
  93. if (ret)
  94. return ret;
  95. if (stdev_id)
  96. *stdev_id = cmd.mock_domain.out_stdev_id;
  97. assert(cmd.id != 0);
  98. if (hwpt_id)
  99. *hwpt_id = cmd.mock_domain.out_hwpt_id;
  100. if (idev_id)
  101. *idev_id = cmd.mock_domain.out_idev_id;
  102. return 0;
  103. }
  104. #define test_cmd_mock_domain(ioas_id, stdev_id, hwpt_id, idev_id) \
  105. ASSERT_EQ(0, _test_cmd_mock_domain(self->fd, ioas_id, stdev_id, \
  106. hwpt_id, idev_id))
  107. #define test_err_mock_domain(_errno, ioas_id, stdev_id, hwpt_id) \
  108. EXPECT_ERRNO(_errno, _test_cmd_mock_domain(self->fd, ioas_id, \
  109. stdev_id, hwpt_id, NULL))
  110. static int _test_cmd_mock_domain_flags(int fd, unsigned int ioas_id,
  111. __u32 stdev_flags, __u32 *stdev_id,
  112. __u32 *hwpt_id, __u32 *idev_id)
  113. {
  114. struct iommu_test_cmd cmd = {
  115. .size = sizeof(cmd),
  116. .op = IOMMU_TEST_OP_MOCK_DOMAIN_FLAGS,
  117. .id = ioas_id,
  118. .mock_domain_flags = { .dev_flags = stdev_flags },
  119. };
  120. int ret;
  121. ret = ioctl(fd, IOMMU_TEST_CMD, &cmd);
  122. if (ret)
  123. return ret;
  124. if (stdev_id)
  125. *stdev_id = cmd.mock_domain_flags.out_stdev_id;
  126. assert(cmd.id != 0);
  127. if (hwpt_id)
  128. *hwpt_id = cmd.mock_domain_flags.out_hwpt_id;
  129. if (idev_id)
  130. *idev_id = cmd.mock_domain_flags.out_idev_id;
  131. return 0;
  132. }
  133. #define test_cmd_mock_domain_flags(ioas_id, flags, stdev_id, hwpt_id, idev_id) \
  134. ASSERT_EQ(0, _test_cmd_mock_domain_flags(self->fd, ioas_id, flags, \
  135. stdev_id, hwpt_id, idev_id))
  136. #define test_err_mock_domain_flags(_errno, ioas_id, flags, stdev_id, hwpt_id) \
  137. EXPECT_ERRNO(_errno, \
  138. _test_cmd_mock_domain_flags(self->fd, ioas_id, flags, \
  139. stdev_id, hwpt_id, NULL))
  140. static int _test_cmd_mock_domain_replace(int fd, __u32 stdev_id, __u32 pt_id,
  141. __u32 *hwpt_id)
  142. {
  143. struct iommu_test_cmd cmd = {
  144. .size = sizeof(cmd),
  145. .op = IOMMU_TEST_OP_MOCK_DOMAIN_REPLACE,
  146. .id = stdev_id,
  147. .mock_domain_replace = {
  148. .pt_id = pt_id,
  149. },
  150. };
  151. int ret;
  152. ret = ioctl(fd, IOMMU_TEST_CMD, &cmd);
  153. if (ret)
  154. return ret;
  155. if (hwpt_id)
  156. *hwpt_id = cmd.mock_domain_replace.pt_id;
  157. return 0;
  158. }
  159. #define test_cmd_mock_domain_replace(stdev_id, pt_id) \
  160. ASSERT_EQ(0, _test_cmd_mock_domain_replace(self->fd, stdev_id, pt_id, \
  161. NULL))
  162. #define test_err_mock_domain_replace(_errno, stdev_id, pt_id) \
  163. EXPECT_ERRNO(_errno, _test_cmd_mock_domain_replace(self->fd, stdev_id, \
  164. pt_id, NULL))
  165. static int _test_cmd_hwpt_alloc(int fd, __u32 device_id, __u32 pt_id, __u32 ft_id,
  166. __u32 flags, __u32 *hwpt_id, __u32 data_type,
  167. void *data, size_t data_len)
  168. {
  169. struct iommu_hwpt_alloc cmd = {
  170. .size = sizeof(cmd),
  171. .flags = flags,
  172. .dev_id = device_id,
  173. .pt_id = pt_id,
  174. .data_type = data_type,
  175. .data_len = data_len,
  176. .data_uptr = (uint64_t)data,
  177. .fault_id = ft_id,
  178. };
  179. int ret;
  180. ret = ioctl(fd, IOMMU_HWPT_ALLOC, &cmd);
  181. if (ret)
  182. return ret;
  183. if (hwpt_id)
  184. *hwpt_id = cmd.out_hwpt_id;
  185. return 0;
  186. }
  187. #define test_cmd_hwpt_alloc(device_id, pt_id, flags, hwpt_id) \
  188. ASSERT_EQ(0, _test_cmd_hwpt_alloc(self->fd, device_id, pt_id, 0, flags, \
  189. hwpt_id, IOMMU_HWPT_DATA_NONE, NULL, \
  190. 0))
  191. #define test_cmd_hwpt_alloc_iommupt(device_id, pt_id, flags, iommupt_type, \
  192. hwpt_id) \
  193. ({ \
  194. struct iommu_hwpt_selftest user_cfg = { \
  195. .pagetable_type = iommupt_type \
  196. }; \
  197. \
  198. ASSERT_EQ(0, _test_cmd_hwpt_alloc( \
  199. self->fd, device_id, pt_id, 0, flags, \
  200. hwpt_id, IOMMU_HWPT_DATA_SELFTEST, \
  201. &user_cfg, sizeof(user_cfg))); \
  202. })
  203. #define test_err_hwpt_alloc(_errno, device_id, pt_id, flags, hwpt_id) \
  204. EXPECT_ERRNO(_errno, _test_cmd_hwpt_alloc( \
  205. self->fd, device_id, pt_id, 0, flags, \
  206. hwpt_id, IOMMU_HWPT_DATA_NONE, NULL, 0))
  207. #define test_cmd_hwpt_alloc_nested(device_id, pt_id, flags, hwpt_id, \
  208. data_type, data, data_len) \
  209. ASSERT_EQ(0, _test_cmd_hwpt_alloc(self->fd, device_id, pt_id, 0, flags, \
  210. hwpt_id, data_type, data, data_len))
  211. #define test_err_hwpt_alloc_nested(_errno, device_id, pt_id, flags, hwpt_id, \
  212. data_type, data, data_len) \
  213. EXPECT_ERRNO(_errno, \
  214. _test_cmd_hwpt_alloc(self->fd, device_id, pt_id, 0, flags, \
  215. hwpt_id, data_type, data, data_len))
  216. #define test_cmd_hwpt_alloc_iopf(device_id, pt_id, fault_id, flags, hwpt_id, \
  217. data_type, data, data_len) \
  218. ASSERT_EQ(0, _test_cmd_hwpt_alloc(self->fd, device_id, pt_id, fault_id, \
  219. flags, hwpt_id, data_type, data, \
  220. data_len))
  221. #define test_err_hwpt_alloc_iopf(_errno, device_id, pt_id, fault_id, flags, \
  222. hwpt_id, data_type, data, data_len) \
  223. EXPECT_ERRNO(_errno, \
  224. _test_cmd_hwpt_alloc(self->fd, device_id, pt_id, fault_id, \
  225. flags, hwpt_id, data_type, data, \
  226. data_len))
  227. #define test_cmd_hwpt_check_iotlb(hwpt_id, iotlb_id, expected) \
  228. ({ \
  229. struct iommu_test_cmd test_cmd = { \
  230. .size = sizeof(test_cmd), \
  231. .op = IOMMU_TEST_OP_MD_CHECK_IOTLB, \
  232. .id = hwpt_id, \
  233. .check_iotlb = { \
  234. .id = iotlb_id, \
  235. .iotlb = expected, \
  236. }, \
  237. }; \
  238. ASSERT_EQ(0, \
  239. ioctl(self->fd, \
  240. _IOMMU_TEST_CMD(IOMMU_TEST_OP_MD_CHECK_IOTLB), \
  241. &test_cmd)); \
  242. })
  243. #define test_cmd_hwpt_check_iotlb_all(hwpt_id, expected) \
  244. ({ \
  245. int i; \
  246. for (i = 0; i < MOCK_NESTED_DOMAIN_IOTLB_NUM; i++) \
  247. test_cmd_hwpt_check_iotlb(hwpt_id, i, expected); \
  248. })
  249. #define test_cmd_dev_check_cache(device_id, cache_id, expected) \
  250. ({ \
  251. struct iommu_test_cmd test_cmd = { \
  252. .size = sizeof(test_cmd), \
  253. .op = IOMMU_TEST_OP_DEV_CHECK_CACHE, \
  254. .id = device_id, \
  255. .check_dev_cache = { \
  256. .id = cache_id, \
  257. .cache = expected, \
  258. }, \
  259. }; \
  260. ASSERT_EQ(0, ioctl(self->fd, \
  261. _IOMMU_TEST_CMD( \
  262. IOMMU_TEST_OP_DEV_CHECK_CACHE), \
  263. &test_cmd)); \
  264. })
  265. #define test_cmd_dev_check_cache_all(device_id, expected) \
  266. ({ \
  267. int c; \
  268. for (c = 0; c < MOCK_DEV_CACHE_NUM; c++) \
  269. test_cmd_dev_check_cache(device_id, c, expected); \
  270. })
  271. static int _test_cmd_hwpt_invalidate(int fd, __u32 hwpt_id, void *reqs,
  272. uint32_t data_type, uint32_t lreq,
  273. uint32_t *nreqs)
  274. {
  275. struct iommu_hwpt_invalidate cmd = {
  276. .size = sizeof(cmd),
  277. .hwpt_id = hwpt_id,
  278. .data_type = data_type,
  279. .data_uptr = (uint64_t)reqs,
  280. .entry_len = lreq,
  281. .entry_num = *nreqs,
  282. };
  283. int rc = ioctl(fd, IOMMU_HWPT_INVALIDATE, &cmd);
  284. *nreqs = cmd.entry_num;
  285. return rc;
  286. }
  287. #define test_cmd_hwpt_invalidate(hwpt_id, reqs, data_type, lreq, nreqs) \
  288. ({ \
  289. ASSERT_EQ(0, \
  290. _test_cmd_hwpt_invalidate(self->fd, hwpt_id, reqs, \
  291. data_type, lreq, nreqs)); \
  292. })
  293. #define test_err_hwpt_invalidate(_errno, hwpt_id, reqs, data_type, lreq, \
  294. nreqs) \
  295. ({ \
  296. EXPECT_ERRNO(_errno, _test_cmd_hwpt_invalidate( \
  297. self->fd, hwpt_id, reqs, \
  298. data_type, lreq, nreqs)); \
  299. })
  300. static int _test_cmd_viommu_invalidate(int fd, __u32 viommu_id, void *reqs,
  301. uint32_t data_type, uint32_t lreq,
  302. uint32_t *nreqs)
  303. {
  304. struct iommu_hwpt_invalidate cmd = {
  305. .size = sizeof(cmd),
  306. .hwpt_id = viommu_id,
  307. .data_type = data_type,
  308. .data_uptr = (uint64_t)reqs,
  309. .entry_len = lreq,
  310. .entry_num = *nreqs,
  311. };
  312. int rc = ioctl(fd, IOMMU_HWPT_INVALIDATE, &cmd);
  313. *nreqs = cmd.entry_num;
  314. return rc;
  315. }
  316. #define test_cmd_viommu_invalidate(viommu, reqs, lreq, nreqs) \
  317. ({ \
  318. ASSERT_EQ(0, \
  319. _test_cmd_viommu_invalidate(self->fd, viommu, reqs, \
  320. IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST, \
  321. lreq, nreqs)); \
  322. })
  323. #define test_err_viommu_invalidate(_errno, viommu_id, reqs, data_type, lreq, \
  324. nreqs) \
  325. ({ \
  326. EXPECT_ERRNO(_errno, _test_cmd_viommu_invalidate( \
  327. self->fd, viommu_id, reqs, \
  328. data_type, lreq, nreqs)); \
  329. })
  330. static int _test_cmd_access_replace_ioas(int fd, __u32 access_id,
  331. unsigned int ioas_id)
  332. {
  333. struct iommu_test_cmd cmd = {
  334. .size = sizeof(cmd),
  335. .op = IOMMU_TEST_OP_ACCESS_REPLACE_IOAS,
  336. .id = access_id,
  337. .access_replace_ioas = { .ioas_id = ioas_id },
  338. };
  339. int ret;
  340. ret = ioctl(fd, IOMMU_TEST_CMD, &cmd);
  341. if (ret)
  342. return ret;
  343. return 0;
  344. }
  345. #define test_cmd_access_replace_ioas(access_id, ioas_id) \
  346. ASSERT_EQ(0, _test_cmd_access_replace_ioas(self->fd, access_id, ioas_id))
  347. static int _test_cmd_set_dirty_tracking(int fd, __u32 hwpt_id, bool enabled)
  348. {
  349. struct iommu_hwpt_set_dirty_tracking cmd = {
  350. .size = sizeof(cmd),
  351. .flags = enabled ? IOMMU_HWPT_DIRTY_TRACKING_ENABLE : 0,
  352. .hwpt_id = hwpt_id,
  353. };
  354. int ret;
  355. ret = ioctl(fd, IOMMU_HWPT_SET_DIRTY_TRACKING, &cmd);
  356. if (ret)
  357. return -errno;
  358. return 0;
  359. }
  360. #define test_cmd_set_dirty_tracking(hwpt_id, enabled) \
  361. ASSERT_EQ(0, _test_cmd_set_dirty_tracking(self->fd, hwpt_id, enabled))
  362. static int _test_cmd_get_dirty_bitmap(int fd, __u32 hwpt_id, size_t length,
  363. __u64 iova, size_t page_size,
  364. __u64 *bitmap, __u32 flags)
  365. {
  366. struct iommu_hwpt_get_dirty_bitmap cmd = {
  367. .size = sizeof(cmd),
  368. .hwpt_id = hwpt_id,
  369. .flags = flags,
  370. .iova = iova,
  371. .length = length,
  372. .page_size = page_size,
  373. .data = (uintptr_t)bitmap,
  374. };
  375. int ret;
  376. ret = ioctl(fd, IOMMU_HWPT_GET_DIRTY_BITMAP, &cmd);
  377. if (ret)
  378. return ret;
  379. return 0;
  380. }
  381. #define test_cmd_get_dirty_bitmap(fd, hwpt_id, length, iova, page_size, \
  382. bitmap, flags) \
  383. ASSERT_EQ(0, _test_cmd_get_dirty_bitmap(fd, hwpt_id, length, iova, \
  384. page_size, bitmap, flags))
  385. static int _test_cmd_mock_domain_set_dirty(int fd, __u32 hwpt_id, size_t length,
  386. __u64 iova, size_t page_size,
  387. __u64 *bitmap, __u64 *dirty)
  388. {
  389. struct iommu_test_cmd cmd = {
  390. .size = sizeof(cmd),
  391. .op = IOMMU_TEST_OP_DIRTY,
  392. .id = hwpt_id,
  393. .dirty = {
  394. .iova = iova,
  395. .length = length,
  396. .page_size = page_size,
  397. .uptr = (uintptr_t)bitmap,
  398. }
  399. };
  400. int ret;
  401. ret = ioctl(fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_DIRTY), &cmd);
  402. if (ret)
  403. return -ret;
  404. if (dirty)
  405. *dirty = cmd.dirty.out_nr_dirty;
  406. return 0;
  407. }
  408. #define test_cmd_mock_domain_set_dirty(fd, hwpt_id, length, iova, page_size, \
  409. bitmap, nr) \
  410. ASSERT_EQ(0, \
  411. _test_cmd_mock_domain_set_dirty(fd, hwpt_id, length, iova, \
  412. page_size, bitmap, nr))
  413. static int _test_mock_dirty_bitmaps(int fd, __u32 hwpt_id, size_t length,
  414. __u64 iova, size_t page_size,
  415. size_t pte_page_size, __u64 *bitmap,
  416. __u64 nbits, __u32 flags,
  417. struct __test_metadata *_metadata)
  418. {
  419. unsigned long npte = pte_page_size / page_size, pteset = 2 * npte;
  420. unsigned long j, i, nr = nbits / pteset ?: 1;
  421. unsigned long bitmap_size = DIV_ROUND_UP(nbits, BITS_PER_BYTE);
  422. __u64 out_dirty = 0;
  423. /* Mark all even bits as dirty in the mock domain */
  424. memset(bitmap, 0, bitmap_size);
  425. for (i = 0; i < nbits; i += pteset)
  426. set_bit(i, (unsigned long *)bitmap);
  427. test_cmd_mock_domain_set_dirty(fd, hwpt_id, length, iova, page_size,
  428. bitmap, &out_dirty);
  429. ASSERT_EQ(nr, out_dirty);
  430. /* Expect all even bits as dirty in the user bitmap */
  431. memset(bitmap, 0, bitmap_size);
  432. test_cmd_get_dirty_bitmap(fd, hwpt_id, length, iova, page_size, bitmap,
  433. flags);
  434. /* Beware ASSERT_EQ() is two statements -- braces are not redundant! */
  435. for (i = 0; i < nbits; i += pteset) {
  436. for (j = 0; j < pteset; j++) {
  437. ASSERT_EQ(j < npte,
  438. test_bit(i + j, (unsigned long *)bitmap));
  439. }
  440. ASSERT_EQ(!(i % pteset), test_bit(i, (unsigned long *)bitmap));
  441. }
  442. memset(bitmap, 0, bitmap_size);
  443. test_cmd_get_dirty_bitmap(fd, hwpt_id, length, iova, page_size, bitmap,
  444. flags);
  445. /* It as read already -- expect all zeroes */
  446. for (i = 0; i < nbits; i += pteset) {
  447. for (j = 0; j < pteset; j++) {
  448. ASSERT_EQ(
  449. (j < npte) &&
  450. (flags &
  451. IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR),
  452. test_bit(i + j, (unsigned long *)bitmap));
  453. }
  454. }
  455. return 0;
  456. }
  457. #define test_mock_dirty_bitmaps(hwpt_id, length, iova, page_size, pte_size,\
  458. bitmap, bitmap_size, flags, _metadata) \
  459. ASSERT_EQ(0, _test_mock_dirty_bitmaps(self->fd, hwpt_id, length, iova, \
  460. page_size, pte_size, bitmap, \
  461. bitmap_size, flags, _metadata))
  462. static int _test_cmd_create_access(int fd, unsigned int ioas_id,
  463. __u32 *access_id, unsigned int flags)
  464. {
  465. struct iommu_test_cmd cmd = {
  466. .size = sizeof(cmd),
  467. .op = IOMMU_TEST_OP_CREATE_ACCESS,
  468. .id = ioas_id,
  469. .create_access = { .flags = flags },
  470. };
  471. int ret;
  472. ret = ioctl(fd, IOMMU_TEST_CMD, &cmd);
  473. if (ret)
  474. return ret;
  475. *access_id = cmd.create_access.out_access_fd;
  476. return 0;
  477. }
  478. #define test_cmd_create_access(ioas_id, access_id, flags) \
  479. ASSERT_EQ(0, _test_cmd_create_access(self->fd, ioas_id, access_id, \
  480. flags))
  481. static int _test_cmd_destroy_access(unsigned int access_id)
  482. {
  483. return close(access_id);
  484. }
  485. #define test_cmd_destroy_access(access_id) \
  486. ASSERT_EQ(0, _test_cmd_destroy_access(access_id))
  487. static int _test_cmd_destroy_access_pages(int fd, unsigned int access_id,
  488. unsigned int access_pages_id)
  489. {
  490. struct iommu_test_cmd cmd = {
  491. .size = sizeof(cmd),
  492. .op = IOMMU_TEST_OP_DESTROY_ACCESS_PAGES,
  493. .id = access_id,
  494. .destroy_access_pages = { .access_pages_id = access_pages_id },
  495. };
  496. return ioctl(fd, IOMMU_TEST_CMD, &cmd);
  497. }
  498. #define test_cmd_destroy_access_pages(access_id, access_pages_id) \
  499. ASSERT_EQ(0, _test_cmd_destroy_access_pages(self->fd, access_id, \
  500. access_pages_id))
  501. #define test_err_destroy_access_pages(_errno, access_id, access_pages_id) \
  502. EXPECT_ERRNO(_errno, _test_cmd_destroy_access_pages( \
  503. self->fd, access_id, access_pages_id))
  504. static int _test_cmd_get_dmabuf(int fd, size_t len, int *out_fd)
  505. {
  506. struct iommu_test_cmd cmd = {
  507. .size = sizeof(cmd),
  508. .op = IOMMU_TEST_OP_DMABUF_GET,
  509. .dmabuf_get = { .length = len, .open_flags = O_CLOEXEC },
  510. };
  511. *out_fd = ioctl(fd, IOMMU_TEST_CMD, &cmd);
  512. if (*out_fd < 0)
  513. return -1;
  514. return 0;
  515. }
  516. #define test_cmd_get_dmabuf(len, out_fd) \
  517. ASSERT_EQ(0, _test_cmd_get_dmabuf(self->fd, len, out_fd))
  518. static int _test_cmd_revoke_dmabuf(int fd, int dmabuf_fd, bool revoked)
  519. {
  520. struct iommu_test_cmd cmd = {
  521. .size = sizeof(cmd),
  522. .op = IOMMU_TEST_OP_DMABUF_REVOKE,
  523. .dmabuf_revoke = { .dmabuf_fd = dmabuf_fd, .revoked = revoked },
  524. };
  525. int ret;
  526. ret = ioctl(fd, IOMMU_TEST_CMD, &cmd);
  527. if (ret < 0)
  528. return -1;
  529. return 0;
  530. }
  531. #define test_cmd_revoke_dmabuf(dmabuf_fd, revoke) \
  532. ASSERT_EQ(0, _test_cmd_revoke_dmabuf(self->fd, dmabuf_fd, revoke))
  533. static int _test_ioctl_destroy(int fd, unsigned int id)
  534. {
  535. struct iommu_destroy cmd = {
  536. .size = sizeof(cmd),
  537. .id = id,
  538. };
  539. return ioctl(fd, IOMMU_DESTROY, &cmd);
  540. }
  541. #define test_ioctl_destroy(id) ASSERT_EQ(0, _test_ioctl_destroy(self->fd, id))
  542. static int _test_ioctl_ioas_alloc(int fd, __u32 *id)
  543. {
  544. struct iommu_ioas_alloc cmd = {
  545. .size = sizeof(cmd),
  546. };
  547. int ret;
  548. ret = ioctl(fd, IOMMU_IOAS_ALLOC, &cmd);
  549. if (ret)
  550. return ret;
  551. *id = cmd.out_ioas_id;
  552. return 0;
  553. }
  554. #define test_ioctl_ioas_alloc(id) \
  555. ({ \
  556. ASSERT_EQ(0, _test_ioctl_ioas_alloc(self->fd, id)); \
  557. ASSERT_NE(0, *(id)); \
  558. })
  559. static int _test_ioctl_ioas_map(int fd, unsigned int ioas_id, void *buffer,
  560. size_t length, __u64 *iova, unsigned int flags)
  561. {
  562. struct iommu_ioas_map cmd = {
  563. .size = sizeof(cmd),
  564. .flags = flags,
  565. .ioas_id = ioas_id,
  566. .user_va = (uintptr_t)buffer,
  567. .length = length,
  568. };
  569. int ret;
  570. if (flags & IOMMU_IOAS_MAP_FIXED_IOVA)
  571. cmd.iova = *iova;
  572. ret = ioctl(fd, IOMMU_IOAS_MAP, &cmd);
  573. *iova = cmd.iova;
  574. return ret;
  575. }
  576. #define test_ioctl_ioas_map(buffer, length, iova_p) \
  577. ASSERT_EQ(0, _test_ioctl_ioas_map(self->fd, self->ioas_id, buffer, \
  578. length, iova_p, \
  579. IOMMU_IOAS_MAP_WRITEABLE | \
  580. IOMMU_IOAS_MAP_READABLE))
  581. #define test_err_ioctl_ioas_map(_errno, buffer, length, iova_p) \
  582. EXPECT_ERRNO(_errno, \
  583. _test_ioctl_ioas_map(self->fd, self->ioas_id, buffer, \
  584. length, iova_p, \
  585. IOMMU_IOAS_MAP_WRITEABLE | \
  586. IOMMU_IOAS_MAP_READABLE))
  587. #define test_ioctl_ioas_map_id(ioas_id, buffer, length, iova_p) \
  588. ASSERT_EQ(0, _test_ioctl_ioas_map(self->fd, ioas_id, buffer, length, \
  589. iova_p, \
  590. IOMMU_IOAS_MAP_WRITEABLE | \
  591. IOMMU_IOAS_MAP_READABLE))
  592. #define test_ioctl_ioas_map_fixed(buffer, length, iova) \
  593. ({ \
  594. __u64 __iova = iova; \
  595. ASSERT_EQ(0, _test_ioctl_ioas_map( \
  596. self->fd, self->ioas_id, buffer, length, \
  597. &__iova, \
  598. IOMMU_IOAS_MAP_FIXED_IOVA | \
  599. IOMMU_IOAS_MAP_WRITEABLE | \
  600. IOMMU_IOAS_MAP_READABLE)); \
  601. })
  602. #define test_ioctl_ioas_map_fixed_id(ioas_id, buffer, length, iova) \
  603. ({ \
  604. __u64 __iova = iova; \
  605. ASSERT_EQ(0, \
  606. _test_ioctl_ioas_map( \
  607. self->fd, ioas_id, buffer, length, &__iova, \
  608. IOMMU_IOAS_MAP_FIXED_IOVA | \
  609. IOMMU_IOAS_MAP_WRITEABLE | \
  610. IOMMU_IOAS_MAP_READABLE)); \
  611. })
  612. #define test_err_ioctl_ioas_map_fixed(_errno, buffer, length, iova) \
  613. ({ \
  614. __u64 __iova = iova; \
  615. EXPECT_ERRNO(_errno, \
  616. _test_ioctl_ioas_map( \
  617. self->fd, self->ioas_id, buffer, length, \
  618. &__iova, \
  619. IOMMU_IOAS_MAP_FIXED_IOVA | \
  620. IOMMU_IOAS_MAP_WRITEABLE | \
  621. IOMMU_IOAS_MAP_READABLE)); \
  622. })
  623. static int _test_ioctl_ioas_unmap(int fd, unsigned int ioas_id, uint64_t iova,
  624. size_t length, uint64_t *out_len)
  625. {
  626. struct iommu_ioas_unmap cmd = {
  627. .size = sizeof(cmd),
  628. .ioas_id = ioas_id,
  629. .iova = iova,
  630. .length = length,
  631. };
  632. int ret;
  633. ret = ioctl(fd, IOMMU_IOAS_UNMAP, &cmd);
  634. if (out_len)
  635. *out_len = cmd.length;
  636. return ret;
  637. }
  638. #define test_ioctl_ioas_unmap(iova, length) \
  639. ASSERT_EQ(0, _test_ioctl_ioas_unmap(self->fd, self->ioas_id, iova, \
  640. length, NULL))
  641. #define test_ioctl_ioas_unmap_id(ioas_id, iova, length) \
  642. ASSERT_EQ(0, _test_ioctl_ioas_unmap(self->fd, ioas_id, iova, length, \
  643. NULL))
  644. #define test_err_ioctl_ioas_unmap(_errno, iova, length) \
  645. EXPECT_ERRNO(_errno, _test_ioctl_ioas_unmap(self->fd, self->ioas_id, \
  646. iova, length, NULL))
  647. static int _test_ioctl_ioas_map_file(int fd, unsigned int ioas_id, int mfd,
  648. size_t start, size_t length, __u64 *iova,
  649. unsigned int flags)
  650. {
  651. struct iommu_ioas_map_file cmd = {
  652. .size = sizeof(cmd),
  653. .flags = flags,
  654. .ioas_id = ioas_id,
  655. .fd = mfd,
  656. .start = start,
  657. .length = length,
  658. };
  659. int ret;
  660. if (flags & IOMMU_IOAS_MAP_FIXED_IOVA)
  661. cmd.iova = *iova;
  662. ret = ioctl(fd, IOMMU_IOAS_MAP_FILE, &cmd);
  663. *iova = cmd.iova;
  664. return ret;
  665. }
  666. #define test_ioctl_ioas_map_file(mfd, start, length, iova_p) \
  667. ASSERT_EQ(0, \
  668. _test_ioctl_ioas_map_file( \
  669. self->fd, self->ioas_id, mfd, start, length, iova_p, \
  670. IOMMU_IOAS_MAP_WRITEABLE | IOMMU_IOAS_MAP_READABLE))
  671. #define test_err_ioctl_ioas_map_file(_errno, mfd, start, length, iova_p) \
  672. EXPECT_ERRNO( \
  673. _errno, \
  674. _test_ioctl_ioas_map_file( \
  675. self->fd, self->ioas_id, mfd, start, length, iova_p, \
  676. IOMMU_IOAS_MAP_WRITEABLE | IOMMU_IOAS_MAP_READABLE))
  677. #define test_ioctl_ioas_map_id_file(ioas_id, mfd, start, length, iova_p) \
  678. ASSERT_EQ(0, \
  679. _test_ioctl_ioas_map_file( \
  680. self->fd, ioas_id, mfd, start, length, iova_p, \
  681. IOMMU_IOAS_MAP_WRITEABLE | IOMMU_IOAS_MAP_READABLE))
  682. #define test_ioctl_ioas_map_fixed_file(mfd, start, length, iova) \
  683. ({ \
  684. __u64 __iova = iova; \
  685. ASSERT_EQ(0, _test_ioctl_ioas_map_file( \
  686. self->fd, self->ioas_id, mfd, start, \
  687. length, &__iova, \
  688. IOMMU_IOAS_MAP_FIXED_IOVA | \
  689. IOMMU_IOAS_MAP_WRITEABLE | \
  690. IOMMU_IOAS_MAP_READABLE)); \
  691. })
  692. static int _test_ioctl_set_temp_memory_limit(int fd, unsigned int limit)
  693. {
  694. struct iommu_test_cmd memlimit_cmd = {
  695. .size = sizeof(memlimit_cmd),
  696. .op = IOMMU_TEST_OP_SET_TEMP_MEMORY_LIMIT,
  697. .memory_limit = { .limit = limit },
  698. };
  699. return ioctl(fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_SET_TEMP_MEMORY_LIMIT),
  700. &memlimit_cmd);
  701. }
  702. #define test_ioctl_set_temp_memory_limit(limit) \
  703. ASSERT_EQ(0, _test_ioctl_set_temp_memory_limit(self->fd, limit))
  704. #define test_ioctl_set_default_memory_limit() \
  705. test_ioctl_set_temp_memory_limit(65536)
  706. static void teardown_iommufd(int fd, struct __test_metadata *_metadata)
  707. {
  708. struct iommu_test_cmd test_cmd = {
  709. .size = sizeof(test_cmd),
  710. .op = IOMMU_TEST_OP_MD_CHECK_REFS,
  711. .check_refs = { .length = BUFFER_SIZE,
  712. .uptr = (uintptr_t)buffer },
  713. };
  714. if (fd == -1)
  715. return;
  716. EXPECT_EQ(0, close(fd));
  717. fd = open("/dev/iommu", O_RDWR);
  718. EXPECT_NE(-1, fd);
  719. EXPECT_EQ(0, ioctl(fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_MD_CHECK_REFS),
  720. &test_cmd));
  721. EXPECT_EQ(0, close(fd));
  722. }
  723. #define EXPECT_ERRNO(expected_errno, cmd) \
  724. ({ \
  725. ASSERT_EQ(-1, cmd); \
  726. EXPECT_EQ(expected_errno, errno); \
  727. })
  728. #endif
  729. /* @data can be NULL */
  730. static int _test_cmd_get_hw_info(int fd, __u32 device_id, __u32 data_type,
  731. void *data, size_t data_len,
  732. uint32_t *capabilities, uint8_t *max_pasid)
  733. {
  734. struct iommu_test_hw_info *info = (struct iommu_test_hw_info *)data;
  735. struct iommu_hw_info cmd = {
  736. .size = sizeof(cmd),
  737. .dev_id = device_id,
  738. .data_len = data_len,
  739. .in_data_type = data_type,
  740. .data_uptr = (uint64_t)data,
  741. .out_capabilities = 0,
  742. };
  743. int ret;
  744. if (data_type != IOMMU_HW_INFO_TYPE_DEFAULT)
  745. cmd.flags |= IOMMU_HW_INFO_FLAG_INPUT_TYPE;
  746. ret = ioctl(fd, IOMMU_GET_HW_INFO, &cmd);
  747. if (ret)
  748. return ret;
  749. assert(cmd.out_data_type == IOMMU_HW_INFO_TYPE_SELFTEST);
  750. /*
  751. * The struct iommu_test_hw_info should be the one defined
  752. * by the current kernel.
  753. */
  754. assert(cmd.data_len == sizeof(struct iommu_test_hw_info));
  755. /*
  756. * Trailing bytes should be 0 if user buffer is larger than
  757. * the data that kernel reports.
  758. */
  759. if (data_len > cmd.data_len) {
  760. char *ptr = (char *)(data + cmd.data_len);
  761. int idx = 0;
  762. while (idx < data_len - cmd.data_len) {
  763. assert(!*(ptr + idx));
  764. idx++;
  765. }
  766. }
  767. if (info) {
  768. if (data_len >= offsetofend(struct iommu_test_hw_info, test_reg))
  769. assert(info->test_reg == IOMMU_HW_INFO_SELFTEST_REGVAL);
  770. if (data_len >= offsetofend(struct iommu_test_hw_info, flags))
  771. assert(!info->flags);
  772. }
  773. if (max_pasid)
  774. *max_pasid = cmd.out_max_pasid_log2;
  775. if (capabilities)
  776. *capabilities = cmd.out_capabilities;
  777. return 0;
  778. }
  779. #define test_cmd_get_hw_info(device_id, data_type, data, data_len) \
  780. ASSERT_EQ(0, _test_cmd_get_hw_info(self->fd, device_id, data_type, \
  781. data, data_len, NULL, NULL))
  782. #define test_err_get_hw_info(_errno, device_id, data_type, data, data_len) \
  783. EXPECT_ERRNO(_errno, \
  784. _test_cmd_get_hw_info(self->fd, device_id, data_type, \
  785. data, data_len, NULL, NULL))
  786. #define test_cmd_get_hw_capabilities(device_id, caps) \
  787. ASSERT_EQ(0, _test_cmd_get_hw_info(self->fd, device_id, \
  788. IOMMU_HW_INFO_TYPE_DEFAULT, NULL, \
  789. 0, &caps, NULL))
  790. #define test_cmd_get_hw_info_pasid(device_id, max_pasid) \
  791. ASSERT_EQ(0, _test_cmd_get_hw_info(self->fd, device_id, \
  792. IOMMU_HW_INFO_TYPE_DEFAULT, NULL, \
  793. 0, NULL, max_pasid))
  794. static int _test_ioctl_fault_alloc(int fd, __u32 *fault_id, __u32 *fault_fd)
  795. {
  796. struct iommu_fault_alloc cmd = {
  797. .size = sizeof(cmd),
  798. };
  799. int ret;
  800. ret = ioctl(fd, IOMMU_FAULT_QUEUE_ALLOC, &cmd);
  801. if (ret)
  802. return ret;
  803. *fault_id = cmd.out_fault_id;
  804. *fault_fd = cmd.out_fault_fd;
  805. return 0;
  806. }
  807. #define test_ioctl_fault_alloc(fault_id, fault_fd) \
  808. ({ \
  809. ASSERT_EQ(0, _test_ioctl_fault_alloc(self->fd, fault_id, \
  810. fault_fd)); \
  811. ASSERT_NE(0, *(fault_id)); \
  812. ASSERT_NE(0, *(fault_fd)); \
  813. })
  814. static int _test_cmd_trigger_iopf(int fd, __u32 device_id, __u32 pasid,
  815. __u32 fault_fd)
  816. {
  817. struct iommu_test_cmd trigger_iopf_cmd = {
  818. .size = sizeof(trigger_iopf_cmd),
  819. .op = IOMMU_TEST_OP_TRIGGER_IOPF,
  820. .trigger_iopf = {
  821. .dev_id = device_id,
  822. .pasid = pasid,
  823. .grpid = 0x2,
  824. .perm = IOMMU_PGFAULT_PERM_READ | IOMMU_PGFAULT_PERM_WRITE,
  825. .addr = 0xdeadbeaf,
  826. },
  827. };
  828. struct iommu_hwpt_page_response response = {
  829. .code = IOMMUFD_PAGE_RESP_SUCCESS,
  830. };
  831. struct iommu_hwpt_pgfault fault = {};
  832. ssize_t bytes;
  833. int ret;
  834. ret = ioctl(fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_TRIGGER_IOPF), &trigger_iopf_cmd);
  835. if (ret)
  836. return ret;
  837. bytes = read(fault_fd, &fault, sizeof(fault));
  838. if (bytes <= 0)
  839. return -EIO;
  840. response.cookie = fault.cookie;
  841. bytes = write(fault_fd, &response, sizeof(response));
  842. if (bytes <= 0)
  843. return -EIO;
  844. return 0;
  845. }
  846. #define test_cmd_trigger_iopf(device_id, fault_fd) \
  847. ASSERT_EQ(0, _test_cmd_trigger_iopf(self->fd, device_id, 0x1, fault_fd))
  848. #define test_cmd_trigger_iopf_pasid(device_id, pasid, fault_fd) \
  849. ASSERT_EQ(0, _test_cmd_trigger_iopf(self->fd, device_id, \
  850. pasid, fault_fd))
  851. static int _test_cmd_viommu_alloc(int fd, __u32 device_id, __u32 hwpt_id,
  852. __u32 flags, __u32 type, void *data,
  853. __u32 data_len, __u32 *viommu_id)
  854. {
  855. struct iommu_viommu_alloc cmd = {
  856. .size = sizeof(cmd),
  857. .flags = flags,
  858. .type = type,
  859. .dev_id = device_id,
  860. .hwpt_id = hwpt_id,
  861. .data_uptr = (uint64_t)data,
  862. .data_len = data_len,
  863. };
  864. int ret;
  865. ret = ioctl(fd, IOMMU_VIOMMU_ALLOC, &cmd);
  866. if (ret)
  867. return ret;
  868. if (viommu_id)
  869. *viommu_id = cmd.out_viommu_id;
  870. return 0;
  871. }
  872. #define test_cmd_viommu_alloc(device_id, hwpt_id, type, data, data_len, \
  873. viommu_id) \
  874. ASSERT_EQ(0, _test_cmd_viommu_alloc(self->fd, device_id, hwpt_id, 0, \
  875. type, data, data_len, viommu_id))
  876. #define test_err_viommu_alloc(_errno, device_id, hwpt_id, type, data, \
  877. data_len, viommu_id) \
  878. EXPECT_ERRNO(_errno, \
  879. _test_cmd_viommu_alloc(self->fd, device_id, hwpt_id, 0, \
  880. type, data, data_len, viommu_id))
  881. static int _test_cmd_vdevice_alloc(int fd, __u32 viommu_id, __u32 idev_id,
  882. __u64 virt_id, __u32 *vdev_id)
  883. {
  884. struct iommu_vdevice_alloc cmd = {
  885. .size = sizeof(cmd),
  886. .dev_id = idev_id,
  887. .viommu_id = viommu_id,
  888. .virt_id = virt_id,
  889. };
  890. int ret;
  891. ret = ioctl(fd, IOMMU_VDEVICE_ALLOC, &cmd);
  892. if (ret)
  893. return ret;
  894. if (vdev_id)
  895. *vdev_id = cmd.out_vdevice_id;
  896. return 0;
  897. }
  898. #define test_cmd_vdevice_alloc(viommu_id, idev_id, virt_id, vdev_id) \
  899. ASSERT_EQ(0, _test_cmd_vdevice_alloc(self->fd, viommu_id, idev_id, \
  900. virt_id, vdev_id))
  901. #define test_err_vdevice_alloc(_errno, viommu_id, idev_id, virt_id, vdev_id) \
  902. EXPECT_ERRNO(_errno, \
  903. _test_cmd_vdevice_alloc(self->fd, viommu_id, idev_id, \
  904. virt_id, vdev_id))
  905. static int _test_cmd_hw_queue_alloc(int fd, __u32 viommu_id, __u32 type,
  906. __u32 idx, __u64 base_addr, __u64 length,
  907. __u32 *hw_queue_id)
  908. {
  909. struct iommu_hw_queue_alloc cmd = {
  910. .size = sizeof(cmd),
  911. .viommu_id = viommu_id,
  912. .type = type,
  913. .index = idx,
  914. .nesting_parent_iova = base_addr,
  915. .length = length,
  916. };
  917. int ret;
  918. ret = ioctl(fd, IOMMU_HW_QUEUE_ALLOC, &cmd);
  919. if (ret)
  920. return ret;
  921. if (hw_queue_id)
  922. *hw_queue_id = cmd.out_hw_queue_id;
  923. return 0;
  924. }
  925. #define test_cmd_hw_queue_alloc(viommu_id, type, idx, base_addr, len, out_qid) \
  926. ASSERT_EQ(0, _test_cmd_hw_queue_alloc(self->fd, viommu_id, type, idx, \
  927. base_addr, len, out_qid))
  928. #define test_err_hw_queue_alloc(_errno, viommu_id, type, idx, base_addr, len, \
  929. out_qid) \
  930. EXPECT_ERRNO(_errno, \
  931. _test_cmd_hw_queue_alloc(self->fd, viommu_id, type, idx, \
  932. base_addr, len, out_qid))
  933. static int _test_cmd_veventq_alloc(int fd, __u32 viommu_id, __u32 type,
  934. __u32 *veventq_id, __u32 *veventq_fd)
  935. {
  936. struct iommu_veventq_alloc cmd = {
  937. .size = sizeof(cmd),
  938. .type = type,
  939. .veventq_depth = 2,
  940. .viommu_id = viommu_id,
  941. };
  942. int ret;
  943. ret = ioctl(fd, IOMMU_VEVENTQ_ALLOC, &cmd);
  944. if (ret)
  945. return ret;
  946. if (veventq_id)
  947. *veventq_id = cmd.out_veventq_id;
  948. if (veventq_fd)
  949. *veventq_fd = cmd.out_veventq_fd;
  950. return 0;
  951. }
  952. #define test_cmd_veventq_alloc(viommu_id, type, veventq_id, veventq_fd) \
  953. ASSERT_EQ(0, _test_cmd_veventq_alloc(self->fd, viommu_id, type, \
  954. veventq_id, veventq_fd))
  955. #define test_err_veventq_alloc(_errno, viommu_id, type, veventq_id, \
  956. veventq_fd) \
  957. EXPECT_ERRNO(_errno, \
  958. _test_cmd_veventq_alloc(self->fd, viommu_id, type, \
  959. veventq_id, veventq_fd))
  960. static int _test_cmd_trigger_vevents(int fd, __u32 dev_id, __u32 nvevents)
  961. {
  962. struct iommu_test_cmd trigger_vevent_cmd = {
  963. .size = sizeof(trigger_vevent_cmd),
  964. .op = IOMMU_TEST_OP_TRIGGER_VEVENT,
  965. .trigger_vevent = {
  966. .dev_id = dev_id,
  967. },
  968. };
  969. while (nvevents--) {
  970. if (ioctl(fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_TRIGGER_VEVENT),
  971. &trigger_vevent_cmd))
  972. return -1;
  973. }
  974. return 0;
  975. }
  976. #define test_cmd_trigger_vevents(dev_id, nvevents) \
  977. ASSERT_EQ(0, _test_cmd_trigger_vevents(self->fd, dev_id, nvevents))
  978. static int _test_cmd_read_vevents(int fd, __u32 event_fd, __u32 nvevents,
  979. __u32 virt_id, int *prev_seq)
  980. {
  981. struct pollfd pollfd = { .fd = event_fd, .events = POLLIN };
  982. struct iommu_viommu_event_selftest *event;
  983. struct iommufd_vevent_header *hdr;
  984. ssize_t bytes;
  985. void *data;
  986. int ret, i;
  987. ret = poll(&pollfd, 1, 1000);
  988. if (ret < 0)
  989. return -1;
  990. data = calloc(nvevents, sizeof(*hdr) + sizeof(*event));
  991. if (!data) {
  992. errno = ENOMEM;
  993. return -1;
  994. }
  995. bytes = read(event_fd, data,
  996. nvevents * (sizeof(*hdr) + sizeof(*event)));
  997. if (bytes <= 0) {
  998. errno = EFAULT;
  999. ret = -1;
  1000. goto out_free;
  1001. }
  1002. for (i = 0; i < nvevents; i++) {
  1003. hdr = data + i * (sizeof(*hdr) + sizeof(*event));
  1004. if (hdr->flags & IOMMU_VEVENTQ_FLAG_LOST_EVENTS ||
  1005. hdr->sequence - *prev_seq > 1) {
  1006. *prev_seq = hdr->sequence;
  1007. errno = EOVERFLOW;
  1008. ret = -1;
  1009. goto out_free;
  1010. }
  1011. *prev_seq = hdr->sequence;
  1012. event = data + sizeof(*hdr);
  1013. if (event->virt_id != virt_id) {
  1014. errno = EINVAL;
  1015. ret = -1;
  1016. goto out_free;
  1017. }
  1018. }
  1019. ret = 0;
  1020. out_free:
  1021. free(data);
  1022. return ret;
  1023. }
  1024. #define test_cmd_read_vevents(event_fd, nvevents, virt_id, prev_seq) \
  1025. ASSERT_EQ(0, _test_cmd_read_vevents(self->fd, event_fd, nvevents, \
  1026. virt_id, prev_seq))
  1027. #define test_err_read_vevents(_errno, event_fd, nvevents, virt_id, prev_seq) \
  1028. EXPECT_ERRNO(_errno, \
  1029. _test_cmd_read_vevents(self->fd, event_fd, nvevents, \
  1030. virt_id, prev_seq))
  1031. static int _test_cmd_pasid_attach(int fd, __u32 stdev_id, __u32 pasid,
  1032. __u32 pt_id)
  1033. {
  1034. struct iommu_test_cmd test_attach = {
  1035. .size = sizeof(test_attach),
  1036. .op = IOMMU_TEST_OP_PASID_ATTACH,
  1037. .id = stdev_id,
  1038. .pasid_attach = {
  1039. .pasid = pasid,
  1040. .pt_id = pt_id,
  1041. },
  1042. };
  1043. return ioctl(fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_PASID_ATTACH),
  1044. &test_attach);
  1045. }
  1046. #define test_cmd_pasid_attach(pasid, hwpt_id) \
  1047. ASSERT_EQ(0, _test_cmd_pasid_attach(self->fd, self->stdev_id, \
  1048. pasid, hwpt_id))
  1049. #define test_err_pasid_attach(_errno, pasid, hwpt_id) \
  1050. EXPECT_ERRNO(_errno, \
  1051. _test_cmd_pasid_attach(self->fd, self->stdev_id, \
  1052. pasid, hwpt_id))
  1053. static int _test_cmd_pasid_replace(int fd, __u32 stdev_id, __u32 pasid,
  1054. __u32 pt_id)
  1055. {
  1056. struct iommu_test_cmd test_replace = {
  1057. .size = sizeof(test_replace),
  1058. .op = IOMMU_TEST_OP_PASID_REPLACE,
  1059. .id = stdev_id,
  1060. .pasid_replace = {
  1061. .pasid = pasid,
  1062. .pt_id = pt_id,
  1063. },
  1064. };
  1065. return ioctl(fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_PASID_REPLACE),
  1066. &test_replace);
  1067. }
  1068. #define test_cmd_pasid_replace(pasid, hwpt_id) \
  1069. ASSERT_EQ(0, _test_cmd_pasid_replace(self->fd, self->stdev_id, \
  1070. pasid, hwpt_id))
  1071. #define test_err_pasid_replace(_errno, pasid, hwpt_id) \
  1072. EXPECT_ERRNO(_errno, \
  1073. _test_cmd_pasid_replace(self->fd, self->stdev_id, \
  1074. pasid, hwpt_id))
  1075. static int _test_cmd_pasid_detach(int fd, __u32 stdev_id, __u32 pasid)
  1076. {
  1077. struct iommu_test_cmd test_detach = {
  1078. .size = sizeof(test_detach),
  1079. .op = IOMMU_TEST_OP_PASID_DETACH,
  1080. .id = stdev_id,
  1081. .pasid_detach = {
  1082. .pasid = pasid,
  1083. },
  1084. };
  1085. return ioctl(fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_PASID_DETACH),
  1086. &test_detach);
  1087. }
  1088. #define test_cmd_pasid_detach(pasid) \
  1089. ASSERT_EQ(0, _test_cmd_pasid_detach(self->fd, self->stdev_id, pasid))
  1090. static int test_cmd_pasid_check_hwpt(int fd, __u32 stdev_id, __u32 pasid,
  1091. __u32 hwpt_id)
  1092. {
  1093. struct iommu_test_cmd test_pasid_check = {
  1094. .size = sizeof(test_pasid_check),
  1095. .op = IOMMU_TEST_OP_PASID_CHECK_HWPT,
  1096. .id = stdev_id,
  1097. .pasid_check = {
  1098. .pasid = pasid,
  1099. .hwpt_id = hwpt_id,
  1100. },
  1101. };
  1102. return ioctl(fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_PASID_CHECK_HWPT),
  1103. &test_pasid_check);
  1104. }