iommufd.c 68 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES */
  3. #include <stdlib.h>
  4. #include <sys/mman.h>
  5. #include <sys/eventfd.h>
  6. #define __EXPORTED_HEADERS__
  7. #include <linux/vfio.h>
  8. #include "iommufd_utils.h"
  9. static unsigned long HUGEPAGE_SIZE;
  10. #define MOCK_PAGE_SIZE (PAGE_SIZE / 2)
  11. #define MOCK_HUGE_PAGE_SIZE (512 * MOCK_PAGE_SIZE)
  12. static unsigned long get_huge_page_size(void)
  13. {
  14. char buf[80];
  15. int ret;
  16. int fd;
  17. fd = open("/sys/kernel/mm/transparent_hugepage/hpage_pmd_size",
  18. O_RDONLY);
  19. if (fd < 0)
  20. return 2 * 1024 * 1024;
  21. ret = read(fd, buf, sizeof(buf));
  22. close(fd);
  23. if (ret <= 0 || ret == sizeof(buf))
  24. return 2 * 1024 * 1024;
  25. buf[ret] = 0;
  26. return strtoul(buf, NULL, 10);
  27. }
  28. static __attribute__((constructor)) void setup_sizes(void)
  29. {
  30. void *vrc;
  31. int rc;
  32. PAGE_SIZE = sysconf(_SC_PAGE_SIZE);
  33. HUGEPAGE_SIZE = get_huge_page_size();
  34. BUFFER_SIZE = PAGE_SIZE * 16;
  35. rc = posix_memalign(&buffer, HUGEPAGE_SIZE, BUFFER_SIZE);
  36. assert(!rc);
  37. assert(buffer);
  38. assert((uintptr_t)buffer % HUGEPAGE_SIZE == 0);
  39. vrc = mmap(buffer, BUFFER_SIZE, PROT_READ | PROT_WRITE,
  40. MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
  41. assert(vrc == buffer);
  42. }
  43. FIXTURE(iommufd)
  44. {
  45. int fd;
  46. };
  47. FIXTURE_SETUP(iommufd)
  48. {
  49. self->fd = open("/dev/iommu", O_RDWR);
  50. ASSERT_NE(-1, self->fd);
  51. }
  52. FIXTURE_TEARDOWN(iommufd)
  53. {
  54. teardown_iommufd(self->fd, _metadata);
  55. }
  56. TEST_F(iommufd, simple_close)
  57. {
  58. }
  59. TEST_F(iommufd, cmd_fail)
  60. {
  61. struct iommu_destroy cmd = { .size = sizeof(cmd), .id = 0 };
  62. /* object id is invalid */
  63. EXPECT_ERRNO(ENOENT, _test_ioctl_destroy(self->fd, 0));
  64. /* Bad pointer */
  65. EXPECT_ERRNO(EFAULT, ioctl(self->fd, IOMMU_DESTROY, NULL));
  66. /* Unknown ioctl */
  67. EXPECT_ERRNO(ENOTTY,
  68. ioctl(self->fd, _IO(IOMMUFD_TYPE, IOMMUFD_CMD_BASE - 1),
  69. &cmd));
  70. }
  71. TEST_F(iommufd, cmd_length)
  72. {
  73. #define TEST_LENGTH(_struct, _ioctl, _last) \
  74. { \
  75. size_t min_size = offsetofend(struct _struct, _last); \
  76. struct { \
  77. struct _struct cmd; \
  78. uint8_t extra; \
  79. } cmd = { .cmd = { .size = min_size - 1 }, \
  80. .extra = UINT8_MAX }; \
  81. int old_errno; \
  82. int rc; \
  83. \
  84. EXPECT_ERRNO(EINVAL, ioctl(self->fd, _ioctl, &cmd)); \
  85. cmd.cmd.size = sizeof(struct _struct) + 1; \
  86. EXPECT_ERRNO(E2BIG, ioctl(self->fd, _ioctl, &cmd)); \
  87. cmd.cmd.size = sizeof(struct _struct); \
  88. rc = ioctl(self->fd, _ioctl, &cmd); \
  89. old_errno = errno; \
  90. cmd.cmd.size = sizeof(struct _struct) + 1; \
  91. cmd.extra = 0; \
  92. if (rc) { \
  93. EXPECT_ERRNO(old_errno, \
  94. ioctl(self->fd, _ioctl, &cmd)); \
  95. } else { \
  96. ASSERT_EQ(0, ioctl(self->fd, _ioctl, &cmd)); \
  97. } \
  98. }
  99. TEST_LENGTH(iommu_destroy, IOMMU_DESTROY, id);
  100. TEST_LENGTH(iommu_hw_info, IOMMU_GET_HW_INFO, __reserved);
  101. TEST_LENGTH(iommu_hwpt_alloc, IOMMU_HWPT_ALLOC, __reserved);
  102. TEST_LENGTH(iommu_hwpt_invalidate, IOMMU_HWPT_INVALIDATE, __reserved);
  103. TEST_LENGTH(iommu_ioas_alloc, IOMMU_IOAS_ALLOC, out_ioas_id);
  104. TEST_LENGTH(iommu_ioas_iova_ranges, IOMMU_IOAS_IOVA_RANGES,
  105. out_iova_alignment);
  106. TEST_LENGTH(iommu_ioas_allow_iovas, IOMMU_IOAS_ALLOW_IOVAS,
  107. allowed_iovas);
  108. TEST_LENGTH(iommu_ioas_map, IOMMU_IOAS_MAP, iova);
  109. TEST_LENGTH(iommu_ioas_copy, IOMMU_IOAS_COPY, src_iova);
  110. TEST_LENGTH(iommu_ioas_unmap, IOMMU_IOAS_UNMAP, length);
  111. TEST_LENGTH(iommu_option, IOMMU_OPTION, val64);
  112. TEST_LENGTH(iommu_vfio_ioas, IOMMU_VFIO_IOAS, __reserved);
  113. #undef TEST_LENGTH
  114. }
  115. TEST_F(iommufd, cmd_ex_fail)
  116. {
  117. struct {
  118. struct iommu_destroy cmd;
  119. __u64 future;
  120. } cmd = { .cmd = { .size = sizeof(cmd), .id = 0 } };
  121. /* object id is invalid and command is longer */
  122. EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_DESTROY, &cmd));
  123. /* future area is non-zero */
  124. cmd.future = 1;
  125. EXPECT_ERRNO(E2BIG, ioctl(self->fd, IOMMU_DESTROY, &cmd));
  126. /* Original command "works" */
  127. cmd.cmd.size = sizeof(cmd.cmd);
  128. EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_DESTROY, &cmd));
  129. /* Short command fails */
  130. cmd.cmd.size = sizeof(cmd.cmd) - 1;
  131. EXPECT_ERRNO(EINVAL, ioctl(self->fd, IOMMU_DESTROY, &cmd));
  132. }
  133. TEST_F(iommufd, global_options)
  134. {
  135. struct iommu_option cmd = {
  136. .size = sizeof(cmd),
  137. .option_id = IOMMU_OPTION_RLIMIT_MODE,
  138. .op = IOMMU_OPTION_OP_GET,
  139. .val64 = 1,
  140. };
  141. cmd.option_id = IOMMU_OPTION_RLIMIT_MODE;
  142. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  143. ASSERT_EQ(0, cmd.val64);
  144. /* This requires root */
  145. cmd.op = IOMMU_OPTION_OP_SET;
  146. cmd.val64 = 1;
  147. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  148. cmd.val64 = 2;
  149. EXPECT_ERRNO(EINVAL, ioctl(self->fd, IOMMU_OPTION, &cmd));
  150. cmd.op = IOMMU_OPTION_OP_GET;
  151. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  152. ASSERT_EQ(1, cmd.val64);
  153. cmd.op = IOMMU_OPTION_OP_SET;
  154. cmd.val64 = 0;
  155. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  156. cmd.op = IOMMU_OPTION_OP_GET;
  157. cmd.option_id = IOMMU_OPTION_HUGE_PAGES;
  158. EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_OPTION, &cmd));
  159. cmd.op = IOMMU_OPTION_OP_SET;
  160. EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_OPTION, &cmd));
  161. }
  162. FIXTURE(iommufd_ioas)
  163. {
  164. int fd;
  165. uint32_t ioas_id;
  166. uint32_t stdev_id;
  167. uint32_t hwpt_id;
  168. uint32_t device_id;
  169. uint64_t base_iova;
  170. };
  171. FIXTURE_VARIANT(iommufd_ioas)
  172. {
  173. unsigned int mock_domains;
  174. unsigned int memory_limit;
  175. };
  176. FIXTURE_SETUP(iommufd_ioas)
  177. {
  178. unsigned int i;
  179. self->fd = open("/dev/iommu", O_RDWR);
  180. ASSERT_NE(-1, self->fd);
  181. test_ioctl_ioas_alloc(&self->ioas_id);
  182. if (!variant->memory_limit) {
  183. test_ioctl_set_default_memory_limit();
  184. } else {
  185. test_ioctl_set_temp_memory_limit(variant->memory_limit);
  186. }
  187. for (i = 0; i != variant->mock_domains; i++) {
  188. test_cmd_mock_domain(self->ioas_id, &self->stdev_id,
  189. &self->hwpt_id, &self->device_id);
  190. self->base_iova = MOCK_APERTURE_START;
  191. }
  192. }
  193. FIXTURE_TEARDOWN(iommufd_ioas)
  194. {
  195. test_ioctl_set_default_memory_limit();
  196. teardown_iommufd(self->fd, _metadata);
  197. }
  198. FIXTURE_VARIANT_ADD(iommufd_ioas, no_domain)
  199. {
  200. };
  201. FIXTURE_VARIANT_ADD(iommufd_ioas, mock_domain)
  202. {
  203. .mock_domains = 1,
  204. };
  205. FIXTURE_VARIANT_ADD(iommufd_ioas, two_mock_domain)
  206. {
  207. .mock_domains = 2,
  208. };
  209. FIXTURE_VARIANT_ADD(iommufd_ioas, mock_domain_limit)
  210. {
  211. .mock_domains = 1,
  212. .memory_limit = 16,
  213. };
  214. TEST_F(iommufd_ioas, ioas_auto_destroy)
  215. {
  216. }
  217. TEST_F(iommufd_ioas, ioas_destroy)
  218. {
  219. if (self->stdev_id) {
  220. /* IOAS cannot be freed while a device has a HWPT using it */
  221. EXPECT_ERRNO(EBUSY,
  222. _test_ioctl_destroy(self->fd, self->ioas_id));
  223. } else {
  224. /* Can allocate and manually free an IOAS table */
  225. test_ioctl_destroy(self->ioas_id);
  226. }
  227. }
  228. TEST_F(iommufd_ioas, alloc_hwpt_nested)
  229. {
  230. const uint32_t min_data_len =
  231. offsetofend(struct iommu_hwpt_selftest, iotlb);
  232. struct iommu_hwpt_selftest data = {
  233. .iotlb = IOMMU_TEST_IOTLB_DEFAULT,
  234. };
  235. struct iommu_hwpt_invalidate_selftest inv_reqs[2] = {};
  236. uint32_t nested_hwpt_id[2] = {};
  237. uint32_t num_inv;
  238. uint32_t parent_hwpt_id = 0;
  239. uint32_t parent_hwpt_id_not_work = 0;
  240. uint32_t test_hwpt_id = 0;
  241. uint32_t iopf_hwpt_id;
  242. uint32_t fault_id;
  243. uint32_t fault_fd;
  244. if (self->device_id) {
  245. /* Negative tests */
  246. test_err_hwpt_alloc(ENOENT, self->ioas_id, self->device_id, 0,
  247. &test_hwpt_id);
  248. test_err_hwpt_alloc(EINVAL, self->device_id, self->device_id, 0,
  249. &test_hwpt_id);
  250. test_err_hwpt_alloc(EOPNOTSUPP, self->device_id, self->ioas_id,
  251. IOMMU_HWPT_ALLOC_NEST_PARENT |
  252. IOMMU_HWPT_FAULT_ID_VALID,
  253. &test_hwpt_id);
  254. test_cmd_hwpt_alloc(self->device_id, self->ioas_id,
  255. IOMMU_HWPT_ALLOC_NEST_PARENT,
  256. &parent_hwpt_id);
  257. test_cmd_hwpt_alloc(self->device_id, self->ioas_id, 0,
  258. &parent_hwpt_id_not_work);
  259. /* Negative nested tests */
  260. test_err_hwpt_alloc_nested(EINVAL, self->device_id,
  261. parent_hwpt_id, 0,
  262. &nested_hwpt_id[0],
  263. IOMMU_HWPT_DATA_NONE, &data,
  264. sizeof(data));
  265. test_err_hwpt_alloc_nested(EOPNOTSUPP, self->device_id,
  266. parent_hwpt_id, 0,
  267. &nested_hwpt_id[0],
  268. IOMMU_HWPT_DATA_SELFTEST + 1, &data,
  269. sizeof(data));
  270. test_err_hwpt_alloc_nested(EINVAL, self->device_id,
  271. parent_hwpt_id, 0,
  272. &nested_hwpt_id[0],
  273. IOMMU_HWPT_DATA_SELFTEST, &data,
  274. min_data_len - 1);
  275. test_err_hwpt_alloc_nested(EFAULT, self->device_id,
  276. parent_hwpt_id, 0,
  277. &nested_hwpt_id[0],
  278. IOMMU_HWPT_DATA_SELFTEST, NULL,
  279. sizeof(data));
  280. test_err_hwpt_alloc_nested(
  281. EOPNOTSUPP, self->device_id, parent_hwpt_id,
  282. IOMMU_HWPT_ALLOC_NEST_PARENT, &nested_hwpt_id[0],
  283. IOMMU_HWPT_DATA_SELFTEST, &data, sizeof(data));
  284. test_err_hwpt_alloc_nested(EINVAL, self->device_id,
  285. parent_hwpt_id_not_work, 0,
  286. &nested_hwpt_id[0],
  287. IOMMU_HWPT_DATA_SELFTEST, &data,
  288. sizeof(data));
  289. /* Allocate two nested hwpts sharing one common parent hwpt */
  290. test_ioctl_fault_alloc(&fault_id, &fault_fd);
  291. test_cmd_hwpt_alloc_nested(self->device_id, parent_hwpt_id, 0,
  292. &nested_hwpt_id[0],
  293. IOMMU_HWPT_DATA_SELFTEST, &data,
  294. sizeof(data));
  295. test_cmd_hwpt_alloc_nested(self->device_id, parent_hwpt_id, 0,
  296. &nested_hwpt_id[1],
  297. IOMMU_HWPT_DATA_SELFTEST, &data,
  298. sizeof(data));
  299. test_err_hwpt_alloc_iopf(ENOENT, self->device_id, parent_hwpt_id,
  300. UINT32_MAX, IOMMU_HWPT_FAULT_ID_VALID,
  301. &iopf_hwpt_id, IOMMU_HWPT_DATA_SELFTEST,
  302. &data, sizeof(data));
  303. test_cmd_hwpt_alloc_iopf(self->device_id, parent_hwpt_id, fault_id,
  304. IOMMU_HWPT_FAULT_ID_VALID, &iopf_hwpt_id,
  305. IOMMU_HWPT_DATA_SELFTEST, &data,
  306. sizeof(data));
  307. test_cmd_hwpt_check_iotlb_all(nested_hwpt_id[0],
  308. IOMMU_TEST_IOTLB_DEFAULT);
  309. test_cmd_hwpt_check_iotlb_all(nested_hwpt_id[1],
  310. IOMMU_TEST_IOTLB_DEFAULT);
  311. /* Negative test: a nested hwpt on top of a nested hwpt */
  312. test_err_hwpt_alloc_nested(EINVAL, self->device_id,
  313. nested_hwpt_id[0], 0, &test_hwpt_id,
  314. IOMMU_HWPT_DATA_SELFTEST, &data,
  315. sizeof(data));
  316. /* Negative test: parent hwpt now cannot be freed */
  317. EXPECT_ERRNO(EBUSY,
  318. _test_ioctl_destroy(self->fd, parent_hwpt_id));
  319. /* hwpt_invalidate only supports a user-managed hwpt (nested) */
  320. num_inv = 1;
  321. test_err_hwpt_invalidate(ENOENT, parent_hwpt_id, inv_reqs,
  322. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  323. sizeof(*inv_reqs), &num_inv);
  324. assert(!num_inv);
  325. /* Check data_type by passing zero-length array */
  326. num_inv = 0;
  327. test_cmd_hwpt_invalidate(nested_hwpt_id[0], inv_reqs,
  328. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  329. sizeof(*inv_reqs), &num_inv);
  330. assert(!num_inv);
  331. /* Negative test: Invalid data_type */
  332. num_inv = 1;
  333. test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
  334. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST_INVALID,
  335. sizeof(*inv_reqs), &num_inv);
  336. assert(!num_inv);
  337. /* Negative test: structure size sanity */
  338. num_inv = 1;
  339. test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
  340. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  341. sizeof(*inv_reqs) + 1, &num_inv);
  342. assert(!num_inv);
  343. num_inv = 1;
  344. test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
  345. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  346. 1, &num_inv);
  347. assert(!num_inv);
  348. /* Negative test: invalid flag is passed */
  349. num_inv = 1;
  350. inv_reqs[0].flags = 0xffffffff;
  351. test_err_hwpt_invalidate(EOPNOTSUPP, nested_hwpt_id[0], inv_reqs,
  352. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  353. sizeof(*inv_reqs), &num_inv);
  354. assert(!num_inv);
  355. /* Negative test: invalid data_uptr when array is not empty */
  356. num_inv = 1;
  357. inv_reqs[0].flags = 0;
  358. test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], NULL,
  359. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  360. sizeof(*inv_reqs), &num_inv);
  361. assert(!num_inv);
  362. /* Negative test: invalid entry_len when array is not empty */
  363. num_inv = 1;
  364. inv_reqs[0].flags = 0;
  365. test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
  366. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  367. 0, &num_inv);
  368. assert(!num_inv);
  369. /* Negative test: invalid iotlb_id */
  370. num_inv = 1;
  371. inv_reqs[0].flags = 0;
  372. inv_reqs[0].iotlb_id = MOCK_NESTED_DOMAIN_IOTLB_ID_MAX + 1;
  373. test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
  374. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  375. sizeof(*inv_reqs), &num_inv);
  376. assert(!num_inv);
  377. /*
  378. * Invalidate the 1st iotlb entry but fail the 2nd request
  379. * due to invalid flags configuration in the 2nd request.
  380. */
  381. num_inv = 2;
  382. inv_reqs[0].flags = 0;
  383. inv_reqs[0].iotlb_id = 0;
  384. inv_reqs[1].flags = 0xffffffff;
  385. inv_reqs[1].iotlb_id = 1;
  386. test_err_hwpt_invalidate(EOPNOTSUPP, nested_hwpt_id[0], inv_reqs,
  387. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  388. sizeof(*inv_reqs), &num_inv);
  389. assert(num_inv == 1);
  390. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 0, 0);
  391. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 1,
  392. IOMMU_TEST_IOTLB_DEFAULT);
  393. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 2,
  394. IOMMU_TEST_IOTLB_DEFAULT);
  395. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 3,
  396. IOMMU_TEST_IOTLB_DEFAULT);
  397. /*
  398. * Invalidate the 1st iotlb entry but fail the 2nd request
  399. * due to invalid iotlb_id configuration in the 2nd request.
  400. */
  401. num_inv = 2;
  402. inv_reqs[0].flags = 0;
  403. inv_reqs[0].iotlb_id = 0;
  404. inv_reqs[1].flags = 0;
  405. inv_reqs[1].iotlb_id = MOCK_NESTED_DOMAIN_IOTLB_ID_MAX + 1;
  406. test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
  407. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  408. sizeof(*inv_reqs), &num_inv);
  409. assert(num_inv == 1);
  410. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 0, 0);
  411. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 1,
  412. IOMMU_TEST_IOTLB_DEFAULT);
  413. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 2,
  414. IOMMU_TEST_IOTLB_DEFAULT);
  415. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 3,
  416. IOMMU_TEST_IOTLB_DEFAULT);
  417. /* Invalidate the 2nd iotlb entry and verify */
  418. num_inv = 1;
  419. inv_reqs[0].flags = 0;
  420. inv_reqs[0].iotlb_id = 1;
  421. test_cmd_hwpt_invalidate(nested_hwpt_id[0], inv_reqs,
  422. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  423. sizeof(*inv_reqs), &num_inv);
  424. assert(num_inv == 1);
  425. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 0, 0);
  426. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 1, 0);
  427. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 2,
  428. IOMMU_TEST_IOTLB_DEFAULT);
  429. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 3,
  430. IOMMU_TEST_IOTLB_DEFAULT);
  431. /* Invalidate the 3rd and 4th iotlb entries and verify */
  432. num_inv = 2;
  433. inv_reqs[0].flags = 0;
  434. inv_reqs[0].iotlb_id = 2;
  435. inv_reqs[1].flags = 0;
  436. inv_reqs[1].iotlb_id = 3;
  437. test_cmd_hwpt_invalidate(nested_hwpt_id[0], inv_reqs,
  438. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  439. sizeof(*inv_reqs), &num_inv);
  440. assert(num_inv == 2);
  441. test_cmd_hwpt_check_iotlb_all(nested_hwpt_id[0], 0);
  442. /* Invalidate all iotlb entries for nested_hwpt_id[1] and verify */
  443. num_inv = 1;
  444. inv_reqs[0].flags = IOMMU_TEST_INVALIDATE_FLAG_ALL;
  445. test_cmd_hwpt_invalidate(nested_hwpt_id[1], inv_reqs,
  446. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  447. sizeof(*inv_reqs), &num_inv);
  448. assert(num_inv == 1);
  449. test_cmd_hwpt_check_iotlb_all(nested_hwpt_id[1], 0);
  450. /* Attach device to nested_hwpt_id[0] that then will be busy */
  451. test_cmd_mock_domain_replace(self->stdev_id, nested_hwpt_id[0]);
  452. EXPECT_ERRNO(EBUSY,
  453. _test_ioctl_destroy(self->fd, nested_hwpt_id[0]));
  454. /* Switch from nested_hwpt_id[0] to nested_hwpt_id[1] */
  455. test_cmd_mock_domain_replace(self->stdev_id, nested_hwpt_id[1]);
  456. EXPECT_ERRNO(EBUSY,
  457. _test_ioctl_destroy(self->fd, nested_hwpt_id[1]));
  458. test_ioctl_destroy(nested_hwpt_id[0]);
  459. /* Switch from nested_hwpt_id[1] to iopf_hwpt_id */
  460. test_cmd_mock_domain_replace(self->stdev_id, iopf_hwpt_id);
  461. EXPECT_ERRNO(EBUSY,
  462. _test_ioctl_destroy(self->fd, iopf_hwpt_id));
  463. /* Trigger an IOPF on the device */
  464. test_cmd_trigger_iopf(self->device_id, fault_fd);
  465. /* Detach from nested_hwpt_id[1] and destroy it */
  466. test_cmd_mock_domain_replace(self->stdev_id, parent_hwpt_id);
  467. test_ioctl_destroy(nested_hwpt_id[1]);
  468. test_ioctl_destroy(iopf_hwpt_id);
  469. /* Detach from the parent hw_pagetable and destroy it */
  470. test_cmd_mock_domain_replace(self->stdev_id, self->ioas_id);
  471. test_ioctl_destroy(parent_hwpt_id);
  472. test_ioctl_destroy(parent_hwpt_id_not_work);
  473. close(fault_fd);
  474. test_ioctl_destroy(fault_id);
  475. } else {
  476. test_err_hwpt_alloc(ENOENT, self->device_id, self->ioas_id, 0,
  477. &parent_hwpt_id);
  478. test_err_hwpt_alloc_nested(ENOENT, self->device_id,
  479. parent_hwpt_id, 0,
  480. &nested_hwpt_id[0],
  481. IOMMU_HWPT_DATA_SELFTEST, &data,
  482. sizeof(data));
  483. test_err_hwpt_alloc_nested(ENOENT, self->device_id,
  484. parent_hwpt_id, 0,
  485. &nested_hwpt_id[1],
  486. IOMMU_HWPT_DATA_SELFTEST, &data,
  487. sizeof(data));
  488. test_err_mock_domain_replace(ENOENT, self->stdev_id,
  489. nested_hwpt_id[0]);
  490. test_err_mock_domain_replace(ENOENT, self->stdev_id,
  491. nested_hwpt_id[1]);
  492. }
  493. }
  494. TEST_F(iommufd_ioas, hwpt_attach)
  495. {
  496. /* Create a device attached directly to a hwpt */
  497. if (self->stdev_id) {
  498. test_cmd_mock_domain(self->hwpt_id, NULL, NULL, NULL);
  499. } else {
  500. test_err_mock_domain(ENOENT, self->hwpt_id, NULL, NULL);
  501. }
  502. }
  503. TEST_F(iommufd_ioas, ioas_area_destroy)
  504. {
  505. /* Adding an area does not change ability to destroy */
  506. test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE, self->base_iova);
  507. if (self->stdev_id)
  508. EXPECT_ERRNO(EBUSY,
  509. _test_ioctl_destroy(self->fd, self->ioas_id));
  510. else
  511. test_ioctl_destroy(self->ioas_id);
  512. }
  513. TEST_F(iommufd_ioas, ioas_area_auto_destroy)
  514. {
  515. int i;
  516. /* Can allocate and automatically free an IOAS table with many areas */
  517. for (i = 0; i != 10; i++) {
  518. test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE,
  519. self->base_iova + i * PAGE_SIZE);
  520. }
  521. }
  522. TEST_F(iommufd_ioas, get_hw_info)
  523. {
  524. struct iommu_test_hw_info buffer_exact;
  525. struct iommu_test_hw_info_buffer_larger {
  526. struct iommu_test_hw_info info;
  527. uint64_t trailing_bytes;
  528. } buffer_larger;
  529. struct iommu_test_hw_info_buffer_smaller {
  530. __u32 flags;
  531. } buffer_smaller;
  532. if (self->device_id) {
  533. /* Provide a zero-size user_buffer */
  534. test_cmd_get_hw_info(self->device_id, NULL, 0);
  535. /* Provide a user_buffer with exact size */
  536. test_cmd_get_hw_info(self->device_id, &buffer_exact, sizeof(buffer_exact));
  537. /*
  538. * Provide a user_buffer with size larger than the exact size to check if
  539. * kernel zero the trailing bytes.
  540. */
  541. test_cmd_get_hw_info(self->device_id, &buffer_larger, sizeof(buffer_larger));
  542. /*
  543. * Provide a user_buffer with size smaller than the exact size to check if
  544. * the fields within the size range still gets updated.
  545. */
  546. test_cmd_get_hw_info(self->device_id, &buffer_smaller, sizeof(buffer_smaller));
  547. } else {
  548. test_err_get_hw_info(ENOENT, self->device_id,
  549. &buffer_exact, sizeof(buffer_exact));
  550. test_err_get_hw_info(ENOENT, self->device_id,
  551. &buffer_larger, sizeof(buffer_larger));
  552. }
  553. }
  554. TEST_F(iommufd_ioas, area)
  555. {
  556. int i;
  557. /* Unmap fails if nothing is mapped */
  558. for (i = 0; i != 10; i++)
  559. test_err_ioctl_ioas_unmap(ENOENT, i * PAGE_SIZE, PAGE_SIZE);
  560. /* Unmap works */
  561. for (i = 0; i != 10; i++)
  562. test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE,
  563. self->base_iova + i * PAGE_SIZE);
  564. for (i = 0; i != 10; i++)
  565. test_ioctl_ioas_unmap(self->base_iova + i * PAGE_SIZE,
  566. PAGE_SIZE);
  567. /* Split fails */
  568. test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE * 2,
  569. self->base_iova + 16 * PAGE_SIZE);
  570. test_err_ioctl_ioas_unmap(ENOENT, self->base_iova + 16 * PAGE_SIZE,
  571. PAGE_SIZE);
  572. test_err_ioctl_ioas_unmap(ENOENT, self->base_iova + 17 * PAGE_SIZE,
  573. PAGE_SIZE);
  574. /* Over map fails */
  575. test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE * 2,
  576. self->base_iova + 16 * PAGE_SIZE);
  577. test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE,
  578. self->base_iova + 16 * PAGE_SIZE);
  579. test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE,
  580. self->base_iova + 17 * PAGE_SIZE);
  581. test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE * 2,
  582. self->base_iova + 15 * PAGE_SIZE);
  583. test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE * 3,
  584. self->base_iova + 15 * PAGE_SIZE);
  585. /* unmap all works */
  586. test_ioctl_ioas_unmap(0, UINT64_MAX);
  587. /* Unmap all succeeds on an empty IOAS */
  588. test_ioctl_ioas_unmap(0, UINT64_MAX);
  589. }
  590. TEST_F(iommufd_ioas, unmap_fully_contained_areas)
  591. {
  592. uint64_t unmap_len;
  593. int i;
  594. /* Give no_domain some space to rewind base_iova */
  595. self->base_iova += 4 * PAGE_SIZE;
  596. for (i = 0; i != 4; i++)
  597. test_ioctl_ioas_map_fixed(buffer, 8 * PAGE_SIZE,
  598. self->base_iova + i * 16 * PAGE_SIZE);
  599. /* Unmap not fully contained area doesn't work */
  600. test_err_ioctl_ioas_unmap(ENOENT, self->base_iova - 4 * PAGE_SIZE,
  601. 8 * PAGE_SIZE);
  602. test_err_ioctl_ioas_unmap(ENOENT,
  603. self->base_iova + 3 * 16 * PAGE_SIZE +
  604. 8 * PAGE_SIZE - 4 * PAGE_SIZE,
  605. 8 * PAGE_SIZE);
  606. /* Unmap fully contained areas works */
  607. ASSERT_EQ(0, _test_ioctl_ioas_unmap(self->fd, self->ioas_id,
  608. self->base_iova - 4 * PAGE_SIZE,
  609. 3 * 16 * PAGE_SIZE + 8 * PAGE_SIZE +
  610. 4 * PAGE_SIZE,
  611. &unmap_len));
  612. ASSERT_EQ(32 * PAGE_SIZE, unmap_len);
  613. }
  614. TEST_F(iommufd_ioas, area_auto_iova)
  615. {
  616. struct iommu_test_cmd test_cmd = {
  617. .size = sizeof(test_cmd),
  618. .op = IOMMU_TEST_OP_ADD_RESERVED,
  619. .id = self->ioas_id,
  620. .add_reserved = { .start = PAGE_SIZE * 4,
  621. .length = PAGE_SIZE * 100 },
  622. };
  623. struct iommu_iova_range ranges[1] = {};
  624. struct iommu_ioas_allow_iovas allow_cmd = {
  625. .size = sizeof(allow_cmd),
  626. .ioas_id = self->ioas_id,
  627. .num_iovas = 1,
  628. .allowed_iovas = (uintptr_t)ranges,
  629. };
  630. __u64 iovas[10];
  631. int i;
  632. /* Simple 4k pages */
  633. for (i = 0; i != 10; i++)
  634. test_ioctl_ioas_map(buffer, PAGE_SIZE, &iovas[i]);
  635. for (i = 0; i != 10; i++)
  636. test_ioctl_ioas_unmap(iovas[i], PAGE_SIZE);
  637. /* Kernel automatically aligns IOVAs properly */
  638. for (i = 0; i != 10; i++) {
  639. size_t length = PAGE_SIZE * (i + 1);
  640. if (self->stdev_id) {
  641. test_ioctl_ioas_map(buffer, length, &iovas[i]);
  642. } else {
  643. test_ioctl_ioas_map((void *)(1UL << 31), length,
  644. &iovas[i]);
  645. }
  646. EXPECT_EQ(0, iovas[i] % (1UL << (ffs(length) - 1)));
  647. }
  648. for (i = 0; i != 10; i++)
  649. test_ioctl_ioas_unmap(iovas[i], PAGE_SIZE * (i + 1));
  650. /* Avoids a reserved region */
  651. ASSERT_EQ(0,
  652. ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
  653. &test_cmd));
  654. for (i = 0; i != 10; i++) {
  655. size_t length = PAGE_SIZE * (i + 1);
  656. test_ioctl_ioas_map(buffer, length, &iovas[i]);
  657. EXPECT_EQ(0, iovas[i] % (1UL << (ffs(length) - 1)));
  658. EXPECT_EQ(false,
  659. iovas[i] > test_cmd.add_reserved.start &&
  660. iovas[i] <
  661. test_cmd.add_reserved.start +
  662. test_cmd.add_reserved.length);
  663. }
  664. for (i = 0; i != 10; i++)
  665. test_ioctl_ioas_unmap(iovas[i], PAGE_SIZE * (i + 1));
  666. /* Allowed region intersects with a reserved region */
  667. ranges[0].start = PAGE_SIZE;
  668. ranges[0].last = PAGE_SIZE * 600;
  669. EXPECT_ERRNO(EADDRINUSE,
  670. ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
  671. /* Allocate from an allowed region */
  672. if (self->stdev_id) {
  673. ranges[0].start = MOCK_APERTURE_START + PAGE_SIZE;
  674. ranges[0].last = MOCK_APERTURE_START + PAGE_SIZE * 600 - 1;
  675. } else {
  676. ranges[0].start = PAGE_SIZE * 200;
  677. ranges[0].last = PAGE_SIZE * 600 - 1;
  678. }
  679. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
  680. for (i = 0; i != 10; i++) {
  681. size_t length = PAGE_SIZE * (i + 1);
  682. test_ioctl_ioas_map(buffer, length, &iovas[i]);
  683. EXPECT_EQ(0, iovas[i] % (1UL << (ffs(length) - 1)));
  684. EXPECT_EQ(true, iovas[i] >= ranges[0].start);
  685. EXPECT_EQ(true, iovas[i] <= ranges[0].last);
  686. EXPECT_EQ(true, iovas[i] + length > ranges[0].start);
  687. EXPECT_EQ(true, iovas[i] + length <= ranges[0].last + 1);
  688. }
  689. for (i = 0; i != 10; i++)
  690. test_ioctl_ioas_unmap(iovas[i], PAGE_SIZE * (i + 1));
  691. }
  692. TEST_F(iommufd_ioas, area_allowed)
  693. {
  694. struct iommu_test_cmd test_cmd = {
  695. .size = sizeof(test_cmd),
  696. .op = IOMMU_TEST_OP_ADD_RESERVED,
  697. .id = self->ioas_id,
  698. .add_reserved = { .start = PAGE_SIZE * 4,
  699. .length = PAGE_SIZE * 100 },
  700. };
  701. struct iommu_iova_range ranges[1] = {};
  702. struct iommu_ioas_allow_iovas allow_cmd = {
  703. .size = sizeof(allow_cmd),
  704. .ioas_id = self->ioas_id,
  705. .num_iovas = 1,
  706. .allowed_iovas = (uintptr_t)ranges,
  707. };
  708. /* Reserved intersects an allowed */
  709. allow_cmd.num_iovas = 1;
  710. ranges[0].start = self->base_iova;
  711. ranges[0].last = ranges[0].start + PAGE_SIZE * 600;
  712. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
  713. test_cmd.add_reserved.start = ranges[0].start + PAGE_SIZE;
  714. test_cmd.add_reserved.length = PAGE_SIZE;
  715. EXPECT_ERRNO(EADDRINUSE,
  716. ioctl(self->fd,
  717. _IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
  718. &test_cmd));
  719. allow_cmd.num_iovas = 0;
  720. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
  721. /* Allowed intersects a reserved */
  722. ASSERT_EQ(0,
  723. ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
  724. &test_cmd));
  725. allow_cmd.num_iovas = 1;
  726. ranges[0].start = self->base_iova;
  727. ranges[0].last = ranges[0].start + PAGE_SIZE * 600;
  728. EXPECT_ERRNO(EADDRINUSE,
  729. ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
  730. }
  731. TEST_F(iommufd_ioas, copy_area)
  732. {
  733. struct iommu_ioas_copy copy_cmd = {
  734. .size = sizeof(copy_cmd),
  735. .flags = IOMMU_IOAS_MAP_FIXED_IOVA | IOMMU_IOAS_MAP_WRITEABLE,
  736. .dst_ioas_id = self->ioas_id,
  737. .src_ioas_id = self->ioas_id,
  738. .length = PAGE_SIZE,
  739. };
  740. test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE, self->base_iova);
  741. /* Copy inside a single IOAS */
  742. copy_cmd.src_iova = self->base_iova;
  743. copy_cmd.dst_iova = self->base_iova + PAGE_SIZE;
  744. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
  745. /* Copy between IOAS's */
  746. copy_cmd.src_iova = self->base_iova;
  747. copy_cmd.dst_iova = 0;
  748. test_ioctl_ioas_alloc(&copy_cmd.dst_ioas_id);
  749. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
  750. }
  751. TEST_F(iommufd_ioas, iova_ranges)
  752. {
  753. struct iommu_test_cmd test_cmd = {
  754. .size = sizeof(test_cmd),
  755. .op = IOMMU_TEST_OP_ADD_RESERVED,
  756. .id = self->ioas_id,
  757. .add_reserved = { .start = PAGE_SIZE, .length = PAGE_SIZE },
  758. };
  759. struct iommu_iova_range *ranges = buffer;
  760. struct iommu_ioas_iova_ranges ranges_cmd = {
  761. .size = sizeof(ranges_cmd),
  762. .ioas_id = self->ioas_id,
  763. .num_iovas = BUFFER_SIZE / sizeof(*ranges),
  764. .allowed_iovas = (uintptr_t)ranges,
  765. };
  766. /* Range can be read */
  767. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES, &ranges_cmd));
  768. EXPECT_EQ(1, ranges_cmd.num_iovas);
  769. if (!self->stdev_id) {
  770. EXPECT_EQ(0, ranges[0].start);
  771. EXPECT_EQ(SIZE_MAX, ranges[0].last);
  772. EXPECT_EQ(1, ranges_cmd.out_iova_alignment);
  773. } else {
  774. EXPECT_EQ(MOCK_APERTURE_START, ranges[0].start);
  775. EXPECT_EQ(MOCK_APERTURE_LAST, ranges[0].last);
  776. EXPECT_EQ(MOCK_PAGE_SIZE, ranges_cmd.out_iova_alignment);
  777. }
  778. /* Buffer too small */
  779. memset(ranges, 0, BUFFER_SIZE);
  780. ranges_cmd.num_iovas = 0;
  781. EXPECT_ERRNO(EMSGSIZE,
  782. ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES, &ranges_cmd));
  783. EXPECT_EQ(1, ranges_cmd.num_iovas);
  784. EXPECT_EQ(0, ranges[0].start);
  785. EXPECT_EQ(0, ranges[0].last);
  786. /* 2 ranges */
  787. ASSERT_EQ(0,
  788. ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
  789. &test_cmd));
  790. ranges_cmd.num_iovas = BUFFER_SIZE / sizeof(*ranges);
  791. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES, &ranges_cmd));
  792. if (!self->stdev_id) {
  793. EXPECT_EQ(2, ranges_cmd.num_iovas);
  794. EXPECT_EQ(0, ranges[0].start);
  795. EXPECT_EQ(PAGE_SIZE - 1, ranges[0].last);
  796. EXPECT_EQ(PAGE_SIZE * 2, ranges[1].start);
  797. EXPECT_EQ(SIZE_MAX, ranges[1].last);
  798. } else {
  799. EXPECT_EQ(1, ranges_cmd.num_iovas);
  800. EXPECT_EQ(MOCK_APERTURE_START, ranges[0].start);
  801. EXPECT_EQ(MOCK_APERTURE_LAST, ranges[0].last);
  802. }
  803. /* Buffer too small */
  804. memset(ranges, 0, BUFFER_SIZE);
  805. ranges_cmd.num_iovas = 1;
  806. if (!self->stdev_id) {
  807. EXPECT_ERRNO(EMSGSIZE, ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES,
  808. &ranges_cmd));
  809. EXPECT_EQ(2, ranges_cmd.num_iovas);
  810. EXPECT_EQ(0, ranges[0].start);
  811. EXPECT_EQ(PAGE_SIZE - 1, ranges[0].last);
  812. } else {
  813. ASSERT_EQ(0,
  814. ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES, &ranges_cmd));
  815. EXPECT_EQ(1, ranges_cmd.num_iovas);
  816. EXPECT_EQ(MOCK_APERTURE_START, ranges[0].start);
  817. EXPECT_EQ(MOCK_APERTURE_LAST, ranges[0].last);
  818. }
  819. EXPECT_EQ(0, ranges[1].start);
  820. EXPECT_EQ(0, ranges[1].last);
  821. }
  822. TEST_F(iommufd_ioas, access_domain_destory)
  823. {
  824. struct iommu_test_cmd access_cmd = {
  825. .size = sizeof(access_cmd),
  826. .op = IOMMU_TEST_OP_ACCESS_PAGES,
  827. .access_pages = { .iova = self->base_iova + PAGE_SIZE,
  828. .length = PAGE_SIZE},
  829. };
  830. size_t buf_size = 2 * HUGEPAGE_SIZE;
  831. uint8_t *buf;
  832. buf = mmap(0, buf_size, PROT_READ | PROT_WRITE,
  833. MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, -1,
  834. 0);
  835. ASSERT_NE(MAP_FAILED, buf);
  836. test_ioctl_ioas_map_fixed(buf, buf_size, self->base_iova);
  837. test_cmd_create_access(self->ioas_id, &access_cmd.id,
  838. MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES);
  839. access_cmd.access_pages.uptr = (uintptr_t)buf + PAGE_SIZE;
  840. ASSERT_EQ(0,
  841. ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
  842. &access_cmd));
  843. /* Causes a complicated unpin across a huge page boundary */
  844. if (self->stdev_id)
  845. test_ioctl_destroy(self->stdev_id);
  846. test_cmd_destroy_access_pages(
  847. access_cmd.id, access_cmd.access_pages.out_access_pages_id);
  848. test_cmd_destroy_access(access_cmd.id);
  849. ASSERT_EQ(0, munmap(buf, buf_size));
  850. }
  851. TEST_F(iommufd_ioas, access_pin)
  852. {
  853. struct iommu_test_cmd access_cmd = {
  854. .size = sizeof(access_cmd),
  855. .op = IOMMU_TEST_OP_ACCESS_PAGES,
  856. .access_pages = { .iova = MOCK_APERTURE_START,
  857. .length = BUFFER_SIZE,
  858. .uptr = (uintptr_t)buffer },
  859. };
  860. struct iommu_test_cmd check_map_cmd = {
  861. .size = sizeof(check_map_cmd),
  862. .op = IOMMU_TEST_OP_MD_CHECK_MAP,
  863. .check_map = { .iova = MOCK_APERTURE_START,
  864. .length = BUFFER_SIZE,
  865. .uptr = (uintptr_t)buffer },
  866. };
  867. uint32_t access_pages_id;
  868. unsigned int npages;
  869. test_cmd_create_access(self->ioas_id, &access_cmd.id,
  870. MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES);
  871. for (npages = 1; npages < BUFFER_SIZE / PAGE_SIZE; npages++) {
  872. uint32_t mock_stdev_id;
  873. uint32_t mock_hwpt_id;
  874. access_cmd.access_pages.length = npages * PAGE_SIZE;
  875. /* Single map/unmap */
  876. test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE,
  877. MOCK_APERTURE_START);
  878. ASSERT_EQ(0, ioctl(self->fd,
  879. _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
  880. &access_cmd));
  881. test_cmd_destroy_access_pages(
  882. access_cmd.id,
  883. access_cmd.access_pages.out_access_pages_id);
  884. /* Double user */
  885. ASSERT_EQ(0, ioctl(self->fd,
  886. _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
  887. &access_cmd));
  888. access_pages_id = access_cmd.access_pages.out_access_pages_id;
  889. ASSERT_EQ(0, ioctl(self->fd,
  890. _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
  891. &access_cmd));
  892. test_cmd_destroy_access_pages(
  893. access_cmd.id,
  894. access_cmd.access_pages.out_access_pages_id);
  895. test_cmd_destroy_access_pages(access_cmd.id, access_pages_id);
  896. /* Add/remove a domain with a user */
  897. ASSERT_EQ(0, ioctl(self->fd,
  898. _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
  899. &access_cmd));
  900. test_cmd_mock_domain(self->ioas_id, &mock_stdev_id,
  901. &mock_hwpt_id, NULL);
  902. check_map_cmd.id = mock_hwpt_id;
  903. ASSERT_EQ(0, ioctl(self->fd,
  904. _IOMMU_TEST_CMD(IOMMU_TEST_OP_MD_CHECK_MAP),
  905. &check_map_cmd));
  906. test_ioctl_destroy(mock_stdev_id);
  907. test_cmd_destroy_access_pages(
  908. access_cmd.id,
  909. access_cmd.access_pages.out_access_pages_id);
  910. test_ioctl_ioas_unmap(MOCK_APERTURE_START, BUFFER_SIZE);
  911. }
  912. test_cmd_destroy_access(access_cmd.id);
  913. }
  914. TEST_F(iommufd_ioas, access_pin_unmap)
  915. {
  916. struct iommu_test_cmd access_pages_cmd = {
  917. .size = sizeof(access_pages_cmd),
  918. .op = IOMMU_TEST_OP_ACCESS_PAGES,
  919. .access_pages = { .iova = MOCK_APERTURE_START,
  920. .length = BUFFER_SIZE,
  921. .uptr = (uintptr_t)buffer },
  922. };
  923. test_cmd_create_access(self->ioas_id, &access_pages_cmd.id,
  924. MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES);
  925. test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE, MOCK_APERTURE_START);
  926. ASSERT_EQ(0,
  927. ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
  928. &access_pages_cmd));
  929. /* Trigger the unmap op */
  930. test_ioctl_ioas_unmap(MOCK_APERTURE_START, BUFFER_SIZE);
  931. /* kernel removed the item for us */
  932. test_err_destroy_access_pages(
  933. ENOENT, access_pages_cmd.id,
  934. access_pages_cmd.access_pages.out_access_pages_id);
  935. }
  936. static void check_access_rw(struct __test_metadata *_metadata, int fd,
  937. unsigned int access_id, uint64_t iova,
  938. unsigned int def_flags)
  939. {
  940. uint16_t tmp[32];
  941. struct iommu_test_cmd access_cmd = {
  942. .size = sizeof(access_cmd),
  943. .op = IOMMU_TEST_OP_ACCESS_RW,
  944. .id = access_id,
  945. .access_rw = { .uptr = (uintptr_t)tmp },
  946. };
  947. uint16_t *buffer16 = buffer;
  948. unsigned int i;
  949. void *tmp2;
  950. for (i = 0; i != BUFFER_SIZE / sizeof(*buffer16); i++)
  951. buffer16[i] = rand();
  952. for (access_cmd.access_rw.iova = iova + PAGE_SIZE - 50;
  953. access_cmd.access_rw.iova < iova + PAGE_SIZE + 50;
  954. access_cmd.access_rw.iova++) {
  955. for (access_cmd.access_rw.length = 1;
  956. access_cmd.access_rw.length < sizeof(tmp);
  957. access_cmd.access_rw.length++) {
  958. access_cmd.access_rw.flags = def_flags;
  959. ASSERT_EQ(0, ioctl(fd,
  960. _IOMMU_TEST_CMD(
  961. IOMMU_TEST_OP_ACCESS_RW),
  962. &access_cmd));
  963. ASSERT_EQ(0,
  964. memcmp(buffer + (access_cmd.access_rw.iova -
  965. iova),
  966. tmp, access_cmd.access_rw.length));
  967. for (i = 0; i != ARRAY_SIZE(tmp); i++)
  968. tmp[i] = rand();
  969. access_cmd.access_rw.flags = def_flags |
  970. MOCK_ACCESS_RW_WRITE;
  971. ASSERT_EQ(0, ioctl(fd,
  972. _IOMMU_TEST_CMD(
  973. IOMMU_TEST_OP_ACCESS_RW),
  974. &access_cmd));
  975. ASSERT_EQ(0,
  976. memcmp(buffer + (access_cmd.access_rw.iova -
  977. iova),
  978. tmp, access_cmd.access_rw.length));
  979. }
  980. }
  981. /* Multi-page test */
  982. tmp2 = malloc(BUFFER_SIZE);
  983. ASSERT_NE(NULL, tmp2);
  984. access_cmd.access_rw.iova = iova;
  985. access_cmd.access_rw.length = BUFFER_SIZE;
  986. access_cmd.access_rw.flags = def_flags;
  987. access_cmd.access_rw.uptr = (uintptr_t)tmp2;
  988. ASSERT_EQ(0, ioctl(fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_RW),
  989. &access_cmd));
  990. ASSERT_EQ(0, memcmp(buffer, tmp2, access_cmd.access_rw.length));
  991. free(tmp2);
  992. }
  993. TEST_F(iommufd_ioas, access_rw)
  994. {
  995. __u32 access_id;
  996. __u64 iova;
  997. test_cmd_create_access(self->ioas_id, &access_id, 0);
  998. test_ioctl_ioas_map(buffer, BUFFER_SIZE, &iova);
  999. check_access_rw(_metadata, self->fd, access_id, iova, 0);
  1000. check_access_rw(_metadata, self->fd, access_id, iova,
  1001. MOCK_ACCESS_RW_SLOW_PATH);
  1002. test_ioctl_ioas_unmap(iova, BUFFER_SIZE);
  1003. test_cmd_destroy_access(access_id);
  1004. }
  1005. TEST_F(iommufd_ioas, access_rw_unaligned)
  1006. {
  1007. __u32 access_id;
  1008. __u64 iova;
  1009. test_cmd_create_access(self->ioas_id, &access_id, 0);
  1010. /* Unaligned pages */
  1011. iova = self->base_iova + MOCK_PAGE_SIZE;
  1012. test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE, iova);
  1013. check_access_rw(_metadata, self->fd, access_id, iova, 0);
  1014. test_ioctl_ioas_unmap(iova, BUFFER_SIZE);
  1015. test_cmd_destroy_access(access_id);
  1016. }
  1017. TEST_F(iommufd_ioas, fork_gone)
  1018. {
  1019. __u32 access_id;
  1020. pid_t child;
  1021. test_cmd_create_access(self->ioas_id, &access_id, 0);
  1022. /* Create a mapping with a different mm */
  1023. child = fork();
  1024. if (!child) {
  1025. test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE,
  1026. MOCK_APERTURE_START);
  1027. exit(0);
  1028. }
  1029. ASSERT_NE(-1, child);
  1030. ASSERT_EQ(child, waitpid(child, NULL, 0));
  1031. if (self->stdev_id) {
  1032. /*
  1033. * If a domain already existed then everything was pinned within
  1034. * the fork, so this copies from one domain to another.
  1035. */
  1036. test_cmd_mock_domain(self->ioas_id, NULL, NULL, NULL);
  1037. check_access_rw(_metadata, self->fd, access_id,
  1038. MOCK_APERTURE_START, 0);
  1039. } else {
  1040. /*
  1041. * Otherwise we need to actually pin pages which can't happen
  1042. * since the fork is gone.
  1043. */
  1044. test_err_mock_domain(EFAULT, self->ioas_id, NULL, NULL);
  1045. }
  1046. test_cmd_destroy_access(access_id);
  1047. }
  1048. TEST_F(iommufd_ioas, fork_present)
  1049. {
  1050. __u32 access_id;
  1051. int pipefds[2];
  1052. uint64_t tmp;
  1053. pid_t child;
  1054. int efd;
  1055. test_cmd_create_access(self->ioas_id, &access_id, 0);
  1056. ASSERT_EQ(0, pipe2(pipefds, O_CLOEXEC));
  1057. efd = eventfd(0, EFD_CLOEXEC);
  1058. ASSERT_NE(-1, efd);
  1059. /* Create a mapping with a different mm */
  1060. child = fork();
  1061. if (!child) {
  1062. __u64 iova;
  1063. uint64_t one = 1;
  1064. close(pipefds[1]);
  1065. test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE,
  1066. MOCK_APERTURE_START);
  1067. if (write(efd, &one, sizeof(one)) != sizeof(one))
  1068. exit(100);
  1069. if (read(pipefds[0], &iova, 1) != 1)
  1070. exit(100);
  1071. exit(0);
  1072. }
  1073. close(pipefds[0]);
  1074. ASSERT_NE(-1, child);
  1075. ASSERT_EQ(8, read(efd, &tmp, sizeof(tmp)));
  1076. /* Read pages from the remote process */
  1077. test_cmd_mock_domain(self->ioas_id, NULL, NULL, NULL);
  1078. check_access_rw(_metadata, self->fd, access_id, MOCK_APERTURE_START, 0);
  1079. ASSERT_EQ(0, close(pipefds[1]));
  1080. ASSERT_EQ(child, waitpid(child, NULL, 0));
  1081. test_cmd_destroy_access(access_id);
  1082. }
  1083. TEST_F(iommufd_ioas, ioas_option_huge_pages)
  1084. {
  1085. struct iommu_option cmd = {
  1086. .size = sizeof(cmd),
  1087. .option_id = IOMMU_OPTION_HUGE_PAGES,
  1088. .op = IOMMU_OPTION_OP_GET,
  1089. .val64 = 3,
  1090. .object_id = self->ioas_id,
  1091. };
  1092. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1093. ASSERT_EQ(1, cmd.val64);
  1094. cmd.op = IOMMU_OPTION_OP_SET;
  1095. cmd.val64 = 0;
  1096. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1097. cmd.op = IOMMU_OPTION_OP_GET;
  1098. cmd.val64 = 3;
  1099. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1100. ASSERT_EQ(0, cmd.val64);
  1101. cmd.op = IOMMU_OPTION_OP_SET;
  1102. cmd.val64 = 2;
  1103. EXPECT_ERRNO(EINVAL, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1104. cmd.op = IOMMU_OPTION_OP_SET;
  1105. cmd.val64 = 1;
  1106. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1107. }
  1108. TEST_F(iommufd_ioas, ioas_iova_alloc)
  1109. {
  1110. unsigned int length;
  1111. __u64 iova;
  1112. for (length = 1; length != PAGE_SIZE * 2; length++) {
  1113. if (variant->mock_domains && (length % MOCK_PAGE_SIZE)) {
  1114. test_err_ioctl_ioas_map(EINVAL, buffer, length, &iova);
  1115. } else {
  1116. test_ioctl_ioas_map(buffer, length, &iova);
  1117. test_ioctl_ioas_unmap(iova, length);
  1118. }
  1119. }
  1120. }
  1121. TEST_F(iommufd_ioas, ioas_align_change)
  1122. {
  1123. struct iommu_option cmd = {
  1124. .size = sizeof(cmd),
  1125. .option_id = IOMMU_OPTION_HUGE_PAGES,
  1126. .op = IOMMU_OPTION_OP_SET,
  1127. .object_id = self->ioas_id,
  1128. /* 0 means everything must be aligned to PAGE_SIZE */
  1129. .val64 = 0,
  1130. };
  1131. /*
  1132. * We cannot upgrade the alignment using OPTION_HUGE_PAGES when a domain
  1133. * and map are present.
  1134. */
  1135. if (variant->mock_domains)
  1136. return;
  1137. /*
  1138. * We can upgrade to PAGE_SIZE alignment when things are aligned right
  1139. */
  1140. test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE, MOCK_APERTURE_START);
  1141. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1142. /* Misalignment is rejected at map time */
  1143. test_err_ioctl_ioas_map_fixed(EINVAL, buffer + MOCK_PAGE_SIZE,
  1144. PAGE_SIZE,
  1145. MOCK_APERTURE_START + PAGE_SIZE);
  1146. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1147. /* Reduce alignment */
  1148. cmd.val64 = 1;
  1149. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1150. /* Confirm misalignment is rejected during alignment upgrade */
  1151. test_ioctl_ioas_map_fixed(buffer + MOCK_PAGE_SIZE, PAGE_SIZE,
  1152. MOCK_APERTURE_START + PAGE_SIZE);
  1153. cmd.val64 = 0;
  1154. EXPECT_ERRNO(EADDRINUSE, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1155. test_ioctl_ioas_unmap(MOCK_APERTURE_START + PAGE_SIZE, PAGE_SIZE);
  1156. test_ioctl_ioas_unmap(MOCK_APERTURE_START, PAGE_SIZE);
  1157. }
  1158. TEST_F(iommufd_ioas, copy_sweep)
  1159. {
  1160. struct iommu_ioas_copy copy_cmd = {
  1161. .size = sizeof(copy_cmd),
  1162. .flags = IOMMU_IOAS_MAP_FIXED_IOVA | IOMMU_IOAS_MAP_WRITEABLE,
  1163. .src_ioas_id = self->ioas_id,
  1164. .dst_iova = MOCK_APERTURE_START,
  1165. .length = MOCK_PAGE_SIZE,
  1166. };
  1167. unsigned int dst_ioas_id;
  1168. uint64_t last_iova;
  1169. uint64_t iova;
  1170. test_ioctl_ioas_alloc(&dst_ioas_id);
  1171. copy_cmd.dst_ioas_id = dst_ioas_id;
  1172. if (variant->mock_domains)
  1173. last_iova = MOCK_APERTURE_START + BUFFER_SIZE - 1;
  1174. else
  1175. last_iova = MOCK_APERTURE_START + BUFFER_SIZE - 2;
  1176. test_ioctl_ioas_map_fixed(buffer, last_iova - MOCK_APERTURE_START + 1,
  1177. MOCK_APERTURE_START);
  1178. for (iova = MOCK_APERTURE_START - PAGE_SIZE; iova <= last_iova;
  1179. iova += 511) {
  1180. copy_cmd.src_iova = iova;
  1181. if (iova < MOCK_APERTURE_START ||
  1182. iova + copy_cmd.length - 1 > last_iova) {
  1183. EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_IOAS_COPY,
  1184. &copy_cmd));
  1185. } else {
  1186. ASSERT_EQ(0,
  1187. ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
  1188. test_ioctl_ioas_unmap_id(dst_ioas_id, copy_cmd.dst_iova,
  1189. copy_cmd.length);
  1190. }
  1191. }
  1192. test_ioctl_destroy(dst_ioas_id);
  1193. }
  1194. FIXTURE(iommufd_mock_domain)
  1195. {
  1196. int fd;
  1197. uint32_t ioas_id;
  1198. uint32_t hwpt_id;
  1199. uint32_t hwpt_ids[2];
  1200. uint32_t stdev_ids[2];
  1201. uint32_t idev_ids[2];
  1202. int mmap_flags;
  1203. size_t mmap_buf_size;
  1204. };
  1205. FIXTURE_VARIANT(iommufd_mock_domain)
  1206. {
  1207. unsigned int mock_domains;
  1208. bool hugepages;
  1209. };
  1210. FIXTURE_SETUP(iommufd_mock_domain)
  1211. {
  1212. unsigned int i;
  1213. self->fd = open("/dev/iommu", O_RDWR);
  1214. ASSERT_NE(-1, self->fd);
  1215. test_ioctl_ioas_alloc(&self->ioas_id);
  1216. ASSERT_GE(ARRAY_SIZE(self->hwpt_ids), variant->mock_domains);
  1217. for (i = 0; i != variant->mock_domains; i++)
  1218. test_cmd_mock_domain(self->ioas_id, &self->stdev_ids[i],
  1219. &self->hwpt_ids[i], &self->idev_ids[i]);
  1220. self->hwpt_id = self->hwpt_ids[0];
  1221. self->mmap_flags = MAP_SHARED | MAP_ANONYMOUS;
  1222. self->mmap_buf_size = PAGE_SIZE * 8;
  1223. if (variant->hugepages) {
  1224. /*
  1225. * MAP_POPULATE will cause the kernel to fail mmap if THPs are
  1226. * not available.
  1227. */
  1228. self->mmap_flags |= MAP_HUGETLB | MAP_POPULATE;
  1229. self->mmap_buf_size = HUGEPAGE_SIZE * 2;
  1230. }
  1231. }
  1232. FIXTURE_TEARDOWN(iommufd_mock_domain)
  1233. {
  1234. teardown_iommufd(self->fd, _metadata);
  1235. }
  1236. FIXTURE_VARIANT_ADD(iommufd_mock_domain, one_domain)
  1237. {
  1238. .mock_domains = 1,
  1239. .hugepages = false,
  1240. };
  1241. FIXTURE_VARIANT_ADD(iommufd_mock_domain, two_domains)
  1242. {
  1243. .mock_domains = 2,
  1244. .hugepages = false,
  1245. };
  1246. FIXTURE_VARIANT_ADD(iommufd_mock_domain, one_domain_hugepage)
  1247. {
  1248. .mock_domains = 1,
  1249. .hugepages = true,
  1250. };
  1251. FIXTURE_VARIANT_ADD(iommufd_mock_domain, two_domains_hugepage)
  1252. {
  1253. .mock_domains = 2,
  1254. .hugepages = true,
  1255. };
  1256. /* Have the kernel check that the user pages made it to the iommu_domain */
  1257. #define check_mock_iova(_ptr, _iova, _length) \
  1258. ({ \
  1259. struct iommu_test_cmd check_map_cmd = { \
  1260. .size = sizeof(check_map_cmd), \
  1261. .op = IOMMU_TEST_OP_MD_CHECK_MAP, \
  1262. .id = self->hwpt_id, \
  1263. .check_map = { .iova = _iova, \
  1264. .length = _length, \
  1265. .uptr = (uintptr_t)(_ptr) }, \
  1266. }; \
  1267. ASSERT_EQ(0, \
  1268. ioctl(self->fd, \
  1269. _IOMMU_TEST_CMD(IOMMU_TEST_OP_MD_CHECK_MAP), \
  1270. &check_map_cmd)); \
  1271. if (self->hwpt_ids[1]) { \
  1272. check_map_cmd.id = self->hwpt_ids[1]; \
  1273. ASSERT_EQ(0, \
  1274. ioctl(self->fd, \
  1275. _IOMMU_TEST_CMD( \
  1276. IOMMU_TEST_OP_MD_CHECK_MAP), \
  1277. &check_map_cmd)); \
  1278. } \
  1279. })
  1280. TEST_F(iommufd_mock_domain, basic)
  1281. {
  1282. size_t buf_size = self->mmap_buf_size;
  1283. uint8_t *buf;
  1284. __u64 iova;
  1285. /* Simple one page map */
  1286. test_ioctl_ioas_map(buffer, PAGE_SIZE, &iova);
  1287. check_mock_iova(buffer, iova, PAGE_SIZE);
  1288. buf = mmap(0, buf_size, PROT_READ | PROT_WRITE, self->mmap_flags, -1,
  1289. 0);
  1290. ASSERT_NE(MAP_FAILED, buf);
  1291. /* EFAULT half way through mapping */
  1292. ASSERT_EQ(0, munmap(buf + buf_size / 2, buf_size / 2));
  1293. test_err_ioctl_ioas_map(EFAULT, buf, buf_size, &iova);
  1294. /* EFAULT on first page */
  1295. ASSERT_EQ(0, munmap(buf, buf_size / 2));
  1296. test_err_ioctl_ioas_map(EFAULT, buf, buf_size, &iova);
  1297. }
  1298. TEST_F(iommufd_mock_domain, ro_unshare)
  1299. {
  1300. uint8_t *buf;
  1301. __u64 iova;
  1302. int fd;
  1303. fd = open("/proc/self/exe", O_RDONLY);
  1304. ASSERT_NE(-1, fd);
  1305. buf = mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
  1306. ASSERT_NE(MAP_FAILED, buf);
  1307. close(fd);
  1308. /*
  1309. * There have been lots of changes to the "unshare" mechanism in
  1310. * get_user_pages(), make sure it works right. The write to the page
  1311. * after we map it for reading should not change the assigned PFN.
  1312. */
  1313. ASSERT_EQ(0,
  1314. _test_ioctl_ioas_map(self->fd, self->ioas_id, buf, PAGE_SIZE,
  1315. &iova, IOMMU_IOAS_MAP_READABLE));
  1316. check_mock_iova(buf, iova, PAGE_SIZE);
  1317. memset(buf, 1, PAGE_SIZE);
  1318. check_mock_iova(buf, iova, PAGE_SIZE);
  1319. ASSERT_EQ(0, munmap(buf, PAGE_SIZE));
  1320. }
  1321. TEST_F(iommufd_mock_domain, all_aligns)
  1322. {
  1323. size_t test_step = variant->hugepages ? (self->mmap_buf_size / 16) :
  1324. MOCK_PAGE_SIZE;
  1325. size_t buf_size = self->mmap_buf_size;
  1326. unsigned int start;
  1327. unsigned int end;
  1328. uint8_t *buf;
  1329. buf = mmap(0, buf_size, PROT_READ | PROT_WRITE, self->mmap_flags, -1,
  1330. 0);
  1331. ASSERT_NE(MAP_FAILED, buf);
  1332. check_refs(buf, buf_size, 0);
  1333. /*
  1334. * Map every combination of page size and alignment within a big region,
  1335. * less for hugepage case as it takes so long to finish.
  1336. */
  1337. for (start = 0; start < buf_size; start += test_step) {
  1338. if (variant->hugepages)
  1339. end = buf_size;
  1340. else
  1341. end = start + MOCK_PAGE_SIZE;
  1342. for (; end < buf_size; end += MOCK_PAGE_SIZE) {
  1343. size_t length = end - start;
  1344. __u64 iova;
  1345. test_ioctl_ioas_map(buf + start, length, &iova);
  1346. check_mock_iova(buf + start, iova, length);
  1347. check_refs(buf + start / PAGE_SIZE * PAGE_SIZE,
  1348. end / PAGE_SIZE * PAGE_SIZE -
  1349. start / PAGE_SIZE * PAGE_SIZE,
  1350. 1);
  1351. test_ioctl_ioas_unmap(iova, length);
  1352. }
  1353. }
  1354. check_refs(buf, buf_size, 0);
  1355. ASSERT_EQ(0, munmap(buf, buf_size));
  1356. }
  1357. TEST_F(iommufd_mock_domain, all_aligns_copy)
  1358. {
  1359. size_t test_step = variant->hugepages ? self->mmap_buf_size / 16 :
  1360. MOCK_PAGE_SIZE;
  1361. size_t buf_size = self->mmap_buf_size;
  1362. unsigned int start;
  1363. unsigned int end;
  1364. uint8_t *buf;
  1365. buf = mmap(0, buf_size, PROT_READ | PROT_WRITE, self->mmap_flags, -1,
  1366. 0);
  1367. ASSERT_NE(MAP_FAILED, buf);
  1368. check_refs(buf, buf_size, 0);
  1369. /*
  1370. * Map every combination of page size and alignment within a big region,
  1371. * less for hugepage case as it takes so long to finish.
  1372. */
  1373. for (start = 0; start < buf_size; start += test_step) {
  1374. if (variant->hugepages)
  1375. end = buf_size;
  1376. else
  1377. end = start + MOCK_PAGE_SIZE;
  1378. for (; end < buf_size; end += MOCK_PAGE_SIZE) {
  1379. size_t length = end - start;
  1380. unsigned int old_id;
  1381. uint32_t mock_stdev_id;
  1382. __u64 iova;
  1383. test_ioctl_ioas_map(buf + start, length, &iova);
  1384. /* Add and destroy a domain while the area exists */
  1385. old_id = self->hwpt_ids[1];
  1386. test_cmd_mock_domain(self->ioas_id, &mock_stdev_id,
  1387. &self->hwpt_ids[1], NULL);
  1388. check_mock_iova(buf + start, iova, length);
  1389. check_refs(buf + start / PAGE_SIZE * PAGE_SIZE,
  1390. end / PAGE_SIZE * PAGE_SIZE -
  1391. start / PAGE_SIZE * PAGE_SIZE,
  1392. 1);
  1393. test_ioctl_destroy(mock_stdev_id);
  1394. self->hwpt_ids[1] = old_id;
  1395. test_ioctl_ioas_unmap(iova, length);
  1396. }
  1397. }
  1398. check_refs(buf, buf_size, 0);
  1399. ASSERT_EQ(0, munmap(buf, buf_size));
  1400. }
  1401. TEST_F(iommufd_mock_domain, user_copy)
  1402. {
  1403. struct iommu_test_cmd access_cmd = {
  1404. .size = sizeof(access_cmd),
  1405. .op = IOMMU_TEST_OP_ACCESS_PAGES,
  1406. .access_pages = { .length = BUFFER_SIZE,
  1407. .uptr = (uintptr_t)buffer },
  1408. };
  1409. struct iommu_ioas_copy copy_cmd = {
  1410. .size = sizeof(copy_cmd),
  1411. .flags = IOMMU_IOAS_MAP_FIXED_IOVA | IOMMU_IOAS_MAP_WRITEABLE,
  1412. .dst_ioas_id = self->ioas_id,
  1413. .dst_iova = MOCK_APERTURE_START,
  1414. .length = BUFFER_SIZE,
  1415. };
  1416. struct iommu_ioas_unmap unmap_cmd = {
  1417. .size = sizeof(unmap_cmd),
  1418. .ioas_id = self->ioas_id,
  1419. .iova = MOCK_APERTURE_START,
  1420. .length = BUFFER_SIZE,
  1421. };
  1422. unsigned int new_ioas_id, ioas_id;
  1423. /* Pin the pages in an IOAS with no domains then copy to an IOAS with domains */
  1424. test_ioctl_ioas_alloc(&ioas_id);
  1425. test_ioctl_ioas_map_id(ioas_id, buffer, BUFFER_SIZE,
  1426. &copy_cmd.src_iova);
  1427. test_cmd_create_access(ioas_id, &access_cmd.id,
  1428. MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES);
  1429. access_cmd.access_pages.iova = copy_cmd.src_iova;
  1430. ASSERT_EQ(0,
  1431. ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
  1432. &access_cmd));
  1433. copy_cmd.src_ioas_id = ioas_id;
  1434. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
  1435. check_mock_iova(buffer, MOCK_APERTURE_START, BUFFER_SIZE);
  1436. /* Now replace the ioas with a new one */
  1437. test_ioctl_ioas_alloc(&new_ioas_id);
  1438. test_ioctl_ioas_map_id(new_ioas_id, buffer, BUFFER_SIZE,
  1439. &copy_cmd.src_iova);
  1440. test_cmd_access_replace_ioas(access_cmd.id, new_ioas_id);
  1441. /* Destroy the old ioas and cleanup copied mapping */
  1442. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_UNMAP, &unmap_cmd));
  1443. test_ioctl_destroy(ioas_id);
  1444. /* Then run the same test again with the new ioas */
  1445. access_cmd.access_pages.iova = copy_cmd.src_iova;
  1446. ASSERT_EQ(0,
  1447. ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
  1448. &access_cmd));
  1449. copy_cmd.src_ioas_id = new_ioas_id;
  1450. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
  1451. check_mock_iova(buffer, MOCK_APERTURE_START, BUFFER_SIZE);
  1452. test_cmd_destroy_access_pages(
  1453. access_cmd.id, access_cmd.access_pages.out_access_pages_id);
  1454. test_cmd_destroy_access(access_cmd.id);
  1455. test_ioctl_destroy(new_ioas_id);
  1456. }
  1457. TEST_F(iommufd_mock_domain, replace)
  1458. {
  1459. uint32_t ioas_id;
  1460. test_ioctl_ioas_alloc(&ioas_id);
  1461. test_cmd_mock_domain_replace(self->stdev_ids[0], ioas_id);
  1462. /*
  1463. * Replacing the IOAS causes the prior HWPT to be deallocated, thus we
  1464. * should get enoent when we try to use it.
  1465. */
  1466. if (variant->mock_domains == 1)
  1467. test_err_mock_domain_replace(ENOENT, self->stdev_ids[0],
  1468. self->hwpt_ids[0]);
  1469. test_cmd_mock_domain_replace(self->stdev_ids[0], ioas_id);
  1470. if (variant->mock_domains >= 2) {
  1471. test_cmd_mock_domain_replace(self->stdev_ids[0],
  1472. self->hwpt_ids[1]);
  1473. test_cmd_mock_domain_replace(self->stdev_ids[0],
  1474. self->hwpt_ids[1]);
  1475. test_cmd_mock_domain_replace(self->stdev_ids[0],
  1476. self->hwpt_ids[0]);
  1477. }
  1478. test_cmd_mock_domain_replace(self->stdev_ids[0], self->ioas_id);
  1479. test_ioctl_destroy(ioas_id);
  1480. }
  1481. TEST_F(iommufd_mock_domain, alloc_hwpt)
  1482. {
  1483. int i;
  1484. for (i = 0; i != variant->mock_domains; i++) {
  1485. uint32_t hwpt_id[2];
  1486. uint32_t stddev_id;
  1487. test_err_hwpt_alloc(EOPNOTSUPP,
  1488. self->idev_ids[i], self->ioas_id,
  1489. ~IOMMU_HWPT_ALLOC_NEST_PARENT, &hwpt_id[0]);
  1490. test_cmd_hwpt_alloc(self->idev_ids[i], self->ioas_id,
  1491. 0, &hwpt_id[0]);
  1492. test_cmd_hwpt_alloc(self->idev_ids[i], self->ioas_id,
  1493. IOMMU_HWPT_ALLOC_NEST_PARENT, &hwpt_id[1]);
  1494. /* Do a hw_pagetable rotation test */
  1495. test_cmd_mock_domain_replace(self->stdev_ids[i], hwpt_id[0]);
  1496. EXPECT_ERRNO(EBUSY, _test_ioctl_destroy(self->fd, hwpt_id[0]));
  1497. test_cmd_mock_domain_replace(self->stdev_ids[i], hwpt_id[1]);
  1498. EXPECT_ERRNO(EBUSY, _test_ioctl_destroy(self->fd, hwpt_id[1]));
  1499. test_cmd_mock_domain_replace(self->stdev_ids[i], self->ioas_id);
  1500. test_ioctl_destroy(hwpt_id[1]);
  1501. test_cmd_mock_domain(hwpt_id[0], &stddev_id, NULL, NULL);
  1502. test_ioctl_destroy(stddev_id);
  1503. test_ioctl_destroy(hwpt_id[0]);
  1504. }
  1505. }
  1506. FIXTURE(iommufd_dirty_tracking)
  1507. {
  1508. int fd;
  1509. uint32_t ioas_id;
  1510. uint32_t hwpt_id;
  1511. uint32_t stdev_id;
  1512. uint32_t idev_id;
  1513. unsigned long page_size;
  1514. unsigned long bitmap_size;
  1515. void *bitmap;
  1516. void *buffer;
  1517. };
  1518. FIXTURE_VARIANT(iommufd_dirty_tracking)
  1519. {
  1520. unsigned long buffer_size;
  1521. bool hugepages;
  1522. };
  1523. FIXTURE_SETUP(iommufd_dirty_tracking)
  1524. {
  1525. size_t mmap_buffer_size;
  1526. unsigned long size;
  1527. int mmap_flags;
  1528. void *vrc;
  1529. int rc;
  1530. if (variant->buffer_size < MOCK_PAGE_SIZE) {
  1531. SKIP(return,
  1532. "Skipping buffer_size=%lu, less than MOCK_PAGE_SIZE=%lu",
  1533. variant->buffer_size, MOCK_PAGE_SIZE);
  1534. }
  1535. self->fd = open("/dev/iommu", O_RDWR);
  1536. ASSERT_NE(-1, self->fd);
  1537. mmap_flags = MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED;
  1538. mmap_buffer_size = variant->buffer_size;
  1539. if (variant->hugepages) {
  1540. /*
  1541. * MAP_POPULATE will cause the kernel to fail mmap if THPs are
  1542. * not available.
  1543. */
  1544. mmap_flags |= MAP_HUGETLB | MAP_POPULATE;
  1545. /*
  1546. * Allocation must be aligned to the HUGEPAGE_SIZE, because the
  1547. * following mmap() will automatically align the length to be a
  1548. * multiple of the underlying huge page size. Failing to do the
  1549. * same at this allocation will result in a memory overwrite by
  1550. * the mmap().
  1551. */
  1552. if (mmap_buffer_size < HUGEPAGE_SIZE)
  1553. mmap_buffer_size = HUGEPAGE_SIZE;
  1554. }
  1555. rc = posix_memalign(&self->buffer, HUGEPAGE_SIZE, mmap_buffer_size);
  1556. if (rc || !self->buffer) {
  1557. SKIP(return, "Skipping buffer_size=%lu due to errno=%d",
  1558. mmap_buffer_size, rc);
  1559. }
  1560. assert((uintptr_t)self->buffer % HUGEPAGE_SIZE == 0);
  1561. vrc = mmap(self->buffer, mmap_buffer_size, PROT_READ | PROT_WRITE,
  1562. mmap_flags, -1, 0);
  1563. assert(vrc == self->buffer);
  1564. self->page_size = MOCK_PAGE_SIZE;
  1565. self->bitmap_size = variant->buffer_size / self->page_size;
  1566. /* Provision with an extra (PAGE_SIZE) for the unaligned case */
  1567. size = DIV_ROUND_UP(self->bitmap_size, BITS_PER_BYTE);
  1568. rc = posix_memalign(&self->bitmap, PAGE_SIZE, size + PAGE_SIZE);
  1569. assert(!rc);
  1570. assert(self->bitmap);
  1571. assert((uintptr_t)self->bitmap % PAGE_SIZE == 0);
  1572. test_ioctl_ioas_alloc(&self->ioas_id);
  1573. /* Enable 1M mock IOMMU hugepages */
  1574. if (variant->hugepages) {
  1575. test_cmd_mock_domain_flags(self->ioas_id,
  1576. MOCK_FLAGS_DEVICE_HUGE_IOVA,
  1577. &self->stdev_id, &self->hwpt_id,
  1578. &self->idev_id);
  1579. } else {
  1580. test_cmd_mock_domain(self->ioas_id, &self->stdev_id,
  1581. &self->hwpt_id, &self->idev_id);
  1582. }
  1583. }
  1584. FIXTURE_TEARDOWN(iommufd_dirty_tracking)
  1585. {
  1586. free(self->buffer);
  1587. free(self->bitmap);
  1588. teardown_iommufd(self->fd, _metadata);
  1589. }
  1590. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty8k)
  1591. {
  1592. /* half of an u8 index bitmap */
  1593. .buffer_size = 8UL * 1024UL,
  1594. };
  1595. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty16k)
  1596. {
  1597. /* one u8 index bitmap */
  1598. .buffer_size = 16UL * 1024UL,
  1599. };
  1600. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty64k)
  1601. {
  1602. /* one u32 index bitmap */
  1603. .buffer_size = 64UL * 1024UL,
  1604. };
  1605. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty128k)
  1606. {
  1607. /* one u64 index bitmap */
  1608. .buffer_size = 128UL * 1024UL,
  1609. };
  1610. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty320k)
  1611. {
  1612. /* two u64 index and trailing end bitmap */
  1613. .buffer_size = 320UL * 1024UL,
  1614. };
  1615. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty64M)
  1616. {
  1617. /* 4K bitmap (64M IOVA range) */
  1618. .buffer_size = 64UL * 1024UL * 1024UL,
  1619. };
  1620. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty64M_huge)
  1621. {
  1622. /* 4K bitmap (64M IOVA range) */
  1623. .buffer_size = 64UL * 1024UL * 1024UL,
  1624. .hugepages = true,
  1625. };
  1626. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty128M)
  1627. {
  1628. /* 8K bitmap (128M IOVA range) */
  1629. .buffer_size = 128UL * 1024UL * 1024UL,
  1630. };
  1631. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty128M_huge)
  1632. {
  1633. /* 8K bitmap (128M IOVA range) */
  1634. .buffer_size = 128UL * 1024UL * 1024UL,
  1635. .hugepages = true,
  1636. };
  1637. TEST_F(iommufd_dirty_tracking, enforce_dirty)
  1638. {
  1639. uint32_t ioas_id, stddev_id, idev_id;
  1640. uint32_t hwpt_id, _hwpt_id;
  1641. uint32_t dev_flags;
  1642. /* Regular case */
  1643. dev_flags = MOCK_FLAGS_DEVICE_NO_DIRTY;
  1644. test_cmd_hwpt_alloc(self->idev_id, self->ioas_id,
  1645. IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
  1646. test_cmd_mock_domain(hwpt_id, &stddev_id, NULL, NULL);
  1647. test_err_mock_domain_flags(EINVAL, hwpt_id, dev_flags, &stddev_id,
  1648. NULL);
  1649. test_ioctl_destroy(stddev_id);
  1650. test_ioctl_destroy(hwpt_id);
  1651. /* IOMMU device does not support dirty tracking */
  1652. test_ioctl_ioas_alloc(&ioas_id);
  1653. test_cmd_mock_domain_flags(ioas_id, dev_flags, &stddev_id, &_hwpt_id,
  1654. &idev_id);
  1655. test_err_hwpt_alloc(EOPNOTSUPP, idev_id, ioas_id,
  1656. IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
  1657. test_ioctl_destroy(stddev_id);
  1658. }
  1659. TEST_F(iommufd_dirty_tracking, set_dirty_tracking)
  1660. {
  1661. uint32_t stddev_id;
  1662. uint32_t hwpt_id;
  1663. test_cmd_hwpt_alloc(self->idev_id, self->ioas_id,
  1664. IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
  1665. test_cmd_mock_domain(hwpt_id, &stddev_id, NULL, NULL);
  1666. test_cmd_set_dirty_tracking(hwpt_id, true);
  1667. test_cmd_set_dirty_tracking(hwpt_id, false);
  1668. test_ioctl_destroy(stddev_id);
  1669. test_ioctl_destroy(hwpt_id);
  1670. }
  1671. TEST_F(iommufd_dirty_tracking, device_dirty_capability)
  1672. {
  1673. uint32_t caps = 0;
  1674. uint32_t stddev_id;
  1675. uint32_t hwpt_id;
  1676. test_cmd_hwpt_alloc(self->idev_id, self->ioas_id, 0, &hwpt_id);
  1677. test_cmd_mock_domain(hwpt_id, &stddev_id, NULL, NULL);
  1678. test_cmd_get_hw_capabilities(self->idev_id, caps,
  1679. IOMMU_HW_CAP_DIRTY_TRACKING);
  1680. ASSERT_EQ(IOMMU_HW_CAP_DIRTY_TRACKING,
  1681. caps & IOMMU_HW_CAP_DIRTY_TRACKING);
  1682. test_ioctl_destroy(stddev_id);
  1683. test_ioctl_destroy(hwpt_id);
  1684. }
  1685. TEST_F(iommufd_dirty_tracking, get_dirty_bitmap)
  1686. {
  1687. uint32_t page_size = MOCK_PAGE_SIZE;
  1688. uint32_t hwpt_id;
  1689. uint32_t ioas_id;
  1690. if (variant->hugepages)
  1691. page_size = MOCK_HUGE_PAGE_SIZE;
  1692. test_ioctl_ioas_alloc(&ioas_id);
  1693. test_ioctl_ioas_map_fixed_id(ioas_id, self->buffer,
  1694. variant->buffer_size, MOCK_APERTURE_START);
  1695. test_cmd_hwpt_alloc(self->idev_id, ioas_id,
  1696. IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
  1697. test_cmd_set_dirty_tracking(hwpt_id, true);
  1698. test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
  1699. MOCK_APERTURE_START, self->page_size, page_size,
  1700. self->bitmap, self->bitmap_size, 0, _metadata);
  1701. /* PAGE_SIZE unaligned bitmap */
  1702. test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
  1703. MOCK_APERTURE_START, self->page_size, page_size,
  1704. self->bitmap + MOCK_PAGE_SIZE,
  1705. self->bitmap_size, 0, _metadata);
  1706. /* u64 unaligned bitmap */
  1707. test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
  1708. MOCK_APERTURE_START, self->page_size, page_size,
  1709. self->bitmap + 0xff1, self->bitmap_size, 0,
  1710. _metadata);
  1711. test_ioctl_destroy(hwpt_id);
  1712. }
  1713. TEST_F(iommufd_dirty_tracking, get_dirty_bitmap_no_clear)
  1714. {
  1715. uint32_t page_size = MOCK_PAGE_SIZE;
  1716. uint32_t hwpt_id;
  1717. uint32_t ioas_id;
  1718. if (variant->hugepages)
  1719. page_size = MOCK_HUGE_PAGE_SIZE;
  1720. test_ioctl_ioas_alloc(&ioas_id);
  1721. test_ioctl_ioas_map_fixed_id(ioas_id, self->buffer,
  1722. variant->buffer_size, MOCK_APERTURE_START);
  1723. test_cmd_hwpt_alloc(self->idev_id, ioas_id,
  1724. IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
  1725. test_cmd_set_dirty_tracking(hwpt_id, true);
  1726. test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
  1727. MOCK_APERTURE_START, self->page_size, page_size,
  1728. self->bitmap, self->bitmap_size,
  1729. IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
  1730. _metadata);
  1731. /* Unaligned bitmap */
  1732. test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
  1733. MOCK_APERTURE_START, self->page_size, page_size,
  1734. self->bitmap + MOCK_PAGE_SIZE,
  1735. self->bitmap_size,
  1736. IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
  1737. _metadata);
  1738. /* u64 unaligned bitmap */
  1739. test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
  1740. MOCK_APERTURE_START, self->page_size, page_size,
  1741. self->bitmap + 0xff1, self->bitmap_size,
  1742. IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
  1743. _metadata);
  1744. test_ioctl_destroy(hwpt_id);
  1745. }
  1746. /* VFIO compatibility IOCTLs */
  1747. TEST_F(iommufd, simple_ioctls)
  1748. {
  1749. ASSERT_EQ(VFIO_API_VERSION, ioctl(self->fd, VFIO_GET_API_VERSION));
  1750. ASSERT_EQ(1, ioctl(self->fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU));
  1751. }
  1752. TEST_F(iommufd, unmap_cmd)
  1753. {
  1754. struct vfio_iommu_type1_dma_unmap unmap_cmd = {
  1755. .iova = MOCK_APERTURE_START,
  1756. .size = PAGE_SIZE,
  1757. };
  1758. unmap_cmd.argsz = 1;
  1759. EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
  1760. unmap_cmd.argsz = sizeof(unmap_cmd);
  1761. unmap_cmd.flags = 1 << 31;
  1762. EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
  1763. unmap_cmd.flags = 0;
  1764. EXPECT_ERRNO(ENODEV, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
  1765. }
  1766. TEST_F(iommufd, map_cmd)
  1767. {
  1768. struct vfio_iommu_type1_dma_map map_cmd = {
  1769. .iova = MOCK_APERTURE_START,
  1770. .size = PAGE_SIZE,
  1771. .vaddr = (__u64)buffer,
  1772. };
  1773. map_cmd.argsz = 1;
  1774. EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
  1775. map_cmd.argsz = sizeof(map_cmd);
  1776. map_cmd.flags = 1 << 31;
  1777. EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
  1778. /* Requires a domain to be attached */
  1779. map_cmd.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE;
  1780. EXPECT_ERRNO(ENODEV, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
  1781. }
  1782. TEST_F(iommufd, info_cmd)
  1783. {
  1784. struct vfio_iommu_type1_info info_cmd = {};
  1785. /* Invalid argsz */
  1786. info_cmd.argsz = 1;
  1787. EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_GET_INFO, &info_cmd));
  1788. info_cmd.argsz = sizeof(info_cmd);
  1789. EXPECT_ERRNO(ENODEV, ioctl(self->fd, VFIO_IOMMU_GET_INFO, &info_cmd));
  1790. }
  1791. TEST_F(iommufd, set_iommu_cmd)
  1792. {
  1793. /* Requires a domain to be attached */
  1794. EXPECT_ERRNO(ENODEV,
  1795. ioctl(self->fd, VFIO_SET_IOMMU, VFIO_TYPE1v2_IOMMU));
  1796. EXPECT_ERRNO(ENODEV, ioctl(self->fd, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU));
  1797. }
  1798. TEST_F(iommufd, vfio_ioas)
  1799. {
  1800. struct iommu_vfio_ioas vfio_ioas_cmd = {
  1801. .size = sizeof(vfio_ioas_cmd),
  1802. .op = IOMMU_VFIO_IOAS_GET,
  1803. };
  1804. __u32 ioas_id;
  1805. /* ENODEV if there is no compat ioas */
  1806. EXPECT_ERRNO(ENODEV, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
  1807. /* Invalid id for set */
  1808. vfio_ioas_cmd.op = IOMMU_VFIO_IOAS_SET;
  1809. EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
  1810. /* Valid id for set*/
  1811. test_ioctl_ioas_alloc(&ioas_id);
  1812. vfio_ioas_cmd.ioas_id = ioas_id;
  1813. ASSERT_EQ(0, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
  1814. /* Same id comes back from get */
  1815. vfio_ioas_cmd.op = IOMMU_VFIO_IOAS_GET;
  1816. ASSERT_EQ(0, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
  1817. ASSERT_EQ(ioas_id, vfio_ioas_cmd.ioas_id);
  1818. /* Clear works */
  1819. vfio_ioas_cmd.op = IOMMU_VFIO_IOAS_CLEAR;
  1820. ASSERT_EQ(0, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
  1821. vfio_ioas_cmd.op = IOMMU_VFIO_IOAS_GET;
  1822. EXPECT_ERRNO(ENODEV, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
  1823. }
  1824. FIXTURE(vfio_compat_mock_domain)
  1825. {
  1826. int fd;
  1827. uint32_t ioas_id;
  1828. };
  1829. FIXTURE_VARIANT(vfio_compat_mock_domain)
  1830. {
  1831. unsigned int version;
  1832. };
  1833. FIXTURE_SETUP(vfio_compat_mock_domain)
  1834. {
  1835. struct iommu_vfio_ioas vfio_ioas_cmd = {
  1836. .size = sizeof(vfio_ioas_cmd),
  1837. .op = IOMMU_VFIO_IOAS_SET,
  1838. };
  1839. self->fd = open("/dev/iommu", O_RDWR);
  1840. ASSERT_NE(-1, self->fd);
  1841. /* Create what VFIO would consider a group */
  1842. test_ioctl_ioas_alloc(&self->ioas_id);
  1843. test_cmd_mock_domain(self->ioas_id, NULL, NULL, NULL);
  1844. /* Attach it to the vfio compat */
  1845. vfio_ioas_cmd.ioas_id = self->ioas_id;
  1846. ASSERT_EQ(0, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
  1847. ASSERT_EQ(0, ioctl(self->fd, VFIO_SET_IOMMU, variant->version));
  1848. }
  1849. FIXTURE_TEARDOWN(vfio_compat_mock_domain)
  1850. {
  1851. teardown_iommufd(self->fd, _metadata);
  1852. }
  1853. FIXTURE_VARIANT_ADD(vfio_compat_mock_domain, Ver1v2)
  1854. {
  1855. .version = VFIO_TYPE1v2_IOMMU,
  1856. };
  1857. FIXTURE_VARIANT_ADD(vfio_compat_mock_domain, Ver1v0)
  1858. {
  1859. .version = VFIO_TYPE1_IOMMU,
  1860. };
  1861. TEST_F(vfio_compat_mock_domain, simple_close)
  1862. {
  1863. }
  1864. TEST_F(vfio_compat_mock_domain, option_huge_pages)
  1865. {
  1866. struct iommu_option cmd = {
  1867. .size = sizeof(cmd),
  1868. .option_id = IOMMU_OPTION_HUGE_PAGES,
  1869. .op = IOMMU_OPTION_OP_GET,
  1870. .val64 = 3,
  1871. .object_id = self->ioas_id,
  1872. };
  1873. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1874. if (variant->version == VFIO_TYPE1_IOMMU) {
  1875. ASSERT_EQ(0, cmd.val64);
  1876. } else {
  1877. ASSERT_EQ(1, cmd.val64);
  1878. }
  1879. }
  1880. /*
  1881. * Execute an ioctl command stored in buffer and check that the result does not
  1882. * overflow memory.
  1883. */
  1884. static bool is_filled(const void *buf, uint8_t c, size_t len)
  1885. {
  1886. const uint8_t *cbuf = buf;
  1887. for (; len; cbuf++, len--)
  1888. if (*cbuf != c)
  1889. return false;
  1890. return true;
  1891. }
  1892. #define ioctl_check_buf(fd, cmd) \
  1893. ({ \
  1894. size_t _cmd_len = *(__u32 *)buffer; \
  1895. \
  1896. memset(buffer + _cmd_len, 0xAA, BUFFER_SIZE - _cmd_len); \
  1897. ASSERT_EQ(0, ioctl(fd, cmd, buffer)); \
  1898. ASSERT_EQ(true, is_filled(buffer + _cmd_len, 0xAA, \
  1899. BUFFER_SIZE - _cmd_len)); \
  1900. })
  1901. static void check_vfio_info_cap_chain(struct __test_metadata *_metadata,
  1902. struct vfio_iommu_type1_info *info_cmd)
  1903. {
  1904. const struct vfio_info_cap_header *cap;
  1905. ASSERT_GE(info_cmd->argsz, info_cmd->cap_offset + sizeof(*cap));
  1906. cap = buffer + info_cmd->cap_offset;
  1907. while (true) {
  1908. size_t cap_size;
  1909. if (cap->next)
  1910. cap_size = (buffer + cap->next) - (void *)cap;
  1911. else
  1912. cap_size = (buffer + info_cmd->argsz) - (void *)cap;
  1913. switch (cap->id) {
  1914. case VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE: {
  1915. struct vfio_iommu_type1_info_cap_iova_range *data =
  1916. (void *)cap;
  1917. ASSERT_EQ(1, data->header.version);
  1918. ASSERT_EQ(1, data->nr_iovas);
  1919. EXPECT_EQ(MOCK_APERTURE_START,
  1920. data->iova_ranges[0].start);
  1921. EXPECT_EQ(MOCK_APERTURE_LAST, data->iova_ranges[0].end);
  1922. break;
  1923. }
  1924. case VFIO_IOMMU_TYPE1_INFO_DMA_AVAIL: {
  1925. struct vfio_iommu_type1_info_dma_avail *data =
  1926. (void *)cap;
  1927. ASSERT_EQ(1, data->header.version);
  1928. ASSERT_EQ(sizeof(*data), cap_size);
  1929. break;
  1930. }
  1931. default:
  1932. ASSERT_EQ(false, true);
  1933. break;
  1934. }
  1935. if (!cap->next)
  1936. break;
  1937. ASSERT_GE(info_cmd->argsz, cap->next + sizeof(*cap));
  1938. ASSERT_GE(buffer + cap->next, (void *)cap);
  1939. cap = buffer + cap->next;
  1940. }
  1941. }
  1942. TEST_F(vfio_compat_mock_domain, get_info)
  1943. {
  1944. struct vfio_iommu_type1_info *info_cmd = buffer;
  1945. unsigned int i;
  1946. size_t caplen;
  1947. /* Pre-cap ABI */
  1948. *info_cmd = (struct vfio_iommu_type1_info){
  1949. .argsz = offsetof(struct vfio_iommu_type1_info, cap_offset),
  1950. };
  1951. ioctl_check_buf(self->fd, VFIO_IOMMU_GET_INFO);
  1952. ASSERT_NE(0, info_cmd->iova_pgsizes);
  1953. ASSERT_EQ(VFIO_IOMMU_INFO_PGSIZES | VFIO_IOMMU_INFO_CAPS,
  1954. info_cmd->flags);
  1955. /* Read the cap chain size */
  1956. *info_cmd = (struct vfio_iommu_type1_info){
  1957. .argsz = sizeof(*info_cmd),
  1958. };
  1959. ioctl_check_buf(self->fd, VFIO_IOMMU_GET_INFO);
  1960. ASSERT_NE(0, info_cmd->iova_pgsizes);
  1961. ASSERT_EQ(VFIO_IOMMU_INFO_PGSIZES | VFIO_IOMMU_INFO_CAPS,
  1962. info_cmd->flags);
  1963. ASSERT_EQ(0, info_cmd->cap_offset);
  1964. ASSERT_LT(sizeof(*info_cmd), info_cmd->argsz);
  1965. /* Read the caps, kernel should never create a corrupted caps */
  1966. caplen = info_cmd->argsz;
  1967. for (i = sizeof(*info_cmd); i < caplen; i++) {
  1968. *info_cmd = (struct vfio_iommu_type1_info){
  1969. .argsz = i,
  1970. };
  1971. ioctl_check_buf(self->fd, VFIO_IOMMU_GET_INFO);
  1972. ASSERT_EQ(VFIO_IOMMU_INFO_PGSIZES | VFIO_IOMMU_INFO_CAPS,
  1973. info_cmd->flags);
  1974. if (!info_cmd->cap_offset)
  1975. continue;
  1976. check_vfio_info_cap_chain(_metadata, info_cmd);
  1977. }
  1978. }
  1979. static void shuffle_array(unsigned long *array, size_t nelms)
  1980. {
  1981. unsigned int i;
  1982. /* Shuffle */
  1983. for (i = 0; i != nelms; i++) {
  1984. unsigned long tmp = array[i];
  1985. unsigned int other = rand() % (nelms - i);
  1986. array[i] = array[other];
  1987. array[other] = tmp;
  1988. }
  1989. }
  1990. TEST_F(vfio_compat_mock_domain, map)
  1991. {
  1992. struct vfio_iommu_type1_dma_map map_cmd = {
  1993. .argsz = sizeof(map_cmd),
  1994. .flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE,
  1995. .vaddr = (uintptr_t)buffer,
  1996. .size = BUFFER_SIZE,
  1997. .iova = MOCK_APERTURE_START,
  1998. };
  1999. struct vfio_iommu_type1_dma_unmap unmap_cmd = {
  2000. .argsz = sizeof(unmap_cmd),
  2001. .size = BUFFER_SIZE,
  2002. .iova = MOCK_APERTURE_START,
  2003. };
  2004. unsigned long pages_iova[BUFFER_SIZE / PAGE_SIZE];
  2005. unsigned int i;
  2006. /* Simple map/unmap */
  2007. ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
  2008. ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
  2009. ASSERT_EQ(BUFFER_SIZE, unmap_cmd.size);
  2010. /* UNMAP_FLAG_ALL requires 0 iova/size */
  2011. ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
  2012. unmap_cmd.flags = VFIO_DMA_UNMAP_FLAG_ALL;
  2013. EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
  2014. unmap_cmd.iova = 0;
  2015. unmap_cmd.size = 0;
  2016. ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
  2017. ASSERT_EQ(BUFFER_SIZE, unmap_cmd.size);
  2018. /* Small pages */
  2019. for (i = 0; i != ARRAY_SIZE(pages_iova); i++) {
  2020. map_cmd.iova = pages_iova[i] =
  2021. MOCK_APERTURE_START + i * PAGE_SIZE;
  2022. map_cmd.vaddr = (uintptr_t)buffer + i * PAGE_SIZE;
  2023. map_cmd.size = PAGE_SIZE;
  2024. ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
  2025. }
  2026. shuffle_array(pages_iova, ARRAY_SIZE(pages_iova));
  2027. unmap_cmd.flags = 0;
  2028. unmap_cmd.size = PAGE_SIZE;
  2029. for (i = 0; i != ARRAY_SIZE(pages_iova); i++) {
  2030. unmap_cmd.iova = pages_iova[i];
  2031. ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
  2032. }
  2033. }
  2034. TEST_F(vfio_compat_mock_domain, huge_map)
  2035. {
  2036. size_t buf_size = HUGEPAGE_SIZE * 2;
  2037. struct vfio_iommu_type1_dma_map map_cmd = {
  2038. .argsz = sizeof(map_cmd),
  2039. .flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE,
  2040. .size = buf_size,
  2041. .iova = MOCK_APERTURE_START,
  2042. };
  2043. struct vfio_iommu_type1_dma_unmap unmap_cmd = {
  2044. .argsz = sizeof(unmap_cmd),
  2045. };
  2046. unsigned long pages_iova[16];
  2047. unsigned int i;
  2048. void *buf;
  2049. /* Test huge pages and splitting */
  2050. buf = mmap(0, buf_size, PROT_READ | PROT_WRITE,
  2051. MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, -1,
  2052. 0);
  2053. ASSERT_NE(MAP_FAILED, buf);
  2054. map_cmd.vaddr = (uintptr_t)buf;
  2055. ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
  2056. unmap_cmd.size = buf_size / ARRAY_SIZE(pages_iova);
  2057. for (i = 0; i != ARRAY_SIZE(pages_iova); i++)
  2058. pages_iova[i] = MOCK_APERTURE_START + (i * unmap_cmd.size);
  2059. shuffle_array(pages_iova, ARRAY_SIZE(pages_iova));
  2060. /* type1 mode can cut up larger mappings, type1v2 always fails */
  2061. for (i = 0; i != ARRAY_SIZE(pages_iova); i++) {
  2062. unmap_cmd.iova = pages_iova[i];
  2063. unmap_cmd.size = buf_size / ARRAY_SIZE(pages_iova);
  2064. if (variant->version == VFIO_TYPE1_IOMMU) {
  2065. ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA,
  2066. &unmap_cmd));
  2067. } else {
  2068. EXPECT_ERRNO(ENOENT,
  2069. ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA,
  2070. &unmap_cmd));
  2071. }
  2072. }
  2073. }
  2074. TEST_HARNESS_MAIN