iommufd.c 100 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES */
  3. #include <asm/unistd.h>
  4. #include <stdlib.h>
  5. #include <sys/capability.h>
  6. #include <sys/mman.h>
  7. #include <sys/eventfd.h>
  8. #define __EXPORTED_HEADERS__
  9. #include <linux/vfio.h>
  10. #include "iommufd_utils.h"
  11. static unsigned long HUGEPAGE_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. mfd_buffer = memfd_mmap(BUFFER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
  43. &mfd);
  44. assert(mfd_buffer != MAP_FAILED);
  45. assert(mfd > 0);
  46. }
  47. FIXTURE(iommufd)
  48. {
  49. int fd;
  50. };
  51. FIXTURE_SETUP(iommufd)
  52. {
  53. self->fd = open("/dev/iommu", O_RDWR);
  54. ASSERT_NE(-1, self->fd);
  55. }
  56. FIXTURE_TEARDOWN(iommufd)
  57. {
  58. teardown_iommufd(self->fd, _metadata);
  59. }
  60. TEST_F(iommufd, simple_close)
  61. {
  62. }
  63. TEST_F(iommufd, cmd_fail)
  64. {
  65. struct iommu_destroy cmd = { .size = sizeof(cmd), .id = 0 };
  66. /* object id is invalid */
  67. EXPECT_ERRNO(ENOENT, _test_ioctl_destroy(self->fd, 0));
  68. /* Bad pointer */
  69. EXPECT_ERRNO(EFAULT, ioctl(self->fd, IOMMU_DESTROY, NULL));
  70. /* Unknown ioctl */
  71. EXPECT_ERRNO(ENOTTY,
  72. ioctl(self->fd, _IO(IOMMUFD_TYPE, IOMMUFD_CMD_BASE - 1),
  73. &cmd));
  74. }
  75. TEST_F(iommufd, cmd_length)
  76. {
  77. #define TEST_LENGTH(_struct, _ioctl, _last) \
  78. { \
  79. size_t min_size = offsetofend(struct _struct, _last); \
  80. struct { \
  81. struct _struct cmd; \
  82. uint8_t extra; \
  83. } cmd = { .cmd = { .size = min_size - 1 }, \
  84. .extra = UINT8_MAX }; \
  85. int old_errno; \
  86. int rc; \
  87. \
  88. EXPECT_ERRNO(EINVAL, ioctl(self->fd, _ioctl, &cmd)); \
  89. cmd.cmd.size = sizeof(struct _struct) + 1; \
  90. EXPECT_ERRNO(E2BIG, ioctl(self->fd, _ioctl, &cmd)); \
  91. cmd.cmd.size = sizeof(struct _struct); \
  92. rc = ioctl(self->fd, _ioctl, &cmd); \
  93. old_errno = errno; \
  94. cmd.cmd.size = sizeof(struct _struct) + 1; \
  95. cmd.extra = 0; \
  96. if (rc) { \
  97. EXPECT_ERRNO(old_errno, \
  98. ioctl(self->fd, _ioctl, &cmd)); \
  99. } else { \
  100. ASSERT_EQ(0, ioctl(self->fd, _ioctl, &cmd)); \
  101. } \
  102. }
  103. TEST_LENGTH(iommu_destroy, IOMMU_DESTROY, id);
  104. TEST_LENGTH(iommu_hw_info, IOMMU_GET_HW_INFO, __reserved);
  105. TEST_LENGTH(iommu_hwpt_alloc, IOMMU_HWPT_ALLOC, __reserved);
  106. TEST_LENGTH(iommu_hwpt_invalidate, IOMMU_HWPT_INVALIDATE, __reserved);
  107. TEST_LENGTH(iommu_ioas_alloc, IOMMU_IOAS_ALLOC, out_ioas_id);
  108. TEST_LENGTH(iommu_ioas_iova_ranges, IOMMU_IOAS_IOVA_RANGES,
  109. out_iova_alignment);
  110. TEST_LENGTH(iommu_ioas_allow_iovas, IOMMU_IOAS_ALLOW_IOVAS,
  111. allowed_iovas);
  112. TEST_LENGTH(iommu_ioas_map, IOMMU_IOAS_MAP, iova);
  113. TEST_LENGTH(iommu_ioas_copy, IOMMU_IOAS_COPY, src_iova);
  114. TEST_LENGTH(iommu_ioas_unmap, IOMMU_IOAS_UNMAP, length);
  115. TEST_LENGTH(iommu_option, IOMMU_OPTION, val64);
  116. TEST_LENGTH(iommu_vfio_ioas, IOMMU_VFIO_IOAS, __reserved);
  117. TEST_LENGTH(iommu_ioas_map_file, IOMMU_IOAS_MAP_FILE, iova);
  118. TEST_LENGTH(iommu_viommu_alloc, IOMMU_VIOMMU_ALLOC, out_viommu_id);
  119. TEST_LENGTH(iommu_vdevice_alloc, IOMMU_VDEVICE_ALLOC, virt_id);
  120. TEST_LENGTH(iommu_ioas_change_process, IOMMU_IOAS_CHANGE_PROCESS,
  121. __reserved);
  122. #undef TEST_LENGTH
  123. }
  124. TEST_F(iommufd, cmd_ex_fail)
  125. {
  126. struct {
  127. struct iommu_destroy cmd;
  128. __u64 future;
  129. } cmd = { .cmd = { .size = sizeof(cmd), .id = 0 } };
  130. /* object id is invalid and command is longer */
  131. EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_DESTROY, &cmd));
  132. /* future area is non-zero */
  133. cmd.future = 1;
  134. EXPECT_ERRNO(E2BIG, ioctl(self->fd, IOMMU_DESTROY, &cmd));
  135. /* Original command "works" */
  136. cmd.cmd.size = sizeof(cmd.cmd);
  137. EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_DESTROY, &cmd));
  138. /* Short command fails */
  139. cmd.cmd.size = sizeof(cmd.cmd) - 1;
  140. EXPECT_ERRNO(EINVAL, ioctl(self->fd, IOMMU_DESTROY, &cmd));
  141. }
  142. TEST_F(iommufd, global_options)
  143. {
  144. struct iommu_option cmd = {
  145. .size = sizeof(cmd),
  146. .option_id = IOMMU_OPTION_RLIMIT_MODE,
  147. .op = IOMMU_OPTION_OP_GET,
  148. .val64 = 1,
  149. };
  150. cmd.option_id = IOMMU_OPTION_RLIMIT_MODE;
  151. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  152. ASSERT_EQ(0, cmd.val64);
  153. /* This requires root */
  154. cmd.op = IOMMU_OPTION_OP_SET;
  155. cmd.val64 = 1;
  156. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  157. cmd.val64 = 2;
  158. EXPECT_ERRNO(EINVAL, ioctl(self->fd, IOMMU_OPTION, &cmd));
  159. cmd.op = IOMMU_OPTION_OP_GET;
  160. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  161. ASSERT_EQ(1, cmd.val64);
  162. cmd.op = IOMMU_OPTION_OP_SET;
  163. cmd.val64 = 0;
  164. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  165. cmd.op = IOMMU_OPTION_OP_GET;
  166. cmd.option_id = IOMMU_OPTION_HUGE_PAGES;
  167. EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_OPTION, &cmd));
  168. cmd.op = IOMMU_OPTION_OP_SET;
  169. EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_OPTION, &cmd));
  170. }
  171. static void drop_cap_ipc_lock(struct __test_metadata *_metadata)
  172. {
  173. cap_t caps;
  174. cap_value_t cap_list[1] = { CAP_IPC_LOCK };
  175. caps = cap_get_proc();
  176. ASSERT_NE(caps, NULL);
  177. ASSERT_NE(-1,
  178. cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_CLEAR));
  179. ASSERT_NE(-1, cap_set_proc(caps));
  180. cap_free(caps);
  181. }
  182. static long get_proc_status_value(pid_t pid, const char *var)
  183. {
  184. FILE *fp;
  185. char buf[80], tag[80];
  186. long val = -1;
  187. snprintf(buf, sizeof(buf), "/proc/%d/status", pid);
  188. fp = fopen(buf, "r");
  189. if (!fp)
  190. return val;
  191. while (fgets(buf, sizeof(buf), fp))
  192. if (fscanf(fp, "%s %ld\n", tag, &val) == 2 && !strcmp(tag, var))
  193. break;
  194. fclose(fp);
  195. return val;
  196. }
  197. static long get_vm_pinned(pid_t pid)
  198. {
  199. return get_proc_status_value(pid, "VmPin:");
  200. }
  201. static long get_vm_locked(pid_t pid)
  202. {
  203. return get_proc_status_value(pid, "VmLck:");
  204. }
  205. FIXTURE(change_process)
  206. {
  207. int fd;
  208. uint32_t ioas_id;
  209. };
  210. FIXTURE_VARIANT(change_process)
  211. {
  212. int accounting;
  213. };
  214. FIXTURE_SETUP(change_process)
  215. {
  216. self->fd = open("/dev/iommu", O_RDWR);
  217. ASSERT_NE(-1, self->fd);
  218. drop_cap_ipc_lock(_metadata);
  219. if (variant->accounting != IOPT_PAGES_ACCOUNT_NONE) {
  220. struct iommu_option set_limit_cmd = {
  221. .size = sizeof(set_limit_cmd),
  222. .option_id = IOMMU_OPTION_RLIMIT_MODE,
  223. .op = IOMMU_OPTION_OP_SET,
  224. .val64 = (variant->accounting == IOPT_PAGES_ACCOUNT_MM),
  225. };
  226. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &set_limit_cmd));
  227. }
  228. test_ioctl_ioas_alloc(&self->ioas_id);
  229. test_cmd_mock_domain(self->ioas_id, NULL, NULL, NULL);
  230. }
  231. FIXTURE_TEARDOWN(change_process)
  232. {
  233. teardown_iommufd(self->fd, _metadata);
  234. }
  235. FIXTURE_VARIANT_ADD(change_process, account_none)
  236. {
  237. .accounting = IOPT_PAGES_ACCOUNT_NONE,
  238. };
  239. FIXTURE_VARIANT_ADD(change_process, account_user)
  240. {
  241. .accounting = IOPT_PAGES_ACCOUNT_USER,
  242. };
  243. FIXTURE_VARIANT_ADD(change_process, account_mm)
  244. {
  245. .accounting = IOPT_PAGES_ACCOUNT_MM,
  246. };
  247. TEST_F(change_process, basic)
  248. {
  249. pid_t parent = getpid();
  250. pid_t child;
  251. __u64 iova;
  252. struct iommu_ioas_change_process cmd = {
  253. .size = sizeof(cmd),
  254. };
  255. /* Expect failure if non-file maps exist */
  256. test_ioctl_ioas_map(buffer, PAGE_SIZE, &iova);
  257. EXPECT_ERRNO(EINVAL, ioctl(self->fd, IOMMU_IOAS_CHANGE_PROCESS, &cmd));
  258. test_ioctl_ioas_unmap(iova, PAGE_SIZE);
  259. /* Change process works in current process. */
  260. test_ioctl_ioas_map_file(mfd, 0, PAGE_SIZE, &iova);
  261. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_CHANGE_PROCESS, &cmd));
  262. /* Change process works in another process */
  263. child = fork();
  264. if (!child) {
  265. int nlock = PAGE_SIZE / 1024;
  266. /* Parent accounts for locked memory before */
  267. ASSERT_EQ(nlock, get_vm_pinned(parent));
  268. if (variant->accounting == IOPT_PAGES_ACCOUNT_MM)
  269. ASSERT_EQ(nlock, get_vm_locked(parent));
  270. ASSERT_EQ(0, get_vm_pinned(getpid()));
  271. ASSERT_EQ(0, get_vm_locked(getpid()));
  272. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_CHANGE_PROCESS, &cmd));
  273. /* Child accounts for locked memory after */
  274. ASSERT_EQ(0, get_vm_pinned(parent));
  275. ASSERT_EQ(0, get_vm_locked(parent));
  276. ASSERT_EQ(nlock, get_vm_pinned(getpid()));
  277. if (variant->accounting == IOPT_PAGES_ACCOUNT_MM)
  278. ASSERT_EQ(nlock, get_vm_locked(getpid()));
  279. exit(0);
  280. }
  281. ASSERT_NE(-1, child);
  282. ASSERT_EQ(child, waitpid(child, NULL, 0));
  283. }
  284. FIXTURE(iommufd_ioas)
  285. {
  286. int fd;
  287. uint32_t ioas_id;
  288. uint32_t stdev_id;
  289. uint32_t hwpt_id;
  290. uint32_t device_id;
  291. uint64_t base_iova;
  292. uint32_t device_pasid_id;
  293. };
  294. FIXTURE_VARIANT(iommufd_ioas)
  295. {
  296. unsigned int mock_domains;
  297. unsigned int memory_limit;
  298. bool pasid_capable;
  299. };
  300. FIXTURE_SETUP(iommufd_ioas)
  301. {
  302. unsigned int i;
  303. self->fd = open("/dev/iommu", O_RDWR);
  304. ASSERT_NE(-1, self->fd);
  305. test_ioctl_ioas_alloc(&self->ioas_id);
  306. if (!variant->memory_limit) {
  307. test_ioctl_set_default_memory_limit();
  308. } else {
  309. test_ioctl_set_temp_memory_limit(variant->memory_limit);
  310. }
  311. for (i = 0; i != variant->mock_domains; i++) {
  312. test_cmd_mock_domain(self->ioas_id, &self->stdev_id,
  313. &self->hwpt_id, &self->device_id);
  314. test_cmd_dev_check_cache_all(self->device_id,
  315. IOMMU_TEST_DEV_CACHE_DEFAULT);
  316. self->base_iova = MOCK_APERTURE_START;
  317. }
  318. if (variant->pasid_capable)
  319. test_cmd_mock_domain_flags(self->ioas_id,
  320. MOCK_FLAGS_DEVICE_PASID,
  321. NULL, NULL,
  322. &self->device_pasid_id);
  323. }
  324. FIXTURE_TEARDOWN(iommufd_ioas)
  325. {
  326. test_ioctl_set_default_memory_limit();
  327. teardown_iommufd(self->fd, _metadata);
  328. }
  329. FIXTURE_VARIANT_ADD(iommufd_ioas, no_domain)
  330. {
  331. };
  332. FIXTURE_VARIANT_ADD(iommufd_ioas, mock_domain)
  333. {
  334. .mock_domains = 1,
  335. .pasid_capable = true,
  336. };
  337. FIXTURE_VARIANT_ADD(iommufd_ioas, two_mock_domain)
  338. {
  339. .mock_domains = 2,
  340. };
  341. FIXTURE_VARIANT_ADD(iommufd_ioas, mock_domain_limit)
  342. {
  343. .mock_domains = 1,
  344. .memory_limit = 16,
  345. };
  346. TEST_F(iommufd_ioas, ioas_auto_destroy)
  347. {
  348. }
  349. TEST_F(iommufd_ioas, ioas_destroy)
  350. {
  351. if (self->stdev_id) {
  352. /* IOAS cannot be freed while a device has a HWPT using it */
  353. EXPECT_ERRNO(EBUSY,
  354. _test_ioctl_destroy(self->fd, self->ioas_id));
  355. } else {
  356. /* Can allocate and manually free an IOAS table */
  357. test_ioctl_destroy(self->ioas_id);
  358. }
  359. }
  360. TEST_F(iommufd_ioas, alloc_hwpt_nested)
  361. {
  362. const uint32_t min_data_len =
  363. offsetofend(struct iommu_hwpt_selftest, iotlb);
  364. struct iommu_hwpt_selftest data = {
  365. .iotlb = IOMMU_TEST_IOTLB_DEFAULT,
  366. };
  367. struct iommu_hwpt_invalidate_selftest inv_reqs[2] = {};
  368. uint32_t nested_hwpt_id[2] = {};
  369. uint32_t num_inv;
  370. uint32_t parent_hwpt_id = 0;
  371. uint32_t parent_hwpt_id_not_work = 0;
  372. uint32_t test_hwpt_id = 0;
  373. uint32_t iopf_hwpt_id;
  374. uint32_t fault_id;
  375. uint32_t fault_fd;
  376. if (self->device_id) {
  377. /* Negative tests */
  378. test_err_hwpt_alloc(ENOENT, self->ioas_id, self->device_id, 0,
  379. &test_hwpt_id);
  380. test_err_hwpt_alloc(EINVAL, self->device_id, self->device_id, 0,
  381. &test_hwpt_id);
  382. test_err_hwpt_alloc(EOPNOTSUPP, self->device_id, self->ioas_id,
  383. IOMMU_HWPT_ALLOC_NEST_PARENT |
  384. IOMMU_HWPT_FAULT_ID_VALID,
  385. &test_hwpt_id);
  386. test_cmd_hwpt_alloc(self->device_id, self->ioas_id,
  387. IOMMU_HWPT_ALLOC_NEST_PARENT,
  388. &parent_hwpt_id);
  389. test_cmd_hwpt_alloc(self->device_id, self->ioas_id, 0,
  390. &parent_hwpt_id_not_work);
  391. /* Negative nested tests */
  392. test_err_hwpt_alloc_nested(EINVAL, self->device_id,
  393. parent_hwpt_id, 0,
  394. &nested_hwpt_id[0],
  395. IOMMU_HWPT_DATA_NONE, &data,
  396. sizeof(data));
  397. test_err_hwpt_alloc_nested(EOPNOTSUPP, self->device_id,
  398. parent_hwpt_id, 0,
  399. &nested_hwpt_id[0],
  400. IOMMU_HWPT_DATA_SELFTEST + 1, &data,
  401. sizeof(data));
  402. test_err_hwpt_alloc_nested(EINVAL, self->device_id,
  403. parent_hwpt_id, 0,
  404. &nested_hwpt_id[0],
  405. IOMMU_HWPT_DATA_SELFTEST, &data,
  406. min_data_len - 1);
  407. test_err_hwpt_alloc_nested(EFAULT, self->device_id,
  408. parent_hwpt_id, 0,
  409. &nested_hwpt_id[0],
  410. IOMMU_HWPT_DATA_SELFTEST, NULL,
  411. sizeof(data));
  412. test_err_hwpt_alloc_nested(
  413. EOPNOTSUPP, self->device_id, parent_hwpt_id,
  414. IOMMU_HWPT_ALLOC_NEST_PARENT, &nested_hwpt_id[0],
  415. IOMMU_HWPT_DATA_SELFTEST, &data, sizeof(data));
  416. test_err_hwpt_alloc_nested(EINVAL, self->device_id,
  417. parent_hwpt_id_not_work, 0,
  418. &nested_hwpt_id[0],
  419. IOMMU_HWPT_DATA_SELFTEST, &data,
  420. sizeof(data));
  421. /* Allocate two nested hwpts sharing one common parent hwpt */
  422. test_ioctl_fault_alloc(&fault_id, &fault_fd);
  423. test_cmd_hwpt_alloc_nested(self->device_id, parent_hwpt_id, 0,
  424. &nested_hwpt_id[0],
  425. IOMMU_HWPT_DATA_SELFTEST, &data,
  426. sizeof(data));
  427. test_cmd_hwpt_alloc_nested(self->device_id, parent_hwpt_id, 0,
  428. &nested_hwpt_id[1],
  429. IOMMU_HWPT_DATA_SELFTEST, &data,
  430. sizeof(data));
  431. test_err_hwpt_alloc_iopf(ENOENT, self->device_id, parent_hwpt_id,
  432. UINT32_MAX, IOMMU_HWPT_FAULT_ID_VALID,
  433. &iopf_hwpt_id, IOMMU_HWPT_DATA_SELFTEST,
  434. &data, sizeof(data));
  435. test_cmd_hwpt_alloc_iopf(self->device_id, parent_hwpt_id, fault_id,
  436. IOMMU_HWPT_FAULT_ID_VALID, &iopf_hwpt_id,
  437. IOMMU_HWPT_DATA_SELFTEST, &data,
  438. sizeof(data));
  439. test_cmd_hwpt_check_iotlb_all(nested_hwpt_id[0],
  440. IOMMU_TEST_IOTLB_DEFAULT);
  441. test_cmd_hwpt_check_iotlb_all(nested_hwpt_id[1],
  442. IOMMU_TEST_IOTLB_DEFAULT);
  443. /* Negative test: a nested hwpt on top of a nested hwpt */
  444. test_err_hwpt_alloc_nested(EINVAL, self->device_id,
  445. nested_hwpt_id[0], 0, &test_hwpt_id,
  446. IOMMU_HWPT_DATA_SELFTEST, &data,
  447. sizeof(data));
  448. /* Negative test: parent hwpt now cannot be freed */
  449. EXPECT_ERRNO(EBUSY,
  450. _test_ioctl_destroy(self->fd, parent_hwpt_id));
  451. /* hwpt_invalidate does not support a parent hwpt */
  452. num_inv = 1;
  453. test_err_hwpt_invalidate(EINVAL, parent_hwpt_id, inv_reqs,
  454. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  455. sizeof(*inv_reqs), &num_inv);
  456. assert(!num_inv);
  457. /* Check data_type by passing zero-length array */
  458. num_inv = 0;
  459. test_cmd_hwpt_invalidate(nested_hwpt_id[0], inv_reqs,
  460. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  461. sizeof(*inv_reqs), &num_inv);
  462. assert(!num_inv);
  463. /* Negative test: Invalid data_type */
  464. num_inv = 1;
  465. test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
  466. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST_INVALID,
  467. sizeof(*inv_reqs), &num_inv);
  468. assert(!num_inv);
  469. /* Negative test: structure size sanity */
  470. num_inv = 1;
  471. test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
  472. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  473. sizeof(*inv_reqs) + 1, &num_inv);
  474. assert(!num_inv);
  475. num_inv = 1;
  476. test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
  477. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  478. 1, &num_inv);
  479. assert(!num_inv);
  480. /* Negative test: invalid flag is passed */
  481. num_inv = 1;
  482. inv_reqs[0].flags = 0xffffffff;
  483. test_err_hwpt_invalidate(EOPNOTSUPP, nested_hwpt_id[0], inv_reqs,
  484. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  485. sizeof(*inv_reqs), &num_inv);
  486. assert(!num_inv);
  487. /* Negative test: invalid data_uptr when array is not empty */
  488. num_inv = 1;
  489. inv_reqs[0].flags = 0;
  490. test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], NULL,
  491. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  492. sizeof(*inv_reqs), &num_inv);
  493. assert(!num_inv);
  494. /* Negative test: invalid entry_len when array is not empty */
  495. num_inv = 1;
  496. inv_reqs[0].flags = 0;
  497. test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
  498. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  499. 0, &num_inv);
  500. assert(!num_inv);
  501. /* Negative test: invalid iotlb_id */
  502. num_inv = 1;
  503. inv_reqs[0].flags = 0;
  504. inv_reqs[0].iotlb_id = MOCK_NESTED_DOMAIN_IOTLB_ID_MAX + 1;
  505. test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
  506. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  507. sizeof(*inv_reqs), &num_inv);
  508. assert(!num_inv);
  509. /*
  510. * Invalidate the 1st iotlb entry but fail the 2nd request
  511. * due to invalid flags configuration in the 2nd request.
  512. */
  513. num_inv = 2;
  514. inv_reqs[0].flags = 0;
  515. inv_reqs[0].iotlb_id = 0;
  516. inv_reqs[1].flags = 0xffffffff;
  517. inv_reqs[1].iotlb_id = 1;
  518. test_err_hwpt_invalidate(EOPNOTSUPP, nested_hwpt_id[0], inv_reqs,
  519. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  520. sizeof(*inv_reqs), &num_inv);
  521. assert(num_inv == 1);
  522. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 0, 0);
  523. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 1,
  524. IOMMU_TEST_IOTLB_DEFAULT);
  525. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 2,
  526. IOMMU_TEST_IOTLB_DEFAULT);
  527. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 3,
  528. IOMMU_TEST_IOTLB_DEFAULT);
  529. /*
  530. * Invalidate the 1st iotlb entry but fail the 2nd request
  531. * due to invalid iotlb_id configuration in the 2nd request.
  532. */
  533. num_inv = 2;
  534. inv_reqs[0].flags = 0;
  535. inv_reqs[0].iotlb_id = 0;
  536. inv_reqs[1].flags = 0;
  537. inv_reqs[1].iotlb_id = MOCK_NESTED_DOMAIN_IOTLB_ID_MAX + 1;
  538. test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
  539. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  540. sizeof(*inv_reqs), &num_inv);
  541. assert(num_inv == 1);
  542. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 0, 0);
  543. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 1,
  544. IOMMU_TEST_IOTLB_DEFAULT);
  545. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 2,
  546. IOMMU_TEST_IOTLB_DEFAULT);
  547. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 3,
  548. IOMMU_TEST_IOTLB_DEFAULT);
  549. /* Invalidate the 2nd iotlb entry and verify */
  550. num_inv = 1;
  551. inv_reqs[0].flags = 0;
  552. inv_reqs[0].iotlb_id = 1;
  553. test_cmd_hwpt_invalidate(nested_hwpt_id[0], inv_reqs,
  554. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  555. sizeof(*inv_reqs), &num_inv);
  556. assert(num_inv == 1);
  557. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 0, 0);
  558. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 1, 0);
  559. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 2,
  560. IOMMU_TEST_IOTLB_DEFAULT);
  561. test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 3,
  562. IOMMU_TEST_IOTLB_DEFAULT);
  563. /* Invalidate the 3rd and 4th iotlb entries and verify */
  564. num_inv = 2;
  565. inv_reqs[0].flags = 0;
  566. inv_reqs[0].iotlb_id = 2;
  567. inv_reqs[1].flags = 0;
  568. inv_reqs[1].iotlb_id = 3;
  569. test_cmd_hwpt_invalidate(nested_hwpt_id[0], inv_reqs,
  570. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  571. sizeof(*inv_reqs), &num_inv);
  572. assert(num_inv == 2);
  573. test_cmd_hwpt_check_iotlb_all(nested_hwpt_id[0], 0);
  574. /* Invalidate all iotlb entries for nested_hwpt_id[1] and verify */
  575. num_inv = 1;
  576. inv_reqs[0].flags = IOMMU_TEST_INVALIDATE_FLAG_ALL;
  577. test_cmd_hwpt_invalidate(nested_hwpt_id[1], inv_reqs,
  578. IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
  579. sizeof(*inv_reqs), &num_inv);
  580. assert(num_inv == 1);
  581. test_cmd_hwpt_check_iotlb_all(nested_hwpt_id[1], 0);
  582. /* Attach device to nested_hwpt_id[0] that then will be busy */
  583. test_cmd_mock_domain_replace(self->stdev_id, nested_hwpt_id[0]);
  584. EXPECT_ERRNO(EBUSY,
  585. _test_ioctl_destroy(self->fd, nested_hwpt_id[0]));
  586. /* Switch from nested_hwpt_id[0] to nested_hwpt_id[1] */
  587. test_cmd_mock_domain_replace(self->stdev_id, nested_hwpt_id[1]);
  588. EXPECT_ERRNO(EBUSY,
  589. _test_ioctl_destroy(self->fd, nested_hwpt_id[1]));
  590. test_ioctl_destroy(nested_hwpt_id[0]);
  591. /* Switch from nested_hwpt_id[1] to iopf_hwpt_id */
  592. test_cmd_mock_domain_replace(self->stdev_id, iopf_hwpt_id);
  593. EXPECT_ERRNO(EBUSY,
  594. _test_ioctl_destroy(self->fd, iopf_hwpt_id));
  595. /* Trigger an IOPF on the device */
  596. test_cmd_trigger_iopf(self->device_id, fault_fd);
  597. /* Detach from nested_hwpt_id[1] and destroy it */
  598. test_cmd_mock_domain_replace(self->stdev_id, parent_hwpt_id);
  599. test_ioctl_destroy(nested_hwpt_id[1]);
  600. test_ioctl_destroy(iopf_hwpt_id);
  601. /* Detach from the parent hw_pagetable and destroy it */
  602. test_cmd_mock_domain_replace(self->stdev_id, self->ioas_id);
  603. test_ioctl_destroy(parent_hwpt_id);
  604. test_ioctl_destroy(parent_hwpt_id_not_work);
  605. close(fault_fd);
  606. test_ioctl_destroy(fault_id);
  607. } else {
  608. test_err_hwpt_alloc(ENOENT, self->device_id, self->ioas_id, 0,
  609. &parent_hwpt_id);
  610. test_err_hwpt_alloc_nested(ENOENT, self->device_id,
  611. parent_hwpt_id, 0,
  612. &nested_hwpt_id[0],
  613. IOMMU_HWPT_DATA_SELFTEST, &data,
  614. sizeof(data));
  615. test_err_hwpt_alloc_nested(ENOENT, self->device_id,
  616. parent_hwpt_id, 0,
  617. &nested_hwpt_id[1],
  618. IOMMU_HWPT_DATA_SELFTEST, &data,
  619. sizeof(data));
  620. test_err_mock_domain_replace(ENOENT, self->stdev_id,
  621. nested_hwpt_id[0]);
  622. test_err_mock_domain_replace(ENOENT, self->stdev_id,
  623. nested_hwpt_id[1]);
  624. }
  625. }
  626. TEST_F(iommufd_ioas, hwpt_attach)
  627. {
  628. /* Create a device attached directly to a hwpt */
  629. if (self->stdev_id) {
  630. test_cmd_mock_domain(self->hwpt_id, NULL, NULL, NULL);
  631. } else {
  632. test_err_mock_domain(ENOENT, self->hwpt_id, NULL, NULL);
  633. }
  634. }
  635. TEST_F(iommufd_ioas, ioas_area_destroy)
  636. {
  637. /* Adding an area does not change ability to destroy */
  638. test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE, self->base_iova);
  639. if (self->stdev_id)
  640. EXPECT_ERRNO(EBUSY,
  641. _test_ioctl_destroy(self->fd, self->ioas_id));
  642. else
  643. test_ioctl_destroy(self->ioas_id);
  644. }
  645. TEST_F(iommufd_ioas, ioas_area_auto_destroy)
  646. {
  647. int i;
  648. /* Can allocate and automatically free an IOAS table with many areas */
  649. for (i = 0; i != 10; i++) {
  650. test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE,
  651. self->base_iova + i * PAGE_SIZE);
  652. }
  653. }
  654. TEST_F(iommufd_ioas, get_hw_info)
  655. {
  656. struct iommu_test_hw_info buffer_exact;
  657. struct iommu_test_hw_info_buffer_larger {
  658. struct iommu_test_hw_info info;
  659. uint64_t trailing_bytes;
  660. } buffer_larger;
  661. if (self->device_id) {
  662. uint8_t max_pasid = 0;
  663. /* Provide a zero-size user_buffer */
  664. test_cmd_get_hw_info(self->device_id,
  665. IOMMU_HW_INFO_TYPE_DEFAULT, NULL, 0);
  666. /* Provide a user_buffer with exact size */
  667. test_cmd_get_hw_info(self->device_id,
  668. IOMMU_HW_INFO_TYPE_DEFAULT, &buffer_exact,
  669. sizeof(buffer_exact));
  670. /* Request for a wrong data_type, and a correct one */
  671. test_err_get_hw_info(EOPNOTSUPP, self->device_id,
  672. IOMMU_HW_INFO_TYPE_SELFTEST + 1,
  673. &buffer_exact, sizeof(buffer_exact));
  674. test_cmd_get_hw_info(self->device_id,
  675. IOMMU_HW_INFO_TYPE_SELFTEST, &buffer_exact,
  676. sizeof(buffer_exact));
  677. /*
  678. * Provide a user_buffer with size larger than the exact size to check if
  679. * kernel zero the trailing bytes.
  680. */
  681. test_cmd_get_hw_info(self->device_id,
  682. IOMMU_HW_INFO_TYPE_DEFAULT, &buffer_larger,
  683. sizeof(buffer_larger));
  684. /*
  685. * Provide a user_buffer with size smaller than the exact size to check if
  686. * the fields within the size range still gets updated.
  687. */
  688. test_cmd_get_hw_info(self->device_id,
  689. IOMMU_HW_INFO_TYPE_DEFAULT, &buffer_exact,
  690. offsetofend(struct iommu_test_hw_info,
  691. flags));
  692. test_cmd_get_hw_info_pasid(self->device_id, &max_pasid);
  693. ASSERT_EQ(0, max_pasid);
  694. if (variant->pasid_capable) {
  695. test_cmd_get_hw_info_pasid(self->device_pasid_id,
  696. &max_pasid);
  697. ASSERT_EQ(MOCK_PASID_WIDTH, max_pasid);
  698. }
  699. } else {
  700. test_err_get_hw_info(ENOENT, self->device_id,
  701. IOMMU_HW_INFO_TYPE_DEFAULT, &buffer_exact,
  702. sizeof(buffer_exact));
  703. test_err_get_hw_info(ENOENT, self->device_id,
  704. IOMMU_HW_INFO_TYPE_DEFAULT, &buffer_larger,
  705. sizeof(buffer_larger));
  706. }
  707. }
  708. TEST_F(iommufd_ioas, area)
  709. {
  710. int i;
  711. /* Unmap fails if nothing is mapped */
  712. for (i = 0; i != 10; i++)
  713. test_err_ioctl_ioas_unmap(ENOENT, i * PAGE_SIZE, PAGE_SIZE);
  714. /* Unmap works */
  715. for (i = 0; i != 10; i++)
  716. test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE,
  717. self->base_iova + i * PAGE_SIZE);
  718. for (i = 0; i != 10; i++)
  719. test_ioctl_ioas_unmap(self->base_iova + i * PAGE_SIZE,
  720. PAGE_SIZE);
  721. /* Split fails */
  722. test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE * 2,
  723. self->base_iova + 16 * PAGE_SIZE);
  724. test_err_ioctl_ioas_unmap(ENOENT, self->base_iova + 16 * PAGE_SIZE,
  725. PAGE_SIZE);
  726. test_err_ioctl_ioas_unmap(ENOENT, self->base_iova + 17 * PAGE_SIZE,
  727. PAGE_SIZE);
  728. /* Over map fails */
  729. test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE * 2,
  730. self->base_iova + 16 * PAGE_SIZE);
  731. test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE,
  732. self->base_iova + 16 * PAGE_SIZE);
  733. test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE,
  734. self->base_iova + 17 * PAGE_SIZE);
  735. test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE * 2,
  736. self->base_iova + 15 * PAGE_SIZE);
  737. test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE * 3,
  738. self->base_iova + 15 * PAGE_SIZE);
  739. /* unmap all works */
  740. test_ioctl_ioas_unmap(0, UINT64_MAX);
  741. /* Unmap all succeeds on an empty IOAS */
  742. test_ioctl_ioas_unmap(0, UINT64_MAX);
  743. }
  744. TEST_F(iommufd_ioas, unmap_fully_contained_areas)
  745. {
  746. uint64_t unmap_len;
  747. int i;
  748. /* Give no_domain some space to rewind base_iova */
  749. self->base_iova += 4 * PAGE_SIZE;
  750. for (i = 0; i != 4; i++)
  751. test_ioctl_ioas_map_fixed(buffer, 8 * PAGE_SIZE,
  752. self->base_iova + i * 16 * PAGE_SIZE);
  753. /* Unmap not fully contained area doesn't work */
  754. test_err_ioctl_ioas_unmap(ENOENT, self->base_iova - 4 * PAGE_SIZE,
  755. 8 * PAGE_SIZE);
  756. test_err_ioctl_ioas_unmap(ENOENT,
  757. self->base_iova + 3 * 16 * PAGE_SIZE +
  758. 8 * PAGE_SIZE - 4 * PAGE_SIZE,
  759. 8 * PAGE_SIZE);
  760. /* Unmap fully contained areas works */
  761. ASSERT_EQ(0, _test_ioctl_ioas_unmap(self->fd, self->ioas_id,
  762. self->base_iova - 4 * PAGE_SIZE,
  763. 3 * 16 * PAGE_SIZE + 8 * PAGE_SIZE +
  764. 4 * PAGE_SIZE,
  765. &unmap_len));
  766. ASSERT_EQ(32 * PAGE_SIZE, unmap_len);
  767. }
  768. TEST_F(iommufd_ioas, area_auto_iova)
  769. {
  770. struct iommu_test_cmd test_cmd = {
  771. .size = sizeof(test_cmd),
  772. .op = IOMMU_TEST_OP_ADD_RESERVED,
  773. .id = self->ioas_id,
  774. .add_reserved = { .start = PAGE_SIZE * 4,
  775. .length = PAGE_SIZE * 100 },
  776. };
  777. struct iommu_iova_range ranges[1] = {};
  778. struct iommu_ioas_allow_iovas allow_cmd = {
  779. .size = sizeof(allow_cmd),
  780. .ioas_id = self->ioas_id,
  781. .num_iovas = 1,
  782. .allowed_iovas = (uintptr_t)ranges,
  783. };
  784. __u64 iovas[10];
  785. int i;
  786. /* Simple 4k pages */
  787. for (i = 0; i != 10; i++)
  788. test_ioctl_ioas_map(buffer, PAGE_SIZE, &iovas[i]);
  789. for (i = 0; i != 10; i++)
  790. test_ioctl_ioas_unmap(iovas[i], PAGE_SIZE);
  791. /* Kernel automatically aligns IOVAs properly */
  792. for (i = 0; i != 10; i++) {
  793. size_t length = PAGE_SIZE * (i + 1);
  794. if (self->stdev_id) {
  795. test_ioctl_ioas_map(buffer, length, &iovas[i]);
  796. } else {
  797. test_ioctl_ioas_map((void *)(1UL << 31), length,
  798. &iovas[i]);
  799. }
  800. EXPECT_EQ(0, iovas[i] % (1UL << (ffs(length) - 1)));
  801. }
  802. for (i = 0; i != 10; i++)
  803. test_ioctl_ioas_unmap(iovas[i], PAGE_SIZE * (i + 1));
  804. /* Avoids a reserved region */
  805. ASSERT_EQ(0,
  806. ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
  807. &test_cmd));
  808. for (i = 0; i != 10; i++) {
  809. size_t length = PAGE_SIZE * (i + 1);
  810. test_ioctl_ioas_map(buffer, length, &iovas[i]);
  811. EXPECT_EQ(0, iovas[i] % (1UL << (ffs(length) - 1)));
  812. EXPECT_EQ(false,
  813. iovas[i] > test_cmd.add_reserved.start &&
  814. iovas[i] <
  815. test_cmd.add_reserved.start +
  816. test_cmd.add_reserved.length);
  817. }
  818. for (i = 0; i != 10; i++)
  819. test_ioctl_ioas_unmap(iovas[i], PAGE_SIZE * (i + 1));
  820. /* Allowed region intersects with a reserved region */
  821. ranges[0].start = PAGE_SIZE;
  822. ranges[0].last = PAGE_SIZE * 600;
  823. EXPECT_ERRNO(EADDRINUSE,
  824. ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
  825. /* Allocate from an allowed region */
  826. if (self->stdev_id) {
  827. ranges[0].start = MOCK_APERTURE_START + PAGE_SIZE;
  828. ranges[0].last = MOCK_APERTURE_START + PAGE_SIZE * 600 - 1;
  829. } else {
  830. ranges[0].start = PAGE_SIZE * 200;
  831. ranges[0].last = PAGE_SIZE * 600 - 1;
  832. }
  833. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
  834. for (i = 0; i != 10; i++) {
  835. size_t length = PAGE_SIZE * (i + 1);
  836. test_ioctl_ioas_map(buffer, length, &iovas[i]);
  837. EXPECT_EQ(0, iovas[i] % (1UL << (ffs(length) - 1)));
  838. EXPECT_EQ(true, iovas[i] >= ranges[0].start);
  839. EXPECT_EQ(true, iovas[i] <= ranges[0].last);
  840. EXPECT_EQ(true, iovas[i] + length > ranges[0].start);
  841. EXPECT_EQ(true, iovas[i] + length <= ranges[0].last + 1);
  842. }
  843. for (i = 0; i != 10; i++)
  844. test_ioctl_ioas_unmap(iovas[i], PAGE_SIZE * (i + 1));
  845. }
  846. /* https://lore.kernel.org/r/685af644.a00a0220.2e5631.0094.GAE@google.com */
  847. TEST_F(iommufd_ioas, reserved_overflow)
  848. {
  849. struct iommu_test_cmd test_cmd = {
  850. .size = sizeof(test_cmd),
  851. .op = IOMMU_TEST_OP_ADD_RESERVED,
  852. .id = self->ioas_id,
  853. .add_reserved.start = 6,
  854. };
  855. unsigned int map_len;
  856. __u64 iova;
  857. if (PAGE_SIZE == 4096) {
  858. test_cmd.add_reserved.length = 0xffffffffffff8001;
  859. map_len = 0x5000;
  860. } else {
  861. test_cmd.add_reserved.length =
  862. 0xffffffffffffffff - MOCK_PAGE_SIZE * 16;
  863. map_len = MOCK_PAGE_SIZE * 10;
  864. }
  865. ASSERT_EQ(0,
  866. ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
  867. &test_cmd));
  868. test_err_ioctl_ioas_map(ENOSPC, buffer, map_len, &iova);
  869. }
  870. TEST_F(iommufd_ioas, area_allowed)
  871. {
  872. struct iommu_test_cmd test_cmd = {
  873. .size = sizeof(test_cmd),
  874. .op = IOMMU_TEST_OP_ADD_RESERVED,
  875. .id = self->ioas_id,
  876. .add_reserved = { .start = PAGE_SIZE * 4,
  877. .length = PAGE_SIZE * 100 },
  878. };
  879. struct iommu_iova_range ranges[1] = {};
  880. struct iommu_ioas_allow_iovas allow_cmd = {
  881. .size = sizeof(allow_cmd),
  882. .ioas_id = self->ioas_id,
  883. .num_iovas = 1,
  884. .allowed_iovas = (uintptr_t)ranges,
  885. };
  886. /* Reserved intersects an allowed */
  887. allow_cmd.num_iovas = 1;
  888. ranges[0].start = self->base_iova;
  889. ranges[0].last = ranges[0].start + PAGE_SIZE * 600;
  890. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
  891. test_cmd.add_reserved.start = ranges[0].start + PAGE_SIZE;
  892. test_cmd.add_reserved.length = PAGE_SIZE;
  893. EXPECT_ERRNO(EADDRINUSE,
  894. ioctl(self->fd,
  895. _IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
  896. &test_cmd));
  897. allow_cmd.num_iovas = 0;
  898. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
  899. /* Allowed intersects a reserved */
  900. ASSERT_EQ(0,
  901. ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
  902. &test_cmd));
  903. allow_cmd.num_iovas = 1;
  904. ranges[0].start = self->base_iova;
  905. ranges[0].last = ranges[0].start + PAGE_SIZE * 600;
  906. EXPECT_ERRNO(EADDRINUSE,
  907. ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
  908. }
  909. TEST_F(iommufd_ioas, copy_area)
  910. {
  911. struct iommu_ioas_copy copy_cmd = {
  912. .size = sizeof(copy_cmd),
  913. .flags = IOMMU_IOAS_MAP_FIXED_IOVA | IOMMU_IOAS_MAP_WRITEABLE,
  914. .dst_ioas_id = self->ioas_id,
  915. .src_ioas_id = self->ioas_id,
  916. .length = PAGE_SIZE,
  917. };
  918. test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE, self->base_iova);
  919. /* Copy inside a single IOAS */
  920. copy_cmd.src_iova = self->base_iova;
  921. copy_cmd.dst_iova = self->base_iova + PAGE_SIZE;
  922. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
  923. /* Copy between IOAS's */
  924. copy_cmd.src_iova = self->base_iova;
  925. copy_cmd.dst_iova = 0;
  926. test_ioctl_ioas_alloc(&copy_cmd.dst_ioas_id);
  927. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
  928. }
  929. TEST_F(iommufd_ioas, iova_ranges)
  930. {
  931. struct iommu_test_cmd test_cmd = {
  932. .size = sizeof(test_cmd),
  933. .op = IOMMU_TEST_OP_ADD_RESERVED,
  934. .id = self->ioas_id,
  935. .add_reserved = { .start = PAGE_SIZE, .length = PAGE_SIZE },
  936. };
  937. struct iommu_iova_range *ranges = buffer;
  938. struct iommu_ioas_iova_ranges ranges_cmd = {
  939. .size = sizeof(ranges_cmd),
  940. .ioas_id = self->ioas_id,
  941. .num_iovas = BUFFER_SIZE / sizeof(*ranges),
  942. .allowed_iovas = (uintptr_t)ranges,
  943. };
  944. /* Range can be read */
  945. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES, &ranges_cmd));
  946. EXPECT_EQ(1, ranges_cmd.num_iovas);
  947. if (!self->stdev_id) {
  948. EXPECT_EQ(0, ranges[0].start);
  949. EXPECT_EQ(SIZE_MAX, ranges[0].last);
  950. EXPECT_EQ(1, ranges_cmd.out_iova_alignment);
  951. } else {
  952. EXPECT_EQ(MOCK_APERTURE_START, ranges[0].start);
  953. EXPECT_EQ(MOCK_APERTURE_LAST, ranges[0].last);
  954. EXPECT_EQ(MOCK_PAGE_SIZE, ranges_cmd.out_iova_alignment);
  955. }
  956. /* Buffer too small */
  957. memset(ranges, 0, BUFFER_SIZE);
  958. ranges_cmd.num_iovas = 0;
  959. EXPECT_ERRNO(EMSGSIZE,
  960. ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES, &ranges_cmd));
  961. EXPECT_EQ(1, ranges_cmd.num_iovas);
  962. EXPECT_EQ(0, ranges[0].start);
  963. EXPECT_EQ(0, ranges[0].last);
  964. /* 2 ranges */
  965. ASSERT_EQ(0,
  966. ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
  967. &test_cmd));
  968. ranges_cmd.num_iovas = BUFFER_SIZE / sizeof(*ranges);
  969. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES, &ranges_cmd));
  970. if (!self->stdev_id) {
  971. EXPECT_EQ(2, ranges_cmd.num_iovas);
  972. EXPECT_EQ(0, ranges[0].start);
  973. EXPECT_EQ(PAGE_SIZE - 1, ranges[0].last);
  974. EXPECT_EQ(PAGE_SIZE * 2, ranges[1].start);
  975. EXPECT_EQ(SIZE_MAX, ranges[1].last);
  976. } else {
  977. EXPECT_EQ(1, ranges_cmd.num_iovas);
  978. EXPECT_EQ(MOCK_APERTURE_START, ranges[0].start);
  979. EXPECT_EQ(MOCK_APERTURE_LAST, ranges[0].last);
  980. }
  981. /* Buffer too small */
  982. memset(ranges, 0, BUFFER_SIZE);
  983. ranges_cmd.num_iovas = 1;
  984. if (!self->stdev_id) {
  985. EXPECT_ERRNO(EMSGSIZE, ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES,
  986. &ranges_cmd));
  987. EXPECT_EQ(2, ranges_cmd.num_iovas);
  988. EXPECT_EQ(0, ranges[0].start);
  989. EXPECT_EQ(PAGE_SIZE - 1, ranges[0].last);
  990. } else {
  991. ASSERT_EQ(0,
  992. ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES, &ranges_cmd));
  993. EXPECT_EQ(1, ranges_cmd.num_iovas);
  994. EXPECT_EQ(MOCK_APERTURE_START, ranges[0].start);
  995. EXPECT_EQ(MOCK_APERTURE_LAST, ranges[0].last);
  996. }
  997. EXPECT_EQ(0, ranges[1].start);
  998. EXPECT_EQ(0, ranges[1].last);
  999. }
  1000. TEST_F(iommufd_ioas, access_domain_destory)
  1001. {
  1002. struct iommu_test_cmd access_cmd = {
  1003. .size = sizeof(access_cmd),
  1004. .op = IOMMU_TEST_OP_ACCESS_PAGES,
  1005. .access_pages = { .iova = self->base_iova + PAGE_SIZE,
  1006. .length = PAGE_SIZE},
  1007. };
  1008. size_t buf_size = 2 * HUGEPAGE_SIZE;
  1009. uint8_t *buf;
  1010. buf = mmap(0, buf_size, PROT_READ | PROT_WRITE,
  1011. MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, -1,
  1012. 0);
  1013. ASSERT_NE(MAP_FAILED, buf);
  1014. test_ioctl_ioas_map_fixed(buf, buf_size, self->base_iova);
  1015. test_cmd_create_access(self->ioas_id, &access_cmd.id,
  1016. MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES);
  1017. access_cmd.access_pages.uptr = (uintptr_t)buf + PAGE_SIZE;
  1018. ASSERT_EQ(0,
  1019. ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
  1020. &access_cmd));
  1021. /* Causes a complicated unpin across a huge page boundary */
  1022. if (self->stdev_id)
  1023. test_ioctl_destroy(self->stdev_id);
  1024. test_cmd_destroy_access_pages(
  1025. access_cmd.id, access_cmd.access_pages.out_access_pages_id);
  1026. test_cmd_destroy_access(access_cmd.id);
  1027. ASSERT_EQ(0, munmap(buf, buf_size));
  1028. }
  1029. TEST_F(iommufd_ioas, access_pin)
  1030. {
  1031. struct iommu_test_cmd access_cmd = {
  1032. .size = sizeof(access_cmd),
  1033. .op = IOMMU_TEST_OP_ACCESS_PAGES,
  1034. .access_pages = { .iova = MOCK_APERTURE_START,
  1035. .length = BUFFER_SIZE,
  1036. .uptr = (uintptr_t)buffer },
  1037. };
  1038. struct iommu_test_cmd check_map_cmd = {
  1039. .size = sizeof(check_map_cmd),
  1040. .op = IOMMU_TEST_OP_MD_CHECK_MAP,
  1041. .check_map = { .iova = MOCK_APERTURE_START,
  1042. .length = BUFFER_SIZE,
  1043. .uptr = (uintptr_t)buffer },
  1044. };
  1045. uint32_t access_pages_id;
  1046. unsigned int npages;
  1047. test_cmd_create_access(self->ioas_id, &access_cmd.id,
  1048. MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES);
  1049. for (npages = 1; npages < BUFFER_SIZE / PAGE_SIZE; npages++) {
  1050. uint32_t mock_stdev_id;
  1051. uint32_t mock_hwpt_id;
  1052. access_cmd.access_pages.length = npages * PAGE_SIZE;
  1053. /* Single map/unmap */
  1054. test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE,
  1055. MOCK_APERTURE_START);
  1056. ASSERT_EQ(0, ioctl(self->fd,
  1057. _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
  1058. &access_cmd));
  1059. test_cmd_destroy_access_pages(
  1060. access_cmd.id,
  1061. access_cmd.access_pages.out_access_pages_id);
  1062. /* Double user */
  1063. ASSERT_EQ(0, ioctl(self->fd,
  1064. _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
  1065. &access_cmd));
  1066. access_pages_id = access_cmd.access_pages.out_access_pages_id;
  1067. ASSERT_EQ(0, ioctl(self->fd,
  1068. _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
  1069. &access_cmd));
  1070. test_cmd_destroy_access_pages(
  1071. access_cmd.id,
  1072. access_cmd.access_pages.out_access_pages_id);
  1073. test_cmd_destroy_access_pages(access_cmd.id, access_pages_id);
  1074. /* Add/remove a domain with a user */
  1075. ASSERT_EQ(0, ioctl(self->fd,
  1076. _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
  1077. &access_cmd));
  1078. test_cmd_mock_domain(self->ioas_id, &mock_stdev_id,
  1079. &mock_hwpt_id, NULL);
  1080. check_map_cmd.id = mock_hwpt_id;
  1081. ASSERT_EQ(0, ioctl(self->fd,
  1082. _IOMMU_TEST_CMD(IOMMU_TEST_OP_MD_CHECK_MAP),
  1083. &check_map_cmd));
  1084. test_ioctl_destroy(mock_stdev_id);
  1085. test_cmd_destroy_access_pages(
  1086. access_cmd.id,
  1087. access_cmd.access_pages.out_access_pages_id);
  1088. test_ioctl_ioas_unmap(MOCK_APERTURE_START, BUFFER_SIZE);
  1089. }
  1090. test_cmd_destroy_access(access_cmd.id);
  1091. }
  1092. TEST_F(iommufd_ioas, access_pin_unmap)
  1093. {
  1094. struct iommu_test_cmd access_pages_cmd = {
  1095. .size = sizeof(access_pages_cmd),
  1096. .op = IOMMU_TEST_OP_ACCESS_PAGES,
  1097. .access_pages = { .iova = MOCK_APERTURE_START,
  1098. .length = BUFFER_SIZE,
  1099. .uptr = (uintptr_t)buffer },
  1100. };
  1101. test_cmd_create_access(self->ioas_id, &access_pages_cmd.id,
  1102. MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES);
  1103. test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE, MOCK_APERTURE_START);
  1104. ASSERT_EQ(0,
  1105. ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
  1106. &access_pages_cmd));
  1107. /* Trigger the unmap op */
  1108. test_ioctl_ioas_unmap(MOCK_APERTURE_START, BUFFER_SIZE);
  1109. /* kernel removed the item for us */
  1110. test_err_destroy_access_pages(
  1111. ENOENT, access_pages_cmd.id,
  1112. access_pages_cmd.access_pages.out_access_pages_id);
  1113. }
  1114. static void check_access_rw(struct __test_metadata *_metadata, int fd,
  1115. unsigned int access_id, uint64_t iova,
  1116. unsigned int def_flags)
  1117. {
  1118. uint16_t tmp[32];
  1119. struct iommu_test_cmd access_cmd = {
  1120. .size = sizeof(access_cmd),
  1121. .op = IOMMU_TEST_OP_ACCESS_RW,
  1122. .id = access_id,
  1123. .access_rw = { .uptr = (uintptr_t)tmp },
  1124. };
  1125. uint16_t *buffer16 = buffer;
  1126. unsigned int i;
  1127. void *tmp2;
  1128. for (i = 0; i != BUFFER_SIZE / sizeof(*buffer16); i++)
  1129. buffer16[i] = rand();
  1130. for (access_cmd.access_rw.iova = iova + PAGE_SIZE - 50;
  1131. access_cmd.access_rw.iova < iova + PAGE_SIZE + 50;
  1132. access_cmd.access_rw.iova++) {
  1133. for (access_cmd.access_rw.length = 1;
  1134. access_cmd.access_rw.length < sizeof(tmp);
  1135. access_cmd.access_rw.length++) {
  1136. access_cmd.access_rw.flags = def_flags;
  1137. ASSERT_EQ(0, ioctl(fd,
  1138. _IOMMU_TEST_CMD(
  1139. IOMMU_TEST_OP_ACCESS_RW),
  1140. &access_cmd));
  1141. ASSERT_EQ(0,
  1142. memcmp(buffer + (access_cmd.access_rw.iova -
  1143. iova),
  1144. tmp, access_cmd.access_rw.length));
  1145. for (i = 0; i != ARRAY_SIZE(tmp); i++)
  1146. tmp[i] = rand();
  1147. access_cmd.access_rw.flags = def_flags |
  1148. MOCK_ACCESS_RW_WRITE;
  1149. ASSERT_EQ(0, ioctl(fd,
  1150. _IOMMU_TEST_CMD(
  1151. IOMMU_TEST_OP_ACCESS_RW),
  1152. &access_cmd));
  1153. ASSERT_EQ(0,
  1154. memcmp(buffer + (access_cmd.access_rw.iova -
  1155. iova),
  1156. tmp, access_cmd.access_rw.length));
  1157. }
  1158. }
  1159. /* Multi-page test */
  1160. tmp2 = malloc(BUFFER_SIZE);
  1161. ASSERT_NE(NULL, tmp2);
  1162. access_cmd.access_rw.iova = iova;
  1163. access_cmd.access_rw.length = BUFFER_SIZE;
  1164. access_cmd.access_rw.flags = def_flags;
  1165. access_cmd.access_rw.uptr = (uintptr_t)tmp2;
  1166. ASSERT_EQ(0, ioctl(fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_RW),
  1167. &access_cmd));
  1168. ASSERT_EQ(0, memcmp(buffer, tmp2, access_cmd.access_rw.length));
  1169. free(tmp2);
  1170. }
  1171. TEST_F(iommufd_ioas, access_rw)
  1172. {
  1173. __u32 access_id;
  1174. __u64 iova;
  1175. test_cmd_create_access(self->ioas_id, &access_id, 0);
  1176. test_ioctl_ioas_map(buffer, BUFFER_SIZE, &iova);
  1177. check_access_rw(_metadata, self->fd, access_id, iova, 0);
  1178. check_access_rw(_metadata, self->fd, access_id, iova,
  1179. MOCK_ACCESS_RW_SLOW_PATH);
  1180. test_ioctl_ioas_unmap(iova, BUFFER_SIZE);
  1181. test_cmd_destroy_access(access_id);
  1182. }
  1183. TEST_F(iommufd_ioas, access_rw_unaligned)
  1184. {
  1185. __u32 access_id;
  1186. __u64 iova;
  1187. test_cmd_create_access(self->ioas_id, &access_id, 0);
  1188. /* Unaligned pages */
  1189. iova = self->base_iova + MOCK_PAGE_SIZE;
  1190. test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE, iova);
  1191. check_access_rw(_metadata, self->fd, access_id, iova, 0);
  1192. test_ioctl_ioas_unmap(iova, BUFFER_SIZE);
  1193. test_cmd_destroy_access(access_id);
  1194. }
  1195. TEST_F(iommufd_ioas, fork_gone)
  1196. {
  1197. __u32 access_id;
  1198. pid_t child;
  1199. test_cmd_create_access(self->ioas_id, &access_id, 0);
  1200. /* Create a mapping with a different mm */
  1201. child = fork();
  1202. if (!child) {
  1203. test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE,
  1204. MOCK_APERTURE_START);
  1205. exit(0);
  1206. }
  1207. ASSERT_NE(-1, child);
  1208. ASSERT_EQ(child, waitpid(child, NULL, 0));
  1209. if (self->stdev_id) {
  1210. /*
  1211. * If a domain already existed then everything was pinned within
  1212. * the fork, so this copies from one domain to another.
  1213. */
  1214. test_cmd_mock_domain(self->ioas_id, NULL, NULL, NULL);
  1215. check_access_rw(_metadata, self->fd, access_id,
  1216. MOCK_APERTURE_START, 0);
  1217. } else {
  1218. /*
  1219. * Otherwise we need to actually pin pages which can't happen
  1220. * since the fork is gone.
  1221. */
  1222. test_err_mock_domain(EFAULT, self->ioas_id, NULL, NULL);
  1223. }
  1224. test_cmd_destroy_access(access_id);
  1225. }
  1226. TEST_F(iommufd_ioas, fork_present)
  1227. {
  1228. __u32 access_id;
  1229. int pipefds[2];
  1230. uint64_t tmp;
  1231. pid_t child;
  1232. int efd;
  1233. test_cmd_create_access(self->ioas_id, &access_id, 0);
  1234. ASSERT_EQ(0, pipe2(pipefds, O_CLOEXEC));
  1235. efd = eventfd(0, EFD_CLOEXEC);
  1236. ASSERT_NE(-1, efd);
  1237. /* Create a mapping with a different mm */
  1238. child = fork();
  1239. if (!child) {
  1240. __u64 iova;
  1241. uint64_t one = 1;
  1242. close(pipefds[1]);
  1243. test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE,
  1244. MOCK_APERTURE_START);
  1245. if (write(efd, &one, sizeof(one)) != sizeof(one))
  1246. exit(100);
  1247. if (read(pipefds[0], &iova, 1) != 1)
  1248. exit(100);
  1249. exit(0);
  1250. }
  1251. close(pipefds[0]);
  1252. ASSERT_NE(-1, child);
  1253. ASSERT_EQ(8, read(efd, &tmp, sizeof(tmp)));
  1254. /* Read pages from the remote process */
  1255. test_cmd_mock_domain(self->ioas_id, NULL, NULL, NULL);
  1256. check_access_rw(_metadata, self->fd, access_id, MOCK_APERTURE_START, 0);
  1257. ASSERT_EQ(0, close(pipefds[1]));
  1258. ASSERT_EQ(child, waitpid(child, NULL, 0));
  1259. test_cmd_destroy_access(access_id);
  1260. }
  1261. TEST_F(iommufd_ioas, ioas_option_huge_pages)
  1262. {
  1263. struct iommu_option cmd = {
  1264. .size = sizeof(cmd),
  1265. .option_id = IOMMU_OPTION_HUGE_PAGES,
  1266. .op = IOMMU_OPTION_OP_GET,
  1267. .val64 = 3,
  1268. .object_id = self->ioas_id,
  1269. };
  1270. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1271. ASSERT_EQ(1, cmd.val64);
  1272. cmd.op = IOMMU_OPTION_OP_SET;
  1273. cmd.val64 = 0;
  1274. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1275. cmd.op = IOMMU_OPTION_OP_GET;
  1276. cmd.val64 = 3;
  1277. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1278. ASSERT_EQ(0, cmd.val64);
  1279. cmd.op = IOMMU_OPTION_OP_SET;
  1280. cmd.val64 = 2;
  1281. EXPECT_ERRNO(EINVAL, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1282. cmd.op = IOMMU_OPTION_OP_SET;
  1283. cmd.val64 = 1;
  1284. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1285. }
  1286. TEST_F(iommufd_ioas, ioas_iova_alloc)
  1287. {
  1288. unsigned int length;
  1289. __u64 iova;
  1290. for (length = 1; length != PAGE_SIZE * 2; length++) {
  1291. if (variant->mock_domains && (length % MOCK_PAGE_SIZE)) {
  1292. test_err_ioctl_ioas_map(EINVAL, buffer, length, &iova);
  1293. } else {
  1294. test_ioctl_ioas_map(buffer, length, &iova);
  1295. test_ioctl_ioas_unmap(iova, length);
  1296. }
  1297. }
  1298. }
  1299. TEST_F(iommufd_ioas, ioas_align_change)
  1300. {
  1301. struct iommu_option cmd = {
  1302. .size = sizeof(cmd),
  1303. .option_id = IOMMU_OPTION_HUGE_PAGES,
  1304. .op = IOMMU_OPTION_OP_SET,
  1305. .object_id = self->ioas_id,
  1306. /* 0 means everything must be aligned to PAGE_SIZE */
  1307. .val64 = 0,
  1308. };
  1309. /*
  1310. * We cannot upgrade the alignment using OPTION_HUGE_PAGES when a domain
  1311. * and map are present.
  1312. */
  1313. if (variant->mock_domains)
  1314. return;
  1315. /*
  1316. * We can upgrade to PAGE_SIZE alignment when things are aligned right
  1317. */
  1318. test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE, MOCK_APERTURE_START);
  1319. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1320. /* Misalignment is rejected at map time */
  1321. test_err_ioctl_ioas_map_fixed(EINVAL, buffer + MOCK_PAGE_SIZE,
  1322. PAGE_SIZE,
  1323. MOCK_APERTURE_START + PAGE_SIZE);
  1324. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1325. /* Reduce alignment */
  1326. cmd.val64 = 1;
  1327. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1328. /* Confirm misalignment is rejected during alignment upgrade */
  1329. test_ioctl_ioas_map_fixed(buffer + MOCK_PAGE_SIZE, PAGE_SIZE,
  1330. MOCK_APERTURE_START + PAGE_SIZE);
  1331. cmd.val64 = 0;
  1332. EXPECT_ERRNO(EADDRINUSE, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1333. test_ioctl_ioas_unmap(MOCK_APERTURE_START + PAGE_SIZE, PAGE_SIZE);
  1334. test_ioctl_ioas_unmap(MOCK_APERTURE_START, PAGE_SIZE);
  1335. }
  1336. TEST_F(iommufd_ioas, copy_sweep)
  1337. {
  1338. struct iommu_ioas_copy copy_cmd = {
  1339. .size = sizeof(copy_cmd),
  1340. .flags = IOMMU_IOAS_MAP_FIXED_IOVA | IOMMU_IOAS_MAP_WRITEABLE,
  1341. .src_ioas_id = self->ioas_id,
  1342. .dst_iova = MOCK_APERTURE_START,
  1343. .length = MOCK_PAGE_SIZE,
  1344. };
  1345. unsigned int dst_ioas_id;
  1346. uint64_t last_iova;
  1347. uint64_t iova;
  1348. test_ioctl_ioas_alloc(&dst_ioas_id);
  1349. copy_cmd.dst_ioas_id = dst_ioas_id;
  1350. if (variant->mock_domains)
  1351. last_iova = MOCK_APERTURE_START + BUFFER_SIZE - 1;
  1352. else
  1353. last_iova = MOCK_APERTURE_START + BUFFER_SIZE - 2;
  1354. test_ioctl_ioas_map_fixed(buffer, last_iova - MOCK_APERTURE_START + 1,
  1355. MOCK_APERTURE_START);
  1356. for (iova = MOCK_APERTURE_START - PAGE_SIZE; iova <= last_iova;
  1357. iova += 511) {
  1358. copy_cmd.src_iova = iova;
  1359. if (iova < MOCK_APERTURE_START ||
  1360. iova + copy_cmd.length - 1 > last_iova) {
  1361. EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_IOAS_COPY,
  1362. &copy_cmd));
  1363. } else {
  1364. ASSERT_EQ(0,
  1365. ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
  1366. test_ioctl_ioas_unmap_id(dst_ioas_id, copy_cmd.dst_iova,
  1367. copy_cmd.length);
  1368. }
  1369. }
  1370. test_ioctl_destroy(dst_ioas_id);
  1371. }
  1372. TEST_F(iommufd_ioas, dmabuf_simple)
  1373. {
  1374. size_t buf_size = PAGE_SIZE*4;
  1375. __u64 iova;
  1376. int dfd;
  1377. test_cmd_get_dmabuf(buf_size, &dfd);
  1378. test_err_ioctl_ioas_map_file(EINVAL, dfd, 0, 0, &iova);
  1379. test_err_ioctl_ioas_map_file(EINVAL, dfd, buf_size, buf_size, &iova);
  1380. test_err_ioctl_ioas_map_file(EINVAL, dfd, 0, buf_size + 1, &iova);
  1381. test_ioctl_ioas_map_file(dfd, 0, buf_size, &iova);
  1382. close(dfd);
  1383. }
  1384. TEST_F(iommufd_ioas, dmabuf_revoke)
  1385. {
  1386. size_t buf_size = PAGE_SIZE*4;
  1387. __u32 hwpt_id;
  1388. __u64 iova;
  1389. __u64 iova2;
  1390. int dfd;
  1391. test_cmd_get_dmabuf(buf_size, &dfd);
  1392. test_ioctl_ioas_map_file(dfd, 0, buf_size, &iova);
  1393. test_cmd_revoke_dmabuf(dfd, true);
  1394. if (variant->mock_domains)
  1395. test_cmd_hwpt_alloc(self->device_id, self->ioas_id, 0,
  1396. &hwpt_id);
  1397. test_err_ioctl_ioas_map_file(ENODEV, dfd, 0, buf_size, &iova2);
  1398. test_cmd_revoke_dmabuf(dfd, false);
  1399. test_ioctl_ioas_map_file(dfd, 0, buf_size, &iova2);
  1400. /* Restore the iova back */
  1401. test_ioctl_ioas_unmap(iova, buf_size);
  1402. test_ioctl_ioas_map_fixed_file(dfd, 0, buf_size, iova);
  1403. close(dfd);
  1404. }
  1405. FIXTURE(iommufd_mock_domain)
  1406. {
  1407. int fd;
  1408. uint32_t ioas_id;
  1409. uint32_t hwpt_id;
  1410. uint32_t hwpt_ids[2];
  1411. uint32_t stdev_ids[2];
  1412. uint32_t idev_ids[2];
  1413. int mmap_flags;
  1414. size_t mmap_buf_size;
  1415. };
  1416. FIXTURE_VARIANT(iommufd_mock_domain)
  1417. {
  1418. unsigned int mock_domains;
  1419. bool hugepages;
  1420. bool file;
  1421. };
  1422. FIXTURE_SETUP(iommufd_mock_domain)
  1423. {
  1424. unsigned int i;
  1425. self->fd = open("/dev/iommu", O_RDWR);
  1426. ASSERT_NE(-1, self->fd);
  1427. test_ioctl_ioas_alloc(&self->ioas_id);
  1428. ASSERT_GE(ARRAY_SIZE(self->hwpt_ids), variant->mock_domains);
  1429. for (i = 0; i != variant->mock_domains; i++) {
  1430. test_cmd_mock_domain(self->ioas_id, &self->stdev_ids[i],
  1431. &self->hwpt_ids[i], &self->idev_ids[i]);
  1432. test_cmd_dev_check_cache_all(self->idev_ids[0],
  1433. IOMMU_TEST_DEV_CACHE_DEFAULT);
  1434. }
  1435. self->hwpt_id = self->hwpt_ids[0];
  1436. self->mmap_flags = MAP_SHARED | MAP_ANONYMOUS;
  1437. self->mmap_buf_size = PAGE_SIZE * 8;
  1438. if (variant->hugepages) {
  1439. /*
  1440. * MAP_POPULATE will cause the kernel to fail mmap if THPs are
  1441. * not available.
  1442. */
  1443. self->mmap_flags |= MAP_HUGETLB | MAP_POPULATE;
  1444. self->mmap_buf_size = HUGEPAGE_SIZE * 2;
  1445. }
  1446. }
  1447. FIXTURE_TEARDOWN(iommufd_mock_domain)
  1448. {
  1449. teardown_iommufd(self->fd, _metadata);
  1450. }
  1451. FIXTURE_VARIANT_ADD(iommufd_mock_domain, one_domain)
  1452. {
  1453. .mock_domains = 1,
  1454. .hugepages = false,
  1455. .file = false,
  1456. };
  1457. FIXTURE_VARIANT_ADD(iommufd_mock_domain, two_domains)
  1458. {
  1459. .mock_domains = 2,
  1460. .hugepages = false,
  1461. .file = false,
  1462. };
  1463. FIXTURE_VARIANT_ADD(iommufd_mock_domain, one_domain_hugepage)
  1464. {
  1465. .mock_domains = 1,
  1466. .hugepages = true,
  1467. .file = false,
  1468. };
  1469. FIXTURE_VARIANT_ADD(iommufd_mock_domain, two_domains_hugepage)
  1470. {
  1471. .mock_domains = 2,
  1472. .hugepages = true,
  1473. .file = false,
  1474. };
  1475. FIXTURE_VARIANT_ADD(iommufd_mock_domain, one_domain_file)
  1476. {
  1477. .mock_domains = 1,
  1478. .hugepages = false,
  1479. .file = true,
  1480. };
  1481. FIXTURE_VARIANT_ADD(iommufd_mock_domain, one_domain_file_hugepage)
  1482. {
  1483. .mock_domains = 1,
  1484. .hugepages = true,
  1485. .file = true,
  1486. };
  1487. /* Have the kernel check that the user pages made it to the iommu_domain */
  1488. #define check_mock_iova(_ptr, _iova, _length) \
  1489. ({ \
  1490. struct iommu_test_cmd check_map_cmd = { \
  1491. .size = sizeof(check_map_cmd), \
  1492. .op = IOMMU_TEST_OP_MD_CHECK_MAP, \
  1493. .id = self->hwpt_id, \
  1494. .check_map = { .iova = _iova, \
  1495. .length = _length, \
  1496. .uptr = (uintptr_t)(_ptr) }, \
  1497. }; \
  1498. ASSERT_EQ(0, \
  1499. ioctl(self->fd, \
  1500. _IOMMU_TEST_CMD(IOMMU_TEST_OP_MD_CHECK_MAP), \
  1501. &check_map_cmd)); \
  1502. if (self->hwpt_ids[1]) { \
  1503. check_map_cmd.id = self->hwpt_ids[1]; \
  1504. ASSERT_EQ(0, \
  1505. ioctl(self->fd, \
  1506. _IOMMU_TEST_CMD( \
  1507. IOMMU_TEST_OP_MD_CHECK_MAP), \
  1508. &check_map_cmd)); \
  1509. } \
  1510. })
  1511. static void
  1512. test_basic_mmap(struct __test_metadata *_metadata,
  1513. struct _test_data_iommufd_mock_domain *self,
  1514. const struct _fixture_variant_iommufd_mock_domain *variant)
  1515. {
  1516. size_t buf_size = self->mmap_buf_size;
  1517. uint8_t *buf;
  1518. __u64 iova;
  1519. /* Simple one page map */
  1520. test_ioctl_ioas_map(buffer, PAGE_SIZE, &iova);
  1521. check_mock_iova(buffer, iova, PAGE_SIZE);
  1522. buf = mmap(0, buf_size, PROT_READ | PROT_WRITE, self->mmap_flags, -1,
  1523. 0);
  1524. ASSERT_NE(MAP_FAILED, buf);
  1525. /* EFAULT half way through mapping */
  1526. ASSERT_EQ(0, munmap(buf + buf_size / 2, buf_size / 2));
  1527. test_err_ioctl_ioas_map(EFAULT, buf, buf_size, &iova);
  1528. /* EFAULT on first page */
  1529. ASSERT_EQ(0, munmap(buf, buf_size / 2));
  1530. test_err_ioctl_ioas_map(EFAULT, buf, buf_size, &iova);
  1531. }
  1532. static void
  1533. test_basic_file(struct __test_metadata *_metadata,
  1534. struct _test_data_iommufd_mock_domain *self,
  1535. const struct _fixture_variant_iommufd_mock_domain *variant)
  1536. {
  1537. size_t buf_size = self->mmap_buf_size;
  1538. uint8_t *buf;
  1539. __u64 iova;
  1540. int mfd_tmp;
  1541. int prot = PROT_READ | PROT_WRITE;
  1542. /* Simple one page map */
  1543. test_ioctl_ioas_map_file(mfd, 0, PAGE_SIZE, &iova);
  1544. check_mock_iova(mfd_buffer, iova, PAGE_SIZE);
  1545. buf = memfd_mmap(buf_size, prot, MAP_SHARED, &mfd_tmp);
  1546. ASSERT_NE(MAP_FAILED, buf);
  1547. test_err_ioctl_ioas_map_file(EINVAL, mfd_tmp, 0, buf_size + 1, &iova);
  1548. ASSERT_EQ(0, ftruncate(mfd_tmp, 0));
  1549. test_err_ioctl_ioas_map_file(EINVAL, mfd_tmp, 0, buf_size, &iova);
  1550. close(mfd_tmp);
  1551. }
  1552. TEST_F(iommufd_mock_domain, basic)
  1553. {
  1554. if (variant->file)
  1555. test_basic_file(_metadata, self, variant);
  1556. else
  1557. test_basic_mmap(_metadata, self, variant);
  1558. }
  1559. TEST_F(iommufd_mock_domain, ro_unshare)
  1560. {
  1561. uint8_t *buf;
  1562. __u64 iova;
  1563. int fd;
  1564. fd = open("/proc/self/exe", O_RDONLY);
  1565. ASSERT_NE(-1, fd);
  1566. buf = mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
  1567. ASSERT_NE(MAP_FAILED, buf);
  1568. close(fd);
  1569. /*
  1570. * There have been lots of changes to the "unshare" mechanism in
  1571. * get_user_pages(), make sure it works right. The write to the page
  1572. * after we map it for reading should not change the assigned PFN.
  1573. */
  1574. ASSERT_EQ(0,
  1575. _test_ioctl_ioas_map(self->fd, self->ioas_id, buf, PAGE_SIZE,
  1576. &iova, IOMMU_IOAS_MAP_READABLE));
  1577. check_mock_iova(buf, iova, PAGE_SIZE);
  1578. memset(buf, 1, PAGE_SIZE);
  1579. check_mock_iova(buf, iova, PAGE_SIZE);
  1580. ASSERT_EQ(0, munmap(buf, PAGE_SIZE));
  1581. }
  1582. TEST_F(iommufd_mock_domain, all_aligns)
  1583. {
  1584. size_t test_step = variant->hugepages ? (self->mmap_buf_size / 16) :
  1585. MOCK_PAGE_SIZE;
  1586. size_t buf_size = self->mmap_buf_size;
  1587. unsigned int start;
  1588. unsigned int end;
  1589. uint8_t *buf;
  1590. int prot = PROT_READ | PROT_WRITE;
  1591. int mfd = -1;
  1592. if (variant->file)
  1593. buf = memfd_mmap(buf_size, prot, MAP_SHARED, &mfd);
  1594. else
  1595. buf = mmap(0, buf_size, prot, self->mmap_flags, -1, 0);
  1596. ASSERT_NE(MAP_FAILED, buf);
  1597. if (variant->file)
  1598. ASSERT_GT(mfd, 0);
  1599. check_refs(buf, buf_size, 0);
  1600. /*
  1601. * Map every combination of page size and alignment within a big region,
  1602. * less for hugepage case as it takes so long to finish.
  1603. */
  1604. for (start = 0; start < buf_size; start += test_step) {
  1605. if (variant->hugepages)
  1606. end = buf_size;
  1607. else
  1608. end = start + MOCK_PAGE_SIZE;
  1609. for (; end < buf_size; end += MOCK_PAGE_SIZE) {
  1610. size_t length = end - start;
  1611. __u64 iova;
  1612. if (variant->file) {
  1613. test_ioctl_ioas_map_file(mfd, start, length,
  1614. &iova);
  1615. } else {
  1616. test_ioctl_ioas_map(buf + start, length, &iova);
  1617. }
  1618. check_mock_iova(buf + start, iova, length);
  1619. check_refs(buf + start / PAGE_SIZE * PAGE_SIZE,
  1620. end / PAGE_SIZE * PAGE_SIZE -
  1621. start / PAGE_SIZE * PAGE_SIZE,
  1622. 1);
  1623. test_ioctl_ioas_unmap(iova, length);
  1624. }
  1625. }
  1626. check_refs(buf, buf_size, 0);
  1627. ASSERT_EQ(0, munmap(buf, buf_size));
  1628. if (variant->file)
  1629. close(mfd);
  1630. }
  1631. TEST_F(iommufd_mock_domain, all_aligns_copy)
  1632. {
  1633. size_t test_step = variant->hugepages ? self->mmap_buf_size / 16 :
  1634. MOCK_PAGE_SIZE;
  1635. size_t buf_size = self->mmap_buf_size;
  1636. unsigned int start;
  1637. unsigned int end;
  1638. uint8_t *buf;
  1639. int prot = PROT_READ | PROT_WRITE;
  1640. int mfd = -1;
  1641. if (variant->file)
  1642. buf = memfd_mmap(buf_size, prot, MAP_SHARED, &mfd);
  1643. else
  1644. buf = mmap(0, buf_size, prot, self->mmap_flags, -1, 0);
  1645. ASSERT_NE(MAP_FAILED, buf);
  1646. if (variant->file)
  1647. ASSERT_GT(mfd, 0);
  1648. check_refs(buf, buf_size, 0);
  1649. /*
  1650. * Map every combination of page size and alignment within a big region,
  1651. * less for hugepage case as it takes so long to finish.
  1652. */
  1653. for (start = 0; start < buf_size; start += test_step) {
  1654. if (variant->hugepages)
  1655. end = buf_size;
  1656. else
  1657. end = start + MOCK_PAGE_SIZE;
  1658. for (; end < buf_size; end += MOCK_PAGE_SIZE) {
  1659. size_t length = end - start;
  1660. unsigned int old_id;
  1661. uint32_t mock_stdev_id;
  1662. __u64 iova;
  1663. if (variant->file) {
  1664. test_ioctl_ioas_map_file(mfd, start, length,
  1665. &iova);
  1666. } else {
  1667. test_ioctl_ioas_map(buf + start, length, &iova);
  1668. }
  1669. /* Add and destroy a domain while the area exists */
  1670. old_id = self->hwpt_ids[1];
  1671. test_cmd_mock_domain(self->ioas_id, &mock_stdev_id,
  1672. &self->hwpt_ids[1], NULL);
  1673. check_mock_iova(buf + start, iova, length);
  1674. check_refs(buf + start / PAGE_SIZE * PAGE_SIZE,
  1675. end / PAGE_SIZE * PAGE_SIZE -
  1676. start / PAGE_SIZE * PAGE_SIZE,
  1677. 1);
  1678. test_ioctl_destroy(mock_stdev_id);
  1679. self->hwpt_ids[1] = old_id;
  1680. test_ioctl_ioas_unmap(iova, length);
  1681. }
  1682. }
  1683. check_refs(buf, buf_size, 0);
  1684. ASSERT_EQ(0, munmap(buf, buf_size));
  1685. if (variant->file)
  1686. close(mfd);
  1687. }
  1688. TEST_F(iommufd_mock_domain, user_copy)
  1689. {
  1690. void *buf = variant->file ? mfd_buffer : buffer;
  1691. struct iommu_test_cmd access_cmd = {
  1692. .size = sizeof(access_cmd),
  1693. .op = IOMMU_TEST_OP_ACCESS_PAGES,
  1694. .access_pages = { .length = BUFFER_SIZE,
  1695. .uptr = (uintptr_t)buf },
  1696. };
  1697. struct iommu_ioas_copy copy_cmd = {
  1698. .size = sizeof(copy_cmd),
  1699. .flags = IOMMU_IOAS_MAP_FIXED_IOVA | IOMMU_IOAS_MAP_WRITEABLE,
  1700. .dst_ioas_id = self->ioas_id,
  1701. .dst_iova = MOCK_APERTURE_START,
  1702. .length = BUFFER_SIZE,
  1703. };
  1704. struct iommu_ioas_unmap unmap_cmd = {
  1705. .size = sizeof(unmap_cmd),
  1706. .ioas_id = self->ioas_id,
  1707. .iova = MOCK_APERTURE_START,
  1708. .length = BUFFER_SIZE,
  1709. };
  1710. unsigned int new_ioas_id, ioas_id;
  1711. /* Pin the pages in an IOAS with no domains then copy to an IOAS with domains */
  1712. test_ioctl_ioas_alloc(&ioas_id);
  1713. if (variant->file) {
  1714. test_ioctl_ioas_map_id_file(ioas_id, mfd, 0, BUFFER_SIZE,
  1715. &copy_cmd.src_iova);
  1716. } else {
  1717. test_ioctl_ioas_map_id(ioas_id, buf, BUFFER_SIZE,
  1718. &copy_cmd.src_iova);
  1719. }
  1720. test_cmd_create_access(ioas_id, &access_cmd.id,
  1721. MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES);
  1722. access_cmd.access_pages.iova = copy_cmd.src_iova;
  1723. ASSERT_EQ(0,
  1724. ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
  1725. &access_cmd));
  1726. copy_cmd.src_ioas_id = ioas_id;
  1727. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
  1728. check_mock_iova(buf, MOCK_APERTURE_START, BUFFER_SIZE);
  1729. /* Now replace the ioas with a new one */
  1730. test_ioctl_ioas_alloc(&new_ioas_id);
  1731. if (variant->file) {
  1732. test_ioctl_ioas_map_id_file(new_ioas_id, mfd, 0, BUFFER_SIZE,
  1733. &copy_cmd.src_iova);
  1734. } else {
  1735. test_ioctl_ioas_map_id(new_ioas_id, buf, BUFFER_SIZE,
  1736. &copy_cmd.src_iova);
  1737. }
  1738. test_cmd_access_replace_ioas(access_cmd.id, new_ioas_id);
  1739. /* Destroy the old ioas and cleanup copied mapping */
  1740. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_UNMAP, &unmap_cmd));
  1741. test_ioctl_destroy(ioas_id);
  1742. /* Then run the same test again with the new ioas */
  1743. access_cmd.access_pages.iova = copy_cmd.src_iova;
  1744. ASSERT_EQ(0,
  1745. ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
  1746. &access_cmd));
  1747. copy_cmd.src_ioas_id = new_ioas_id;
  1748. ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
  1749. check_mock_iova(buf, MOCK_APERTURE_START, BUFFER_SIZE);
  1750. test_cmd_destroy_access_pages(
  1751. access_cmd.id, access_cmd.access_pages.out_access_pages_id);
  1752. test_cmd_destroy_access(access_cmd.id);
  1753. test_ioctl_destroy(new_ioas_id);
  1754. }
  1755. TEST_F(iommufd_mock_domain, replace)
  1756. {
  1757. uint32_t ioas_id;
  1758. test_ioctl_ioas_alloc(&ioas_id);
  1759. test_cmd_mock_domain_replace(self->stdev_ids[0], ioas_id);
  1760. /*
  1761. * Replacing the IOAS causes the prior HWPT to be deallocated, thus we
  1762. * should get enoent when we try to use it.
  1763. */
  1764. if (variant->mock_domains == 1)
  1765. test_err_mock_domain_replace(ENOENT, self->stdev_ids[0],
  1766. self->hwpt_ids[0]);
  1767. test_cmd_mock_domain_replace(self->stdev_ids[0], ioas_id);
  1768. if (variant->mock_domains >= 2) {
  1769. test_cmd_mock_domain_replace(self->stdev_ids[0],
  1770. self->hwpt_ids[1]);
  1771. test_cmd_mock_domain_replace(self->stdev_ids[0],
  1772. self->hwpt_ids[1]);
  1773. test_cmd_mock_domain_replace(self->stdev_ids[0],
  1774. self->hwpt_ids[0]);
  1775. }
  1776. test_cmd_mock_domain_replace(self->stdev_ids[0], self->ioas_id);
  1777. test_ioctl_destroy(ioas_id);
  1778. }
  1779. TEST_F(iommufd_mock_domain, alloc_hwpt)
  1780. {
  1781. int i;
  1782. for (i = 0; i != variant->mock_domains; i++) {
  1783. uint32_t hwpt_id[2];
  1784. uint32_t stddev_id;
  1785. test_err_hwpt_alloc(EOPNOTSUPP,
  1786. self->idev_ids[i], self->ioas_id,
  1787. ~IOMMU_HWPT_ALLOC_NEST_PARENT, &hwpt_id[0]);
  1788. test_cmd_hwpt_alloc(self->idev_ids[i], self->ioas_id,
  1789. 0, &hwpt_id[0]);
  1790. test_cmd_hwpt_alloc(self->idev_ids[i], self->ioas_id,
  1791. IOMMU_HWPT_ALLOC_NEST_PARENT, &hwpt_id[1]);
  1792. /* Do a hw_pagetable rotation test */
  1793. test_cmd_mock_domain_replace(self->stdev_ids[i], hwpt_id[0]);
  1794. EXPECT_ERRNO(EBUSY, _test_ioctl_destroy(self->fd, hwpt_id[0]));
  1795. test_cmd_mock_domain_replace(self->stdev_ids[i], hwpt_id[1]);
  1796. EXPECT_ERRNO(EBUSY, _test_ioctl_destroy(self->fd, hwpt_id[1]));
  1797. test_cmd_mock_domain_replace(self->stdev_ids[i], self->ioas_id);
  1798. test_ioctl_destroy(hwpt_id[1]);
  1799. test_cmd_mock_domain(hwpt_id[0], &stddev_id, NULL, NULL);
  1800. test_ioctl_destroy(stddev_id);
  1801. test_ioctl_destroy(hwpt_id[0]);
  1802. }
  1803. }
  1804. FIXTURE(iommufd_dirty_tracking)
  1805. {
  1806. int fd;
  1807. uint32_t ioas_id;
  1808. uint32_t hwpt_id;
  1809. uint32_t stdev_id;
  1810. uint32_t idev_id;
  1811. unsigned long page_size;
  1812. unsigned long bitmap_size;
  1813. void *bitmap;
  1814. void *buffer;
  1815. };
  1816. FIXTURE_VARIANT(iommufd_dirty_tracking)
  1817. {
  1818. unsigned long buffer_size;
  1819. bool hugepages;
  1820. };
  1821. FIXTURE_SETUP(iommufd_dirty_tracking)
  1822. {
  1823. struct iommu_option cmd = {
  1824. .size = sizeof(cmd),
  1825. .option_id = IOMMU_OPTION_HUGE_PAGES,
  1826. .op = IOMMU_OPTION_OP_SET,
  1827. .val64 = 0,
  1828. };
  1829. size_t mmap_buffer_size;
  1830. unsigned long size;
  1831. int mmap_flags;
  1832. void *vrc;
  1833. int rc;
  1834. if (variant->buffer_size < MOCK_PAGE_SIZE) {
  1835. SKIP(return,
  1836. "Skipping buffer_size=%lu, less than MOCK_PAGE_SIZE=%u",
  1837. variant->buffer_size, MOCK_PAGE_SIZE);
  1838. }
  1839. self->fd = open("/dev/iommu", O_RDWR);
  1840. ASSERT_NE(-1, self->fd);
  1841. mmap_flags = MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED;
  1842. mmap_buffer_size = variant->buffer_size;
  1843. if (variant->hugepages) {
  1844. /*
  1845. * MAP_POPULATE will cause the kernel to fail mmap if THPs are
  1846. * not available.
  1847. */
  1848. mmap_flags |= MAP_HUGETLB | MAP_POPULATE;
  1849. /*
  1850. * Allocation must be aligned to the HUGEPAGE_SIZE, because the
  1851. * following mmap() will automatically align the length to be a
  1852. * multiple of the underlying huge page size. Failing to do the
  1853. * same at this allocation will result in a memory overwrite by
  1854. * the mmap().
  1855. */
  1856. if (mmap_buffer_size < HUGEPAGE_SIZE)
  1857. mmap_buffer_size = HUGEPAGE_SIZE;
  1858. }
  1859. rc = posix_memalign(&self->buffer, HUGEPAGE_SIZE, mmap_buffer_size);
  1860. if (rc || !self->buffer) {
  1861. SKIP(return, "Skipping buffer_size=%lu due to errno=%d",
  1862. mmap_buffer_size, rc);
  1863. }
  1864. assert((uintptr_t)self->buffer % HUGEPAGE_SIZE == 0);
  1865. vrc = mmap(self->buffer, mmap_buffer_size, PROT_READ | PROT_WRITE,
  1866. mmap_flags, -1, 0);
  1867. assert(vrc == self->buffer);
  1868. self->page_size = MOCK_PAGE_SIZE;
  1869. self->bitmap_size = variant->buffer_size / self->page_size;
  1870. /* Provision with an extra (PAGE_SIZE) for the unaligned case */
  1871. size = DIV_ROUND_UP(self->bitmap_size, BITS_PER_BYTE);
  1872. rc = posix_memalign(&self->bitmap, PAGE_SIZE, size + PAGE_SIZE);
  1873. assert(!rc);
  1874. assert(self->bitmap);
  1875. assert((uintptr_t)self->bitmap % PAGE_SIZE == 0);
  1876. test_ioctl_ioas_alloc(&self->ioas_id);
  1877. /*
  1878. * For dirty testing it is important that the page size fed into
  1879. * the iommu page tables matches the size the dirty logic
  1880. * expects, or set_dirty can touch too much stuff.
  1881. */
  1882. cmd.object_id = self->ioas_id;
  1883. if (!variant->hugepages)
  1884. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  1885. test_cmd_mock_domain(self->ioas_id, &self->stdev_id, &self->hwpt_id,
  1886. &self->idev_id);
  1887. }
  1888. FIXTURE_TEARDOWN(iommufd_dirty_tracking)
  1889. {
  1890. free(self->buffer);
  1891. free(self->bitmap);
  1892. teardown_iommufd(self->fd, _metadata);
  1893. }
  1894. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty8k)
  1895. {
  1896. /* half of an u8 index bitmap */
  1897. .buffer_size = 8UL * 1024UL,
  1898. };
  1899. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty16k)
  1900. {
  1901. /* one u8 index bitmap */
  1902. .buffer_size = 16UL * 1024UL,
  1903. };
  1904. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty64k)
  1905. {
  1906. /* one u32 index bitmap */
  1907. .buffer_size = 64UL * 1024UL,
  1908. };
  1909. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty128k)
  1910. {
  1911. /* one u64 index bitmap */
  1912. .buffer_size = 128UL * 1024UL,
  1913. };
  1914. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty320k)
  1915. {
  1916. /* two u64 index and trailing end bitmap */
  1917. .buffer_size = 320UL * 1024UL,
  1918. };
  1919. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty64M)
  1920. {
  1921. /* 4K bitmap (64M IOVA range) */
  1922. .buffer_size = 64UL * 1024UL * 1024UL,
  1923. };
  1924. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty64M_huge)
  1925. {
  1926. /* 4K bitmap (64M IOVA range) */
  1927. .buffer_size = 64UL * 1024UL * 1024UL,
  1928. .hugepages = true,
  1929. };
  1930. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty128M)
  1931. {
  1932. /* 8K bitmap (128M IOVA range) */
  1933. .buffer_size = 128UL * 1024UL * 1024UL,
  1934. };
  1935. FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty128M_huge)
  1936. {
  1937. /* 8K bitmap (128M IOVA range) */
  1938. .buffer_size = 128UL * 1024UL * 1024UL,
  1939. .hugepages = true,
  1940. };
  1941. TEST_F(iommufd_dirty_tracking, enforce_dirty)
  1942. {
  1943. uint32_t ioas_id, stddev_id, idev_id;
  1944. uint32_t hwpt_id, _hwpt_id;
  1945. uint32_t dev_flags;
  1946. /* Regular case */
  1947. dev_flags = MOCK_FLAGS_DEVICE_NO_DIRTY;
  1948. test_cmd_hwpt_alloc(self->idev_id, self->ioas_id,
  1949. IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
  1950. test_cmd_mock_domain(hwpt_id, &stddev_id, NULL, NULL);
  1951. test_err_mock_domain_flags(EINVAL, hwpt_id, dev_flags, &stddev_id,
  1952. NULL);
  1953. test_ioctl_destroy(stddev_id);
  1954. test_ioctl_destroy(hwpt_id);
  1955. /* IOMMU device does not support dirty tracking */
  1956. test_ioctl_ioas_alloc(&ioas_id);
  1957. test_cmd_mock_domain_flags(ioas_id, dev_flags, &stddev_id, &_hwpt_id,
  1958. &idev_id);
  1959. test_err_hwpt_alloc(EOPNOTSUPP, idev_id, ioas_id,
  1960. IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
  1961. test_ioctl_destroy(stddev_id);
  1962. }
  1963. TEST_F(iommufd_dirty_tracking, set_dirty_tracking)
  1964. {
  1965. uint32_t stddev_id;
  1966. uint32_t hwpt_id;
  1967. test_cmd_hwpt_alloc(self->idev_id, self->ioas_id,
  1968. IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
  1969. test_cmd_mock_domain(hwpt_id, &stddev_id, NULL, NULL);
  1970. test_cmd_set_dirty_tracking(hwpt_id, true);
  1971. test_cmd_set_dirty_tracking(hwpt_id, false);
  1972. test_ioctl_destroy(stddev_id);
  1973. test_ioctl_destroy(hwpt_id);
  1974. }
  1975. TEST_F(iommufd_dirty_tracking, device_dirty_capability)
  1976. {
  1977. uint32_t caps = 0;
  1978. uint32_t stddev_id;
  1979. uint32_t hwpt_id;
  1980. test_cmd_hwpt_alloc(self->idev_id, self->ioas_id, 0, &hwpt_id);
  1981. test_cmd_mock_domain(hwpt_id, &stddev_id, NULL, NULL);
  1982. test_cmd_get_hw_capabilities(self->idev_id, caps);
  1983. ASSERT_EQ(IOMMU_HW_CAP_DIRTY_TRACKING,
  1984. caps & IOMMU_HW_CAP_DIRTY_TRACKING);
  1985. test_ioctl_destroy(stddev_id);
  1986. test_ioctl_destroy(hwpt_id);
  1987. }
  1988. TEST_F(iommufd_dirty_tracking, get_dirty_bitmap)
  1989. {
  1990. uint32_t page_size = MOCK_PAGE_SIZE;
  1991. uint32_t ioas_id = self->ioas_id;
  1992. uint32_t hwpt_id;
  1993. if (variant->hugepages)
  1994. page_size = MOCK_HUGE_PAGE_SIZE;
  1995. test_ioctl_ioas_map_fixed_id(ioas_id, self->buffer,
  1996. variant->buffer_size, MOCK_APERTURE_START);
  1997. if (variant->hugepages)
  1998. test_cmd_hwpt_alloc_iommupt(self->idev_id, ioas_id,
  1999. IOMMU_HWPT_ALLOC_DIRTY_TRACKING,
  2000. MOCK_IOMMUPT_HUGE, &hwpt_id);
  2001. else
  2002. test_cmd_hwpt_alloc_iommupt(self->idev_id, ioas_id,
  2003. IOMMU_HWPT_ALLOC_DIRTY_TRACKING,
  2004. MOCK_IOMMUPT_DEFAULT, &hwpt_id);
  2005. test_cmd_set_dirty_tracking(hwpt_id, true);
  2006. test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
  2007. MOCK_APERTURE_START, self->page_size, page_size,
  2008. self->bitmap, self->bitmap_size, 0, _metadata);
  2009. /* PAGE_SIZE unaligned bitmap */
  2010. test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
  2011. MOCK_APERTURE_START, self->page_size, page_size,
  2012. self->bitmap + MOCK_PAGE_SIZE,
  2013. self->bitmap_size, 0, _metadata);
  2014. /* u64 unaligned bitmap */
  2015. test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
  2016. MOCK_APERTURE_START, self->page_size, page_size,
  2017. self->bitmap + 0xff1, self->bitmap_size, 0,
  2018. _metadata);
  2019. test_ioctl_destroy(hwpt_id);
  2020. }
  2021. TEST_F(iommufd_dirty_tracking, get_dirty_bitmap_no_clear)
  2022. {
  2023. uint32_t page_size = MOCK_PAGE_SIZE;
  2024. uint32_t ioas_id = self->ioas_id;
  2025. uint32_t hwpt_id;
  2026. if (variant->hugepages)
  2027. page_size = MOCK_HUGE_PAGE_SIZE;
  2028. test_ioctl_ioas_map_fixed_id(ioas_id, self->buffer,
  2029. variant->buffer_size, MOCK_APERTURE_START);
  2030. if (variant->hugepages)
  2031. test_cmd_hwpt_alloc_iommupt(self->idev_id, ioas_id,
  2032. IOMMU_HWPT_ALLOC_DIRTY_TRACKING,
  2033. MOCK_IOMMUPT_HUGE, &hwpt_id);
  2034. else
  2035. test_cmd_hwpt_alloc_iommupt(self->idev_id, ioas_id,
  2036. IOMMU_HWPT_ALLOC_DIRTY_TRACKING,
  2037. MOCK_IOMMUPT_DEFAULT, &hwpt_id);
  2038. test_cmd_set_dirty_tracking(hwpt_id, true);
  2039. test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
  2040. MOCK_APERTURE_START, self->page_size, page_size,
  2041. self->bitmap, self->bitmap_size,
  2042. IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
  2043. _metadata);
  2044. /* Unaligned bitmap */
  2045. test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
  2046. MOCK_APERTURE_START, self->page_size, page_size,
  2047. self->bitmap + MOCK_PAGE_SIZE,
  2048. self->bitmap_size,
  2049. IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
  2050. _metadata);
  2051. /* u64 unaligned bitmap */
  2052. test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
  2053. MOCK_APERTURE_START, self->page_size, page_size,
  2054. self->bitmap + 0xff1, self->bitmap_size,
  2055. IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
  2056. _metadata);
  2057. test_ioctl_destroy(hwpt_id);
  2058. }
  2059. /* VFIO compatibility IOCTLs */
  2060. TEST_F(iommufd, simple_ioctls)
  2061. {
  2062. ASSERT_EQ(VFIO_API_VERSION, ioctl(self->fd, VFIO_GET_API_VERSION));
  2063. ASSERT_EQ(1, ioctl(self->fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU));
  2064. }
  2065. TEST_F(iommufd, unmap_cmd)
  2066. {
  2067. struct vfio_iommu_type1_dma_unmap unmap_cmd = {
  2068. .iova = MOCK_APERTURE_START,
  2069. .size = PAGE_SIZE,
  2070. };
  2071. unmap_cmd.argsz = 1;
  2072. EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
  2073. unmap_cmd.argsz = sizeof(unmap_cmd);
  2074. unmap_cmd.flags = 1 << 31;
  2075. EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
  2076. unmap_cmd.flags = 0;
  2077. EXPECT_ERRNO(ENODEV, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
  2078. }
  2079. TEST_F(iommufd, map_cmd)
  2080. {
  2081. struct vfio_iommu_type1_dma_map map_cmd = {
  2082. .iova = MOCK_APERTURE_START,
  2083. .size = PAGE_SIZE,
  2084. .vaddr = (__u64)buffer,
  2085. };
  2086. map_cmd.argsz = 1;
  2087. EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
  2088. map_cmd.argsz = sizeof(map_cmd);
  2089. map_cmd.flags = 1 << 31;
  2090. EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
  2091. /* Requires a domain to be attached */
  2092. map_cmd.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE;
  2093. EXPECT_ERRNO(ENODEV, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
  2094. }
  2095. TEST_F(iommufd, info_cmd)
  2096. {
  2097. struct vfio_iommu_type1_info info_cmd = {};
  2098. /* Invalid argsz */
  2099. info_cmd.argsz = 1;
  2100. EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_GET_INFO, &info_cmd));
  2101. info_cmd.argsz = sizeof(info_cmd);
  2102. EXPECT_ERRNO(ENODEV, ioctl(self->fd, VFIO_IOMMU_GET_INFO, &info_cmd));
  2103. }
  2104. TEST_F(iommufd, set_iommu_cmd)
  2105. {
  2106. /* Requires a domain to be attached */
  2107. EXPECT_ERRNO(ENODEV,
  2108. ioctl(self->fd, VFIO_SET_IOMMU, VFIO_TYPE1v2_IOMMU));
  2109. EXPECT_ERRNO(ENODEV, ioctl(self->fd, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU));
  2110. }
  2111. TEST_F(iommufd, vfio_ioas)
  2112. {
  2113. struct iommu_vfio_ioas vfio_ioas_cmd = {
  2114. .size = sizeof(vfio_ioas_cmd),
  2115. .op = IOMMU_VFIO_IOAS_GET,
  2116. };
  2117. __u32 ioas_id;
  2118. /* ENODEV if there is no compat ioas */
  2119. EXPECT_ERRNO(ENODEV, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
  2120. /* Invalid id for set */
  2121. vfio_ioas_cmd.op = IOMMU_VFIO_IOAS_SET;
  2122. EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
  2123. /* Valid id for set*/
  2124. test_ioctl_ioas_alloc(&ioas_id);
  2125. vfio_ioas_cmd.ioas_id = ioas_id;
  2126. ASSERT_EQ(0, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
  2127. /* Same id comes back from get */
  2128. vfio_ioas_cmd.op = IOMMU_VFIO_IOAS_GET;
  2129. ASSERT_EQ(0, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
  2130. ASSERT_EQ(ioas_id, vfio_ioas_cmd.ioas_id);
  2131. /* Clear works */
  2132. vfio_ioas_cmd.op = IOMMU_VFIO_IOAS_CLEAR;
  2133. ASSERT_EQ(0, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
  2134. vfio_ioas_cmd.op = IOMMU_VFIO_IOAS_GET;
  2135. EXPECT_ERRNO(ENODEV, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
  2136. }
  2137. FIXTURE(vfio_compat_mock_domain)
  2138. {
  2139. int fd;
  2140. uint32_t ioas_id;
  2141. };
  2142. FIXTURE_VARIANT(vfio_compat_mock_domain)
  2143. {
  2144. unsigned int version;
  2145. };
  2146. FIXTURE_SETUP(vfio_compat_mock_domain)
  2147. {
  2148. struct iommu_vfio_ioas vfio_ioas_cmd = {
  2149. .size = sizeof(vfio_ioas_cmd),
  2150. .op = IOMMU_VFIO_IOAS_SET,
  2151. };
  2152. self->fd = open("/dev/iommu", O_RDWR);
  2153. ASSERT_NE(-1, self->fd);
  2154. /* Create what VFIO would consider a group */
  2155. test_ioctl_ioas_alloc(&self->ioas_id);
  2156. test_cmd_mock_domain(self->ioas_id, NULL, NULL, NULL);
  2157. /* Attach it to the vfio compat */
  2158. vfio_ioas_cmd.ioas_id = self->ioas_id;
  2159. ASSERT_EQ(0, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
  2160. ASSERT_EQ(0, ioctl(self->fd, VFIO_SET_IOMMU, variant->version));
  2161. }
  2162. FIXTURE_TEARDOWN(vfio_compat_mock_domain)
  2163. {
  2164. teardown_iommufd(self->fd, _metadata);
  2165. }
  2166. FIXTURE_VARIANT_ADD(vfio_compat_mock_domain, Ver1v2)
  2167. {
  2168. .version = VFIO_TYPE1v2_IOMMU,
  2169. };
  2170. FIXTURE_VARIANT_ADD(vfio_compat_mock_domain, Ver1v0)
  2171. {
  2172. .version = VFIO_TYPE1_IOMMU,
  2173. };
  2174. TEST_F(vfio_compat_mock_domain, simple_close)
  2175. {
  2176. }
  2177. TEST_F(vfio_compat_mock_domain, option_huge_pages)
  2178. {
  2179. struct iommu_option cmd = {
  2180. .size = sizeof(cmd),
  2181. .option_id = IOMMU_OPTION_HUGE_PAGES,
  2182. .op = IOMMU_OPTION_OP_GET,
  2183. .val64 = 3,
  2184. .object_id = self->ioas_id,
  2185. };
  2186. ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
  2187. if (variant->version == VFIO_TYPE1_IOMMU) {
  2188. ASSERT_EQ(0, cmd.val64);
  2189. } else {
  2190. ASSERT_EQ(1, cmd.val64);
  2191. }
  2192. }
  2193. /*
  2194. * Execute an ioctl command stored in buffer and check that the result does not
  2195. * overflow memory.
  2196. */
  2197. static bool is_filled(const void *buf, uint8_t c, size_t len)
  2198. {
  2199. const uint8_t *cbuf = buf;
  2200. for (; len; cbuf++, len--)
  2201. if (*cbuf != c)
  2202. return false;
  2203. return true;
  2204. }
  2205. #define ioctl_check_buf(fd, cmd) \
  2206. ({ \
  2207. size_t _cmd_len = *(__u32 *)buffer; \
  2208. \
  2209. memset(buffer + _cmd_len, 0xAA, BUFFER_SIZE - _cmd_len); \
  2210. ASSERT_EQ(0, ioctl(fd, cmd, buffer)); \
  2211. ASSERT_EQ(true, is_filled(buffer + _cmd_len, 0xAA, \
  2212. BUFFER_SIZE - _cmd_len)); \
  2213. })
  2214. static void check_vfio_info_cap_chain(struct __test_metadata *_metadata,
  2215. struct vfio_iommu_type1_info *info_cmd)
  2216. {
  2217. const struct vfio_info_cap_header *cap;
  2218. ASSERT_GE(info_cmd->argsz, info_cmd->cap_offset + sizeof(*cap));
  2219. cap = buffer + info_cmd->cap_offset;
  2220. while (true) {
  2221. size_t cap_size;
  2222. if (cap->next)
  2223. cap_size = (buffer + cap->next) - (void *)cap;
  2224. else
  2225. cap_size = (buffer + info_cmd->argsz) - (void *)cap;
  2226. switch (cap->id) {
  2227. case VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE: {
  2228. struct vfio_iommu_type1_info_cap_iova_range *data =
  2229. (void *)cap;
  2230. ASSERT_EQ(1, data->header.version);
  2231. ASSERT_EQ(1, data->nr_iovas);
  2232. EXPECT_EQ(MOCK_APERTURE_START,
  2233. data->iova_ranges[0].start);
  2234. EXPECT_EQ(MOCK_APERTURE_LAST, data->iova_ranges[0].end);
  2235. break;
  2236. }
  2237. case VFIO_IOMMU_TYPE1_INFO_DMA_AVAIL: {
  2238. struct vfio_iommu_type1_info_dma_avail *data =
  2239. (void *)cap;
  2240. ASSERT_EQ(1, data->header.version);
  2241. ASSERT_EQ(sizeof(*data), cap_size);
  2242. break;
  2243. }
  2244. default:
  2245. ASSERT_EQ(false, true);
  2246. break;
  2247. }
  2248. if (!cap->next)
  2249. break;
  2250. ASSERT_GE(info_cmd->argsz, cap->next + sizeof(*cap));
  2251. ASSERT_GE(buffer + cap->next, (void *)cap);
  2252. cap = buffer + cap->next;
  2253. }
  2254. }
  2255. TEST_F(vfio_compat_mock_domain, get_info)
  2256. {
  2257. struct vfio_iommu_type1_info *info_cmd = buffer;
  2258. unsigned int i;
  2259. size_t caplen;
  2260. /* Pre-cap ABI */
  2261. *info_cmd = (struct vfio_iommu_type1_info){
  2262. .argsz = offsetof(struct vfio_iommu_type1_info, cap_offset),
  2263. };
  2264. ioctl_check_buf(self->fd, VFIO_IOMMU_GET_INFO);
  2265. ASSERT_NE(0, info_cmd->iova_pgsizes);
  2266. ASSERT_EQ(VFIO_IOMMU_INFO_PGSIZES | VFIO_IOMMU_INFO_CAPS,
  2267. info_cmd->flags);
  2268. /* Read the cap chain size */
  2269. *info_cmd = (struct vfio_iommu_type1_info){
  2270. .argsz = sizeof(*info_cmd),
  2271. };
  2272. ioctl_check_buf(self->fd, VFIO_IOMMU_GET_INFO);
  2273. ASSERT_NE(0, info_cmd->iova_pgsizes);
  2274. ASSERT_EQ(VFIO_IOMMU_INFO_PGSIZES | VFIO_IOMMU_INFO_CAPS,
  2275. info_cmd->flags);
  2276. ASSERT_EQ(0, info_cmd->cap_offset);
  2277. ASSERT_LT(sizeof(*info_cmd), info_cmd->argsz);
  2278. /* Read the caps, kernel should never create a corrupted caps */
  2279. caplen = info_cmd->argsz;
  2280. for (i = sizeof(*info_cmd); i < caplen; i++) {
  2281. *info_cmd = (struct vfio_iommu_type1_info){
  2282. .argsz = i,
  2283. };
  2284. ioctl_check_buf(self->fd, VFIO_IOMMU_GET_INFO);
  2285. ASSERT_EQ(VFIO_IOMMU_INFO_PGSIZES | VFIO_IOMMU_INFO_CAPS,
  2286. info_cmd->flags);
  2287. if (!info_cmd->cap_offset)
  2288. continue;
  2289. check_vfio_info_cap_chain(_metadata, info_cmd);
  2290. }
  2291. }
  2292. static void shuffle_array(unsigned long *array, size_t nelms)
  2293. {
  2294. unsigned int i;
  2295. /* Shuffle */
  2296. for (i = 0; i != nelms; i++) {
  2297. unsigned long tmp = array[i];
  2298. unsigned int other = rand() % (nelms - i);
  2299. array[i] = array[other];
  2300. array[other] = tmp;
  2301. }
  2302. }
  2303. TEST_F(vfio_compat_mock_domain, map)
  2304. {
  2305. struct vfio_iommu_type1_dma_map map_cmd = {
  2306. .argsz = sizeof(map_cmd),
  2307. .flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE,
  2308. .vaddr = (uintptr_t)buffer,
  2309. .size = BUFFER_SIZE,
  2310. .iova = MOCK_APERTURE_START,
  2311. };
  2312. struct vfio_iommu_type1_dma_unmap unmap_cmd = {
  2313. .argsz = sizeof(unmap_cmd),
  2314. .size = BUFFER_SIZE,
  2315. .iova = MOCK_APERTURE_START,
  2316. };
  2317. unsigned long pages_iova[BUFFER_SIZE / PAGE_SIZE];
  2318. unsigned int i;
  2319. /* Simple map/unmap */
  2320. ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
  2321. ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
  2322. ASSERT_EQ(BUFFER_SIZE, unmap_cmd.size);
  2323. /* Unmap of empty is success */
  2324. ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
  2325. /* UNMAP_FLAG_ALL requires 0 iova/size */
  2326. ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
  2327. unmap_cmd.flags = VFIO_DMA_UNMAP_FLAG_ALL;
  2328. EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
  2329. unmap_cmd.iova = 0;
  2330. unmap_cmd.size = 0;
  2331. ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
  2332. ASSERT_EQ(BUFFER_SIZE, unmap_cmd.size);
  2333. /* Small pages */
  2334. for (i = 0; i != ARRAY_SIZE(pages_iova); i++) {
  2335. map_cmd.iova = pages_iova[i] =
  2336. MOCK_APERTURE_START + i * PAGE_SIZE;
  2337. map_cmd.vaddr = (uintptr_t)buffer + i * PAGE_SIZE;
  2338. map_cmd.size = PAGE_SIZE;
  2339. ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
  2340. }
  2341. shuffle_array(pages_iova, ARRAY_SIZE(pages_iova));
  2342. unmap_cmd.flags = 0;
  2343. unmap_cmd.size = PAGE_SIZE;
  2344. for (i = 0; i != ARRAY_SIZE(pages_iova); i++) {
  2345. unmap_cmd.iova = pages_iova[i];
  2346. ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
  2347. }
  2348. }
  2349. TEST_F(vfio_compat_mock_domain, huge_map)
  2350. {
  2351. size_t buf_size = HUGEPAGE_SIZE * 2;
  2352. struct vfio_iommu_type1_dma_map map_cmd = {
  2353. .argsz = sizeof(map_cmd),
  2354. .flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE,
  2355. .size = buf_size,
  2356. .iova = MOCK_APERTURE_START,
  2357. };
  2358. struct vfio_iommu_type1_dma_unmap unmap_cmd = {
  2359. .argsz = sizeof(unmap_cmd),
  2360. };
  2361. unsigned long pages_iova[16];
  2362. unsigned int i;
  2363. void *buf;
  2364. /* Test huge pages and splitting */
  2365. buf = mmap(0, buf_size, PROT_READ | PROT_WRITE,
  2366. MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, -1,
  2367. 0);
  2368. ASSERT_NE(MAP_FAILED, buf);
  2369. map_cmd.vaddr = (uintptr_t)buf;
  2370. ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
  2371. unmap_cmd.size = buf_size / ARRAY_SIZE(pages_iova);
  2372. for (i = 0; i != ARRAY_SIZE(pages_iova); i++)
  2373. pages_iova[i] = MOCK_APERTURE_START + (i * unmap_cmd.size);
  2374. shuffle_array(pages_iova, ARRAY_SIZE(pages_iova));
  2375. /* type1 mode can cut up larger mappings, type1v2 always fails */
  2376. for (i = 0; i != ARRAY_SIZE(pages_iova); i++) {
  2377. unmap_cmd.iova = pages_iova[i];
  2378. unmap_cmd.size = buf_size / ARRAY_SIZE(pages_iova);
  2379. if (variant->version == VFIO_TYPE1_IOMMU) {
  2380. ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA,
  2381. &unmap_cmd));
  2382. } else {
  2383. EXPECT_ERRNO(ENOENT,
  2384. ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA,
  2385. &unmap_cmd));
  2386. }
  2387. }
  2388. }
  2389. FIXTURE(iommufd_viommu)
  2390. {
  2391. int fd;
  2392. uint32_t ioas_id;
  2393. uint32_t stdev_id;
  2394. uint32_t hwpt_id;
  2395. uint32_t nested_hwpt_id;
  2396. uint32_t device_id;
  2397. uint32_t viommu_id;
  2398. };
  2399. FIXTURE_VARIANT(iommufd_viommu)
  2400. {
  2401. unsigned int viommu;
  2402. };
  2403. FIXTURE_SETUP(iommufd_viommu)
  2404. {
  2405. self->fd = open("/dev/iommu", O_RDWR);
  2406. ASSERT_NE(-1, self->fd);
  2407. test_ioctl_ioas_alloc(&self->ioas_id);
  2408. test_ioctl_set_default_memory_limit();
  2409. if (variant->viommu) {
  2410. struct iommu_hwpt_selftest data = {
  2411. .iotlb = IOMMU_TEST_IOTLB_DEFAULT,
  2412. };
  2413. test_cmd_mock_domain(self->ioas_id, &self->stdev_id, NULL,
  2414. &self->device_id);
  2415. /* Allocate a nesting parent hwpt */
  2416. test_cmd_hwpt_alloc(self->device_id, self->ioas_id,
  2417. IOMMU_HWPT_ALLOC_NEST_PARENT,
  2418. &self->hwpt_id);
  2419. /* Allocate a vIOMMU taking refcount of the parent hwpt */
  2420. test_cmd_viommu_alloc(self->device_id, self->hwpt_id,
  2421. IOMMU_VIOMMU_TYPE_SELFTEST, NULL, 0,
  2422. &self->viommu_id);
  2423. /* Allocate a regular nested hwpt */
  2424. test_cmd_hwpt_alloc_nested(self->device_id, self->viommu_id, 0,
  2425. &self->nested_hwpt_id,
  2426. IOMMU_HWPT_DATA_SELFTEST, &data,
  2427. sizeof(data));
  2428. }
  2429. }
  2430. FIXTURE_TEARDOWN(iommufd_viommu)
  2431. {
  2432. teardown_iommufd(self->fd, _metadata);
  2433. }
  2434. FIXTURE_VARIANT_ADD(iommufd_viommu, no_viommu)
  2435. {
  2436. .viommu = 0,
  2437. };
  2438. FIXTURE_VARIANT_ADD(iommufd_viommu, mock_viommu)
  2439. {
  2440. .viommu = 1,
  2441. };
  2442. TEST_F(iommufd_viommu, viommu_auto_destroy)
  2443. {
  2444. }
  2445. TEST_F(iommufd_viommu, viommu_negative_tests)
  2446. {
  2447. uint32_t device_id = self->device_id;
  2448. uint32_t ioas_id = self->ioas_id;
  2449. uint32_t hwpt_id;
  2450. if (self->device_id) {
  2451. /* Negative test -- invalid hwpt (hwpt_id=0) */
  2452. test_err_viommu_alloc(ENOENT, device_id, 0,
  2453. IOMMU_VIOMMU_TYPE_SELFTEST, NULL, 0,
  2454. NULL);
  2455. /* Negative test -- not a nesting parent hwpt */
  2456. test_cmd_hwpt_alloc(device_id, ioas_id, 0, &hwpt_id);
  2457. test_err_viommu_alloc(EINVAL, device_id, hwpt_id,
  2458. IOMMU_VIOMMU_TYPE_SELFTEST, NULL, 0,
  2459. NULL);
  2460. test_ioctl_destroy(hwpt_id);
  2461. /* Negative test -- unsupported viommu type */
  2462. test_err_viommu_alloc(EOPNOTSUPP, device_id, self->hwpt_id,
  2463. 0xdead, NULL, 0, NULL);
  2464. EXPECT_ERRNO(EBUSY,
  2465. _test_ioctl_destroy(self->fd, self->hwpt_id));
  2466. EXPECT_ERRNO(EBUSY,
  2467. _test_ioctl_destroy(self->fd, self->viommu_id));
  2468. } else {
  2469. test_err_viommu_alloc(ENOENT, self->device_id, self->hwpt_id,
  2470. IOMMU_VIOMMU_TYPE_SELFTEST, NULL, 0,
  2471. NULL);
  2472. }
  2473. }
  2474. TEST_F(iommufd_viommu, viommu_alloc_nested_iopf)
  2475. {
  2476. struct iommu_hwpt_selftest data = {
  2477. .iotlb = IOMMU_TEST_IOTLB_DEFAULT,
  2478. };
  2479. uint32_t viommu_id = self->viommu_id;
  2480. uint32_t dev_id = self->device_id;
  2481. uint32_t iopf_hwpt_id;
  2482. uint32_t fault_id;
  2483. uint32_t fault_fd;
  2484. uint32_t vdev_id;
  2485. if (!dev_id)
  2486. SKIP(return, "Skipping test for variant no_viommu");
  2487. test_ioctl_fault_alloc(&fault_id, &fault_fd);
  2488. test_err_hwpt_alloc_iopf(ENOENT, dev_id, viommu_id, UINT32_MAX,
  2489. IOMMU_HWPT_FAULT_ID_VALID, &iopf_hwpt_id,
  2490. IOMMU_HWPT_DATA_SELFTEST, &data, sizeof(data));
  2491. test_err_hwpt_alloc_iopf(EOPNOTSUPP, dev_id, viommu_id, fault_id,
  2492. IOMMU_HWPT_FAULT_ID_VALID | (1 << 31),
  2493. &iopf_hwpt_id, IOMMU_HWPT_DATA_SELFTEST, &data,
  2494. sizeof(data));
  2495. test_cmd_hwpt_alloc_iopf(dev_id, viommu_id, fault_id,
  2496. IOMMU_HWPT_FAULT_ID_VALID, &iopf_hwpt_id,
  2497. IOMMU_HWPT_DATA_SELFTEST, &data, sizeof(data));
  2498. /* Must allocate vdevice before attaching to a nested hwpt */
  2499. test_err_mock_domain_replace(ENOENT, self->stdev_id, iopf_hwpt_id);
  2500. test_cmd_vdevice_alloc(viommu_id, dev_id, 0x99, &vdev_id);
  2501. test_cmd_mock_domain_replace(self->stdev_id, iopf_hwpt_id);
  2502. EXPECT_ERRNO(EBUSY, _test_ioctl_destroy(self->fd, iopf_hwpt_id));
  2503. test_cmd_trigger_iopf(dev_id, fault_fd);
  2504. test_cmd_mock_domain_replace(self->stdev_id, self->ioas_id);
  2505. test_ioctl_destroy(iopf_hwpt_id);
  2506. close(fault_fd);
  2507. test_ioctl_destroy(fault_id);
  2508. }
  2509. TEST_F(iommufd_viommu, viommu_alloc_with_data)
  2510. {
  2511. struct iommu_viommu_selftest data = {
  2512. .in_data = 0xbeef,
  2513. };
  2514. uint32_t *test;
  2515. if (!self->device_id)
  2516. SKIP(return, "Skipping test for variant no_viommu");
  2517. test_cmd_viommu_alloc(self->device_id, self->hwpt_id,
  2518. IOMMU_VIOMMU_TYPE_SELFTEST, &data, sizeof(data),
  2519. &self->viommu_id);
  2520. ASSERT_EQ(data.out_data, data.in_data);
  2521. /* Negative mmap tests -- offset and length cannot be changed */
  2522. test_err_mmap(ENXIO, data.out_mmap_length,
  2523. data.out_mmap_offset + PAGE_SIZE);
  2524. test_err_mmap(ENXIO, data.out_mmap_length,
  2525. data.out_mmap_offset + PAGE_SIZE * 2);
  2526. test_err_mmap(ENXIO, data.out_mmap_length / 2, data.out_mmap_offset);
  2527. test_err_mmap(ENXIO, data.out_mmap_length * 2, data.out_mmap_offset);
  2528. /* Now do a correct mmap for a loopback test */
  2529. test = mmap(NULL, data.out_mmap_length, PROT_READ | PROT_WRITE,
  2530. MAP_SHARED, self->fd, data.out_mmap_offset);
  2531. ASSERT_NE(MAP_FAILED, test);
  2532. ASSERT_EQ(data.in_data, *test);
  2533. /* The owner of the mmap region should be blocked */
  2534. EXPECT_ERRNO(EBUSY, _test_ioctl_destroy(self->fd, self->viommu_id));
  2535. munmap(test, data.out_mmap_length);
  2536. }
  2537. TEST_F(iommufd_viommu, vdevice_alloc)
  2538. {
  2539. uint32_t viommu_id = self->viommu_id;
  2540. uint32_t dev_id = self->device_id;
  2541. uint32_t vdev_id = 0;
  2542. uint32_t veventq_id;
  2543. uint32_t veventq_fd;
  2544. int prev_seq = -1;
  2545. if (dev_id) {
  2546. /* Must allocate vdevice before attaching to a nested hwpt */
  2547. test_err_mock_domain_replace(ENOENT, self->stdev_id,
  2548. self->nested_hwpt_id);
  2549. /* Allocate a vEVENTQ with veventq_depth=2 */
  2550. test_cmd_veventq_alloc(viommu_id, IOMMU_VEVENTQ_TYPE_SELFTEST,
  2551. &veventq_id, &veventq_fd);
  2552. test_err_veventq_alloc(EEXIST, viommu_id,
  2553. IOMMU_VEVENTQ_TYPE_SELFTEST, NULL, NULL);
  2554. /* Set vdev_id to 0x99, unset it, and set to 0x88 */
  2555. test_cmd_vdevice_alloc(viommu_id, dev_id, 0x99, &vdev_id);
  2556. test_cmd_mock_domain_replace(self->stdev_id,
  2557. self->nested_hwpt_id);
  2558. test_cmd_trigger_vevents(dev_id, 1);
  2559. test_cmd_read_vevents(veventq_fd, 1, 0x99, &prev_seq);
  2560. test_err_vdevice_alloc(EEXIST, viommu_id, dev_id, 0x99,
  2561. &vdev_id);
  2562. test_cmd_mock_domain_replace(self->stdev_id, self->ioas_id);
  2563. test_ioctl_destroy(vdev_id);
  2564. /* Try again with 0x88 */
  2565. test_cmd_vdevice_alloc(viommu_id, dev_id, 0x88, &vdev_id);
  2566. test_cmd_mock_domain_replace(self->stdev_id,
  2567. self->nested_hwpt_id);
  2568. /* Trigger an overflow with three events */
  2569. test_cmd_trigger_vevents(dev_id, 3);
  2570. test_err_read_vevents(EOVERFLOW, veventq_fd, 3, 0x88,
  2571. &prev_seq);
  2572. /* Overflow must be gone after the previous reads */
  2573. test_cmd_trigger_vevents(dev_id, 1);
  2574. test_cmd_read_vevents(veventq_fd, 1, 0x88, &prev_seq);
  2575. close(veventq_fd);
  2576. test_cmd_mock_domain_replace(self->stdev_id, self->ioas_id);
  2577. test_ioctl_destroy(vdev_id);
  2578. test_ioctl_destroy(veventq_id);
  2579. } else {
  2580. test_err_vdevice_alloc(ENOENT, viommu_id, dev_id, 0x99, NULL);
  2581. }
  2582. }
  2583. TEST_F(iommufd_viommu, vdevice_cache)
  2584. {
  2585. struct iommu_viommu_invalidate_selftest inv_reqs[2] = {};
  2586. uint32_t viommu_id = self->viommu_id;
  2587. uint32_t dev_id = self->device_id;
  2588. uint32_t vdev_id = 0;
  2589. uint32_t num_inv;
  2590. if (!dev_id)
  2591. SKIP(return, "Skipping test for variant no_viommu");
  2592. test_cmd_vdevice_alloc(viommu_id, dev_id, 0x99, &vdev_id);
  2593. test_cmd_dev_check_cache_all(dev_id, IOMMU_TEST_DEV_CACHE_DEFAULT);
  2594. /* Check data_type by passing zero-length array */
  2595. num_inv = 0;
  2596. test_cmd_viommu_invalidate(viommu_id, inv_reqs, sizeof(*inv_reqs),
  2597. &num_inv);
  2598. assert(!num_inv);
  2599. /* Negative test: Invalid data_type */
  2600. num_inv = 1;
  2601. test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
  2602. IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST_INVALID,
  2603. sizeof(*inv_reqs), &num_inv);
  2604. assert(!num_inv);
  2605. /* Negative test: structure size sanity */
  2606. num_inv = 1;
  2607. test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
  2608. IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
  2609. sizeof(*inv_reqs) + 1, &num_inv);
  2610. assert(!num_inv);
  2611. num_inv = 1;
  2612. test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
  2613. IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST, 1,
  2614. &num_inv);
  2615. assert(!num_inv);
  2616. /* Negative test: invalid flag is passed */
  2617. num_inv = 1;
  2618. inv_reqs[0].flags = 0xffffffff;
  2619. inv_reqs[0].vdev_id = 0x99;
  2620. test_err_viommu_invalidate(EOPNOTSUPP, viommu_id, inv_reqs,
  2621. IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
  2622. sizeof(*inv_reqs), &num_inv);
  2623. assert(!num_inv);
  2624. /* Negative test: invalid data_uptr when array is not empty */
  2625. num_inv = 1;
  2626. inv_reqs[0].flags = 0;
  2627. inv_reqs[0].vdev_id = 0x99;
  2628. test_err_viommu_invalidate(EINVAL, viommu_id, NULL,
  2629. IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
  2630. sizeof(*inv_reqs), &num_inv);
  2631. assert(!num_inv);
  2632. /* Negative test: invalid entry_len when array is not empty */
  2633. num_inv = 1;
  2634. inv_reqs[0].flags = 0;
  2635. inv_reqs[0].vdev_id = 0x99;
  2636. test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
  2637. IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST, 0,
  2638. &num_inv);
  2639. assert(!num_inv);
  2640. /* Negative test: invalid cache_id */
  2641. num_inv = 1;
  2642. inv_reqs[0].flags = 0;
  2643. inv_reqs[0].vdev_id = 0x99;
  2644. inv_reqs[0].cache_id = MOCK_DEV_CACHE_ID_MAX + 1;
  2645. test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
  2646. IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
  2647. sizeof(*inv_reqs), &num_inv);
  2648. assert(!num_inv);
  2649. /* Negative test: invalid vdev_id */
  2650. num_inv = 1;
  2651. inv_reqs[0].flags = 0;
  2652. inv_reqs[0].vdev_id = 0x9;
  2653. inv_reqs[0].cache_id = 0;
  2654. test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
  2655. IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
  2656. sizeof(*inv_reqs), &num_inv);
  2657. assert(!num_inv);
  2658. /*
  2659. * Invalidate the 1st cache entry but fail the 2nd request
  2660. * due to invalid flags configuration in the 2nd request.
  2661. */
  2662. num_inv = 2;
  2663. inv_reqs[0].flags = 0;
  2664. inv_reqs[0].vdev_id = 0x99;
  2665. inv_reqs[0].cache_id = 0;
  2666. inv_reqs[1].flags = 0xffffffff;
  2667. inv_reqs[1].vdev_id = 0x99;
  2668. inv_reqs[1].cache_id = 1;
  2669. test_err_viommu_invalidate(EOPNOTSUPP, viommu_id, inv_reqs,
  2670. IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
  2671. sizeof(*inv_reqs), &num_inv);
  2672. assert(num_inv == 1);
  2673. test_cmd_dev_check_cache(dev_id, 0, 0);
  2674. test_cmd_dev_check_cache(dev_id, 1, IOMMU_TEST_DEV_CACHE_DEFAULT);
  2675. test_cmd_dev_check_cache(dev_id, 2, IOMMU_TEST_DEV_CACHE_DEFAULT);
  2676. test_cmd_dev_check_cache(dev_id, 3, IOMMU_TEST_DEV_CACHE_DEFAULT);
  2677. /*
  2678. * Invalidate the 1st cache entry but fail the 2nd request
  2679. * due to invalid cache_id configuration in the 2nd request.
  2680. */
  2681. num_inv = 2;
  2682. inv_reqs[0].flags = 0;
  2683. inv_reqs[0].vdev_id = 0x99;
  2684. inv_reqs[0].cache_id = 0;
  2685. inv_reqs[1].flags = 0;
  2686. inv_reqs[1].vdev_id = 0x99;
  2687. inv_reqs[1].cache_id = MOCK_DEV_CACHE_ID_MAX + 1;
  2688. test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
  2689. IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
  2690. sizeof(*inv_reqs), &num_inv);
  2691. assert(num_inv == 1);
  2692. test_cmd_dev_check_cache(dev_id, 0, 0);
  2693. test_cmd_dev_check_cache(dev_id, 1, IOMMU_TEST_DEV_CACHE_DEFAULT);
  2694. test_cmd_dev_check_cache(dev_id, 2, IOMMU_TEST_DEV_CACHE_DEFAULT);
  2695. test_cmd_dev_check_cache(dev_id, 3, IOMMU_TEST_DEV_CACHE_DEFAULT);
  2696. /* Invalidate the 2nd cache entry and verify */
  2697. num_inv = 1;
  2698. inv_reqs[0].flags = 0;
  2699. inv_reqs[0].vdev_id = 0x99;
  2700. inv_reqs[0].cache_id = 1;
  2701. test_cmd_viommu_invalidate(viommu_id, inv_reqs, sizeof(*inv_reqs),
  2702. &num_inv);
  2703. assert(num_inv == 1);
  2704. test_cmd_dev_check_cache(dev_id, 0, 0);
  2705. test_cmd_dev_check_cache(dev_id, 1, 0);
  2706. test_cmd_dev_check_cache(dev_id, 2, IOMMU_TEST_DEV_CACHE_DEFAULT);
  2707. test_cmd_dev_check_cache(dev_id, 3, IOMMU_TEST_DEV_CACHE_DEFAULT);
  2708. /* Invalidate the 3rd and 4th cache entries and verify */
  2709. num_inv = 2;
  2710. inv_reqs[0].flags = 0;
  2711. inv_reqs[0].vdev_id = 0x99;
  2712. inv_reqs[0].cache_id = 2;
  2713. inv_reqs[1].flags = 0;
  2714. inv_reqs[1].vdev_id = 0x99;
  2715. inv_reqs[1].cache_id = 3;
  2716. test_cmd_viommu_invalidate(viommu_id, inv_reqs, sizeof(*inv_reqs),
  2717. &num_inv);
  2718. assert(num_inv == 2);
  2719. test_cmd_dev_check_cache_all(dev_id, 0);
  2720. /* Invalidate all cache entries for nested_dev_id[1] and verify */
  2721. num_inv = 1;
  2722. inv_reqs[0].vdev_id = 0x99;
  2723. inv_reqs[0].flags = IOMMU_TEST_INVALIDATE_FLAG_ALL;
  2724. test_cmd_viommu_invalidate(viommu_id, inv_reqs, sizeof(*inv_reqs),
  2725. &num_inv);
  2726. assert(num_inv == 1);
  2727. test_cmd_dev_check_cache_all(dev_id, 0);
  2728. test_ioctl_destroy(vdev_id);
  2729. }
  2730. TEST_F(iommufd_viommu, hw_queue)
  2731. {
  2732. __u64 iova = MOCK_APERTURE_START, iova2;
  2733. uint32_t viommu_id = self->viommu_id;
  2734. uint32_t hw_queue_id[2];
  2735. if (!viommu_id)
  2736. SKIP(return, "Skipping test for variant no_viommu");
  2737. /* Fail IOMMU_HW_QUEUE_TYPE_DEFAULT */
  2738. test_err_hw_queue_alloc(EOPNOTSUPP, viommu_id,
  2739. IOMMU_HW_QUEUE_TYPE_DEFAULT, 0, iova, PAGE_SIZE,
  2740. &hw_queue_id[0]);
  2741. /* Fail queue addr and length */
  2742. test_err_hw_queue_alloc(EINVAL, viommu_id, IOMMU_HW_QUEUE_TYPE_SELFTEST,
  2743. 0, iova, 0, &hw_queue_id[0]);
  2744. test_err_hw_queue_alloc(EOVERFLOW, viommu_id,
  2745. IOMMU_HW_QUEUE_TYPE_SELFTEST, 0, ~(uint64_t)0,
  2746. PAGE_SIZE, &hw_queue_id[0]);
  2747. /* Fail missing iova */
  2748. test_err_hw_queue_alloc(ENOENT, viommu_id, IOMMU_HW_QUEUE_TYPE_SELFTEST,
  2749. 0, iova, PAGE_SIZE, &hw_queue_id[0]);
  2750. /* Map iova */
  2751. test_ioctl_ioas_map(buffer, PAGE_SIZE, &iova);
  2752. test_ioctl_ioas_map(buffer + PAGE_SIZE, PAGE_SIZE, &iova2);
  2753. /* Fail index=1 and =MAX; must start from index=0 */
  2754. test_err_hw_queue_alloc(EIO, viommu_id, IOMMU_HW_QUEUE_TYPE_SELFTEST, 1,
  2755. iova, PAGE_SIZE, &hw_queue_id[0]);
  2756. test_err_hw_queue_alloc(EINVAL, viommu_id, IOMMU_HW_QUEUE_TYPE_SELFTEST,
  2757. IOMMU_TEST_HW_QUEUE_MAX, iova, PAGE_SIZE,
  2758. &hw_queue_id[0]);
  2759. /* Allocate index=0, declare ownership of the iova */
  2760. test_cmd_hw_queue_alloc(viommu_id, IOMMU_HW_QUEUE_TYPE_SELFTEST, 0,
  2761. iova, PAGE_SIZE, &hw_queue_id[0]);
  2762. /* Fail duplicated index */
  2763. test_err_hw_queue_alloc(EEXIST, viommu_id, IOMMU_HW_QUEUE_TYPE_SELFTEST,
  2764. 0, iova, PAGE_SIZE, &hw_queue_id[0]);
  2765. /* Fail unmap, due to iova ownership */
  2766. test_err_ioctl_ioas_unmap(EBUSY, iova, PAGE_SIZE);
  2767. /* The 2nd page is not pinned, so it can be unmmap */
  2768. test_ioctl_ioas_unmap(iova2, PAGE_SIZE);
  2769. /* Allocate index=1, with an unaligned case */
  2770. test_cmd_hw_queue_alloc(viommu_id, IOMMU_HW_QUEUE_TYPE_SELFTEST, 1,
  2771. iova + PAGE_SIZE / 2, PAGE_SIZE / 2,
  2772. &hw_queue_id[1]);
  2773. /* Fail to destroy, due to dependency */
  2774. EXPECT_ERRNO(EBUSY, _test_ioctl_destroy(self->fd, hw_queue_id[0]));
  2775. /* Destroy in descending order */
  2776. test_ioctl_destroy(hw_queue_id[1]);
  2777. test_ioctl_destroy(hw_queue_id[0]);
  2778. /* Now it can unmap the first page */
  2779. test_ioctl_ioas_unmap(iova, PAGE_SIZE);
  2780. }
  2781. TEST_F(iommufd_viommu, vdevice_tombstone)
  2782. {
  2783. uint32_t viommu_id = self->viommu_id;
  2784. uint32_t dev_id = self->device_id;
  2785. uint32_t vdev_id = 0;
  2786. if (!dev_id)
  2787. SKIP(return, "Skipping test for variant no_viommu");
  2788. test_cmd_vdevice_alloc(viommu_id, dev_id, 0x99, &vdev_id);
  2789. test_ioctl_destroy(self->stdev_id);
  2790. EXPECT_ERRNO(ENOENT, _test_ioctl_destroy(self->fd, vdev_id));
  2791. }
  2792. FIXTURE(iommufd_device_pasid)
  2793. {
  2794. int fd;
  2795. uint32_t ioas_id;
  2796. uint32_t hwpt_id;
  2797. uint32_t stdev_id;
  2798. uint32_t device_id;
  2799. uint32_t no_pasid_stdev_id;
  2800. uint32_t no_pasid_device_id;
  2801. };
  2802. FIXTURE_VARIANT(iommufd_device_pasid)
  2803. {
  2804. bool pasid_capable;
  2805. };
  2806. FIXTURE_SETUP(iommufd_device_pasid)
  2807. {
  2808. self->fd = open("/dev/iommu", O_RDWR);
  2809. ASSERT_NE(-1, self->fd);
  2810. test_ioctl_ioas_alloc(&self->ioas_id);
  2811. test_cmd_mock_domain_flags(self->ioas_id,
  2812. MOCK_FLAGS_DEVICE_PASID,
  2813. &self->stdev_id, &self->hwpt_id,
  2814. &self->device_id);
  2815. if (!variant->pasid_capable)
  2816. test_cmd_mock_domain_flags(self->ioas_id, 0,
  2817. &self->no_pasid_stdev_id, NULL,
  2818. &self->no_pasid_device_id);
  2819. }
  2820. FIXTURE_TEARDOWN(iommufd_device_pasid)
  2821. {
  2822. teardown_iommufd(self->fd, _metadata);
  2823. }
  2824. FIXTURE_VARIANT_ADD(iommufd_device_pasid, no_pasid)
  2825. {
  2826. .pasid_capable = false,
  2827. };
  2828. FIXTURE_VARIANT_ADD(iommufd_device_pasid, has_pasid)
  2829. {
  2830. .pasid_capable = true,
  2831. };
  2832. TEST_F(iommufd_device_pasid, pasid_attach)
  2833. {
  2834. struct iommu_hwpt_selftest data = {
  2835. .iotlb = IOMMU_TEST_IOTLB_DEFAULT,
  2836. };
  2837. uint32_t nested_hwpt_id[3] = {};
  2838. uint32_t parent_hwpt_id = 0;
  2839. uint32_t fault_id, fault_fd;
  2840. uint32_t s2_hwpt_id = 0;
  2841. uint32_t iopf_hwpt_id;
  2842. uint32_t pasid = 100;
  2843. uint32_t viommu_id;
  2844. /*
  2845. * Negative, detach pasid without attaching, this is not expected.
  2846. * But it should not result in failure anyway.
  2847. */
  2848. test_cmd_pasid_detach(pasid);
  2849. /* Allocate two nested hwpts sharing one common parent hwpt */
  2850. test_cmd_hwpt_alloc(self->device_id, self->ioas_id,
  2851. IOMMU_HWPT_ALLOC_NEST_PARENT,
  2852. &parent_hwpt_id);
  2853. test_cmd_hwpt_alloc_nested(self->device_id, parent_hwpt_id,
  2854. IOMMU_HWPT_ALLOC_PASID,
  2855. &nested_hwpt_id[0],
  2856. IOMMU_HWPT_DATA_SELFTEST,
  2857. &data, sizeof(data));
  2858. test_cmd_hwpt_alloc_nested(self->device_id, parent_hwpt_id,
  2859. IOMMU_HWPT_ALLOC_PASID,
  2860. &nested_hwpt_id[1],
  2861. IOMMU_HWPT_DATA_SELFTEST,
  2862. &data, sizeof(data));
  2863. /* Fault related preparation */
  2864. test_ioctl_fault_alloc(&fault_id, &fault_fd);
  2865. test_cmd_hwpt_alloc_iopf(self->device_id, parent_hwpt_id, fault_id,
  2866. IOMMU_HWPT_FAULT_ID_VALID | IOMMU_HWPT_ALLOC_PASID,
  2867. &iopf_hwpt_id,
  2868. IOMMU_HWPT_DATA_SELFTEST, &data,
  2869. sizeof(data));
  2870. /* Allocate a regular nested hwpt based on viommu */
  2871. test_cmd_viommu_alloc(self->device_id, parent_hwpt_id,
  2872. IOMMU_VIOMMU_TYPE_SELFTEST, NULL, 0, &viommu_id);
  2873. test_cmd_hwpt_alloc_nested(self->device_id, viommu_id,
  2874. IOMMU_HWPT_ALLOC_PASID,
  2875. &nested_hwpt_id[2],
  2876. IOMMU_HWPT_DATA_SELFTEST, &data,
  2877. sizeof(data));
  2878. test_cmd_hwpt_alloc(self->device_id, self->ioas_id,
  2879. IOMMU_HWPT_ALLOC_PASID,
  2880. &s2_hwpt_id);
  2881. /* Attach RID to non-pasid compat domain, */
  2882. test_cmd_mock_domain_replace(self->stdev_id, parent_hwpt_id);
  2883. /* then attach to pasid should fail */
  2884. test_err_pasid_attach(EINVAL, pasid, s2_hwpt_id);
  2885. /* Attach RID to pasid compat domain, */
  2886. test_cmd_mock_domain_replace(self->stdev_id, s2_hwpt_id);
  2887. /* then attach to pasid should succeed, */
  2888. test_cmd_pasid_attach(pasid, nested_hwpt_id[0]);
  2889. /* but attach RID to non-pasid compat domain should fail now. */
  2890. test_err_mock_domain_replace(EINVAL, self->stdev_id, parent_hwpt_id);
  2891. /*
  2892. * Detach hwpt from pasid 100, and check if the pasid 100
  2893. * has null domain.
  2894. */
  2895. test_cmd_pasid_detach(pasid);
  2896. ASSERT_EQ(0,
  2897. test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
  2898. pasid, 0));
  2899. /* RID is attached to pasid-comapt domain, pasid path is not used */
  2900. if (!variant->pasid_capable) {
  2901. /*
  2902. * PASID-compatible domain can be used by non-PASID-capable
  2903. * device.
  2904. */
  2905. test_cmd_mock_domain_replace(self->no_pasid_stdev_id, nested_hwpt_id[0]);
  2906. test_cmd_mock_domain_replace(self->no_pasid_stdev_id, self->ioas_id);
  2907. /*
  2908. * Attach hwpt to pasid 100 of non-PASID-capable device,
  2909. * should fail, no matter domain is pasid-comapt or not.
  2910. */
  2911. EXPECT_ERRNO(EINVAL,
  2912. _test_cmd_pasid_attach(self->fd, self->no_pasid_stdev_id,
  2913. pasid, parent_hwpt_id));
  2914. EXPECT_ERRNO(EINVAL,
  2915. _test_cmd_pasid_attach(self->fd, self->no_pasid_stdev_id,
  2916. pasid, s2_hwpt_id));
  2917. }
  2918. /*
  2919. * Attach non pasid compat hwpt to pasid-capable device, should
  2920. * fail, and have null domain.
  2921. */
  2922. test_err_pasid_attach(EINVAL, pasid, parent_hwpt_id);
  2923. ASSERT_EQ(0,
  2924. test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
  2925. pasid, 0));
  2926. /*
  2927. * Attach ioas to pasid 100, should fail, domain should
  2928. * be null.
  2929. */
  2930. test_err_pasid_attach(EINVAL, pasid, self->ioas_id);
  2931. ASSERT_EQ(0,
  2932. test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
  2933. pasid, 0));
  2934. /*
  2935. * Attach the s2_hwpt to pasid 100, should succeed, domain should
  2936. * be valid.
  2937. */
  2938. test_cmd_pasid_attach(pasid, s2_hwpt_id);
  2939. ASSERT_EQ(0,
  2940. test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
  2941. pasid, s2_hwpt_id));
  2942. /*
  2943. * Try attach pasid 100 with another hwpt, should FAIL
  2944. * as attach does not allow overwrite, use REPLACE instead.
  2945. */
  2946. test_err_pasid_attach(EBUSY, pasid, nested_hwpt_id[0]);
  2947. /*
  2948. * Detach hwpt from pasid 100 for next test, should succeed,
  2949. * and have null domain.
  2950. */
  2951. test_cmd_pasid_detach(pasid);
  2952. ASSERT_EQ(0,
  2953. test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
  2954. pasid, 0));
  2955. /*
  2956. * Attach nested hwpt to pasid 100, should succeed, domain
  2957. * should be valid.
  2958. */
  2959. test_cmd_pasid_attach(pasid, nested_hwpt_id[0]);
  2960. ASSERT_EQ(0,
  2961. test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
  2962. pasid, nested_hwpt_id[0]));
  2963. /* Attach to pasid 100 which has been attached, should fail. */
  2964. test_err_pasid_attach(EBUSY, pasid, nested_hwpt_id[0]);
  2965. /* cleanup pasid 100 */
  2966. test_cmd_pasid_detach(pasid);
  2967. /* Replace tests */
  2968. pasid = 200;
  2969. /*
  2970. * Replace pasid 200 without attaching it, should fail
  2971. * with -EINVAL.
  2972. */
  2973. test_err_pasid_replace(EINVAL, pasid, s2_hwpt_id);
  2974. /*
  2975. * Attach the s2 hwpt to pasid 200, should succeed, domain should
  2976. * be valid.
  2977. */
  2978. test_cmd_pasid_attach(pasid, s2_hwpt_id);
  2979. ASSERT_EQ(0,
  2980. test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
  2981. pasid, s2_hwpt_id));
  2982. /*
  2983. * Replace pasid 200 with self->ioas_id, should fail
  2984. * and domain should be the prior s2 hwpt.
  2985. */
  2986. test_err_pasid_replace(EINVAL, pasid, self->ioas_id);
  2987. ASSERT_EQ(0,
  2988. test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
  2989. pasid, s2_hwpt_id));
  2990. /*
  2991. * Replace a nested hwpt for pasid 200, should succeed,
  2992. * and have valid domain.
  2993. */
  2994. test_cmd_pasid_replace(pasid, nested_hwpt_id[0]);
  2995. ASSERT_EQ(0,
  2996. test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
  2997. pasid, nested_hwpt_id[0]));
  2998. /*
  2999. * Replace with another nested hwpt for pasid 200, should
  3000. * succeed, and have valid domain.
  3001. */
  3002. test_cmd_pasid_replace(pasid, nested_hwpt_id[1]);
  3003. ASSERT_EQ(0,
  3004. test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
  3005. pasid, nested_hwpt_id[1]));
  3006. /* cleanup pasid 200 */
  3007. test_cmd_pasid_detach(pasid);
  3008. /* Negative Tests for pasid replace, use pasid 1024 */
  3009. /*
  3010. * Attach the s2 hwpt to pasid 1024, should succeed, domain should
  3011. * be valid.
  3012. */
  3013. pasid = 1024;
  3014. test_cmd_pasid_attach(pasid, s2_hwpt_id);
  3015. ASSERT_EQ(0,
  3016. test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
  3017. pasid, s2_hwpt_id));
  3018. /*
  3019. * Replace pasid 1024 with nested_hwpt_id[0], should fail,
  3020. * but have the old valid domain. This is a designed
  3021. * negative case. Normally, this shall succeed.
  3022. */
  3023. test_err_pasid_replace(ENOMEM, pasid, nested_hwpt_id[0]);
  3024. ASSERT_EQ(0,
  3025. test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
  3026. pasid, s2_hwpt_id));
  3027. /* cleanup pasid 1024 */
  3028. test_cmd_pasid_detach(pasid);
  3029. /* Attach to iopf-capable hwpt */
  3030. /*
  3031. * Attach an iopf hwpt to pasid 2048, should succeed, domain should
  3032. * be valid.
  3033. */
  3034. pasid = 2048;
  3035. test_cmd_pasid_attach(pasid, iopf_hwpt_id);
  3036. ASSERT_EQ(0,
  3037. test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
  3038. pasid, iopf_hwpt_id));
  3039. test_cmd_trigger_iopf_pasid(self->device_id, pasid, fault_fd);
  3040. /*
  3041. * Replace with s2_hwpt_id for pasid 2048, should
  3042. * succeed, and have valid domain.
  3043. */
  3044. test_cmd_pasid_replace(pasid, s2_hwpt_id);
  3045. ASSERT_EQ(0,
  3046. test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
  3047. pasid, s2_hwpt_id));
  3048. /* cleanup pasid 2048 */
  3049. test_cmd_pasid_detach(pasid);
  3050. test_ioctl_destroy(iopf_hwpt_id);
  3051. close(fault_fd);
  3052. test_ioctl_destroy(fault_id);
  3053. /* Detach the s2_hwpt_id from RID */
  3054. test_cmd_mock_domain_replace(self->stdev_id, self->ioas_id);
  3055. }
  3056. TEST_HARNESS_MAIN