drm_gpusvm.c 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762
  1. // SPDX-License-Identifier: GPL-2.0-only OR MIT
  2. /*
  3. * Copyright © 2024 Intel Corporation
  4. *
  5. * Authors:
  6. * Matthew Brost <matthew.brost@intel.com>
  7. */
  8. #include <linux/dma-mapping.h>
  9. #include <linux/export.h>
  10. #include <linux/hmm.h>
  11. #include <linux/hugetlb_inline.h>
  12. #include <linux/memremap.h>
  13. #include <linux/mm_types.h>
  14. #include <linux/slab.h>
  15. #include <drm/drm_device.h>
  16. #include <drm/drm_gpusvm.h>
  17. #include <drm/drm_pagemap.h>
  18. #include <drm/drm_print.h>
  19. /**
  20. * DOC: Overview
  21. *
  22. * GPU Shared Virtual Memory (GPU SVM) layer for the Direct Rendering Manager (DRM)
  23. * is a component of the DRM framework designed to manage shared virtual memory
  24. * between the CPU and GPU. It enables efficient data exchange and processing
  25. * for GPU-accelerated applications by allowing memory sharing and
  26. * synchronization between the CPU's and GPU's virtual address spaces.
  27. *
  28. * Key GPU SVM Components:
  29. *
  30. * - Notifiers:
  31. * Used for tracking memory intervals and notifying the GPU of changes,
  32. * notifiers are sized based on a GPU SVM initialization parameter, with a
  33. * recommendation of 512M or larger. They maintain a Red-BlacK tree and a
  34. * list of ranges that fall within the notifier interval. Notifiers are
  35. * tracked within a GPU SVM Red-BlacK tree and list and are dynamically
  36. * inserted or removed as ranges within the interval are created or
  37. * destroyed.
  38. * - Ranges:
  39. * Represent memory ranges mapped in a DRM device and managed by GPU SVM.
  40. * They are sized based on an array of chunk sizes, which is a GPU SVM
  41. * initialization parameter, and the CPU address space. Upon GPU fault,
  42. * the largest aligned chunk that fits within the faulting CPU address
  43. * space is chosen for the range size. Ranges are expected to be
  44. * dynamically allocated on GPU fault and removed on an MMU notifier UNMAP
  45. * event. As mentioned above, ranges are tracked in a notifier's Red-Black
  46. * tree.
  47. *
  48. * - Operations:
  49. * Define the interface for driver-specific GPU SVM operations such as
  50. * range allocation, notifier allocation, and invalidations.
  51. *
  52. * - Device Memory Allocations:
  53. * Embedded structure containing enough information for GPU SVM to migrate
  54. * to / from device memory.
  55. *
  56. * - Device Memory Operations:
  57. * Define the interface for driver-specific device memory operations
  58. * release memory, populate pfns, and copy to / from device memory.
  59. *
  60. * This layer provides interfaces for allocating, mapping, migrating, and
  61. * releasing memory ranges between the CPU and GPU. It handles all core memory
  62. * management interactions (DMA mapping, HMM, and migration) and provides
  63. * driver-specific virtual functions (vfuncs). This infrastructure is sufficient
  64. * to build the expected driver components for an SVM implementation as detailed
  65. * below.
  66. *
  67. * Expected Driver Components:
  68. *
  69. * - GPU page fault handler:
  70. * Used to create ranges and notifiers based on the fault address,
  71. * optionally migrate the range to device memory, and create GPU bindings.
  72. *
  73. * - Garbage collector:
  74. * Used to unmap and destroy GPU bindings for ranges. Ranges are expected
  75. * to be added to the garbage collector upon a MMU_NOTIFY_UNMAP event in
  76. * notifier callback.
  77. *
  78. * - Notifier callback:
  79. * Used to invalidate and DMA unmap GPU bindings for ranges.
  80. */
  81. /**
  82. * DOC: Locking
  83. *
  84. * GPU SVM handles locking for core MM interactions, i.e., it locks/unlocks the
  85. * mmap lock as needed.
  86. *
  87. * GPU SVM introduces a global notifier lock, which safeguards the notifier's
  88. * range RB tree and list, as well as the range's DMA mappings and sequence
  89. * number. GPU SVM manages all necessary locking and unlocking operations,
  90. * except for the recheck range's pages being valid
  91. * (drm_gpusvm_range_pages_valid) when the driver is committing GPU bindings.
  92. * This lock corresponds to the ``driver->update`` lock mentioned in
  93. * Documentation/mm/hmm.rst. Future revisions may transition from a GPU SVM
  94. * global lock to a per-notifier lock if finer-grained locking is deemed
  95. * necessary.
  96. *
  97. * In addition to the locking mentioned above, the driver should implement a
  98. * lock to safeguard core GPU SVM function calls that modify state, such as
  99. * drm_gpusvm_range_find_or_insert and drm_gpusvm_range_remove. This lock is
  100. * denoted as 'driver_svm_lock' in code examples. Finer grained driver side
  101. * locking should also be possible for concurrent GPU fault processing within a
  102. * single GPU SVM. The 'driver_svm_lock' can be via drm_gpusvm_driver_set_lock
  103. * to add annotations to GPU SVM.
  104. */
  105. /**
  106. * DOC: Partial Unmapping of Ranges
  107. *
  108. * Partial unmapping of ranges (e.g., 1M out of 2M is unmapped by CPU resulting
  109. * in MMU_NOTIFY_UNMAP event) presents several challenges, with the main one
  110. * being that a subset of the range still has CPU and GPU mappings. If the
  111. * backing store for the range is in device memory, a subset of the backing
  112. * store has references. One option would be to split the range and device
  113. * memory backing store, but the implementation for this would be quite
  114. * complicated. Given that partial unmappings are rare and driver-defined range
  115. * sizes are relatively small, GPU SVM does not support splitting of ranges.
  116. *
  117. * With no support for range splitting, upon partial unmapping of a range, the
  118. * driver is expected to invalidate and destroy the entire range. If the range
  119. * has device memory as its backing, the driver is also expected to migrate any
  120. * remaining pages back to RAM.
  121. */
  122. /**
  123. * DOC: Examples
  124. *
  125. * This section provides three examples of how to build the expected driver
  126. * components: the GPU page fault handler, the garbage collector, and the
  127. * notifier callback.
  128. *
  129. * The generic code provided does not include logic for complex migration
  130. * policies, optimized invalidations, fined grained driver locking, or other
  131. * potentially required driver locking (e.g., DMA-resv locks).
  132. *
  133. * 1) GPU page fault handler
  134. *
  135. * .. code-block:: c
  136. *
  137. * int driver_bind_range(struct drm_gpusvm *gpusvm, struct drm_gpusvm_range *range)
  138. * {
  139. * int err = 0;
  140. *
  141. * driver_alloc_and_setup_memory_for_bind(gpusvm, range);
  142. *
  143. * drm_gpusvm_notifier_lock(gpusvm);
  144. * if (drm_gpusvm_range_pages_valid(range))
  145. * driver_commit_bind(gpusvm, range);
  146. * else
  147. * err = -EAGAIN;
  148. * drm_gpusvm_notifier_unlock(gpusvm);
  149. *
  150. * return err;
  151. * }
  152. *
  153. * int driver_gpu_fault(struct drm_gpusvm *gpusvm, unsigned long fault_addr,
  154. * unsigned long gpuva_start, unsigned long gpuva_end)
  155. * {
  156. * struct drm_gpusvm_ctx ctx = {};
  157. * int err;
  158. *
  159. * driver_svm_lock();
  160. * retry:
  161. * // Always process UNMAPs first so view of GPU SVM ranges is current
  162. * driver_garbage_collector(gpusvm);
  163. *
  164. * range = drm_gpusvm_range_find_or_insert(gpusvm, fault_addr,
  165. * gpuva_start, gpuva_end,
  166. * &ctx);
  167. * if (IS_ERR(range)) {
  168. * err = PTR_ERR(range);
  169. * goto unlock;
  170. * }
  171. *
  172. * if (driver_migration_policy(range)) {
  173. * err = drm_pagemap_populate_mm(driver_choose_drm_pagemap(),
  174. * gpuva_start, gpuva_end, gpusvm->mm,
  175. * ctx->timeslice_ms);
  176. * if (err) // CPU mappings may have changed
  177. * goto retry;
  178. * }
  179. *
  180. * err = drm_gpusvm_range_get_pages(gpusvm, range, &ctx);
  181. * if (err == -EOPNOTSUPP || err == -EFAULT || err == -EPERM) { // CPU mappings changed
  182. * if (err == -EOPNOTSUPP)
  183. * drm_gpusvm_range_evict(gpusvm, range);
  184. * goto retry;
  185. * } else if (err) {
  186. * goto unlock;
  187. * }
  188. *
  189. * err = driver_bind_range(gpusvm, range);
  190. * if (err == -EAGAIN) // CPU mappings changed
  191. * goto retry
  192. *
  193. * unlock:
  194. * driver_svm_unlock();
  195. * return err;
  196. * }
  197. *
  198. * 2) Garbage Collector
  199. *
  200. * .. code-block:: c
  201. *
  202. * void __driver_garbage_collector(struct drm_gpusvm *gpusvm,
  203. * struct drm_gpusvm_range *range)
  204. * {
  205. * assert_driver_svm_locked(gpusvm);
  206. *
  207. * // Partial unmap, migrate any remaining device memory pages back to RAM
  208. * if (range->flags.partial_unmap)
  209. * drm_gpusvm_range_evict(gpusvm, range);
  210. *
  211. * driver_unbind_range(range);
  212. * drm_gpusvm_range_remove(gpusvm, range);
  213. * }
  214. *
  215. * void driver_garbage_collector(struct drm_gpusvm *gpusvm)
  216. * {
  217. * assert_driver_svm_locked(gpusvm);
  218. *
  219. * for_each_range_in_garbage_collector(gpusvm, range)
  220. * __driver_garbage_collector(gpusvm, range);
  221. * }
  222. *
  223. * 3) Notifier callback
  224. *
  225. * .. code-block:: c
  226. *
  227. * void driver_invalidation(struct drm_gpusvm *gpusvm,
  228. * struct drm_gpusvm_notifier *notifier,
  229. * const struct mmu_notifier_range *mmu_range)
  230. * {
  231. * struct drm_gpusvm_ctx ctx = { .in_notifier = true, };
  232. * struct drm_gpusvm_range *range = NULL;
  233. *
  234. * driver_invalidate_device_pages(gpusvm, mmu_range->start, mmu_range->end);
  235. *
  236. * drm_gpusvm_for_each_range(range, notifier, mmu_range->start,
  237. * mmu_range->end) {
  238. * drm_gpusvm_range_unmap_pages(gpusvm, range, &ctx);
  239. *
  240. * if (mmu_range->event != MMU_NOTIFY_UNMAP)
  241. * continue;
  242. *
  243. * drm_gpusvm_range_set_unmapped(range, mmu_range);
  244. * driver_garbage_collector_add(gpusvm, range);
  245. * }
  246. * }
  247. */
  248. /**
  249. * npages_in_range() - Calculate the number of pages in a given range
  250. * @start: The start address of the range
  251. * @end: The end address of the range
  252. *
  253. * This macro calculates the number of pages in a given memory range,
  254. * specified by the start and end addresses. It divides the difference
  255. * between the end and start addresses by the page size (PAGE_SIZE) to
  256. * determine the number of pages in the range.
  257. *
  258. * Return: The number of pages in the specified range.
  259. */
  260. static unsigned long
  261. npages_in_range(unsigned long start, unsigned long end)
  262. {
  263. return (end - start) >> PAGE_SHIFT;
  264. }
  265. /**
  266. * drm_gpusvm_notifier_find() - Find GPU SVM notifier from GPU SVM
  267. * @gpusvm: Pointer to the GPU SVM structure.
  268. * @start: Start address of the notifier
  269. * @end: End address of the notifier
  270. *
  271. * Return: A pointer to the drm_gpusvm_notifier if found or NULL
  272. */
  273. struct drm_gpusvm_notifier *
  274. drm_gpusvm_notifier_find(struct drm_gpusvm *gpusvm, unsigned long start,
  275. unsigned long end)
  276. {
  277. struct interval_tree_node *itree;
  278. itree = interval_tree_iter_first(&gpusvm->root, start, end - 1);
  279. if (itree)
  280. return container_of(itree, struct drm_gpusvm_notifier, itree);
  281. else
  282. return NULL;
  283. }
  284. EXPORT_SYMBOL_GPL(drm_gpusvm_notifier_find);
  285. /**
  286. * drm_gpusvm_range_find() - Find GPU SVM range from GPU SVM notifier
  287. * @notifier: Pointer to the GPU SVM notifier structure.
  288. * @start: Start address of the range
  289. * @end: End address of the range
  290. *
  291. * Return: A pointer to the drm_gpusvm_range if found or NULL
  292. */
  293. struct drm_gpusvm_range *
  294. drm_gpusvm_range_find(struct drm_gpusvm_notifier *notifier, unsigned long start,
  295. unsigned long end)
  296. {
  297. struct interval_tree_node *itree;
  298. itree = interval_tree_iter_first(&notifier->root, start, end - 1);
  299. if (itree)
  300. return container_of(itree, struct drm_gpusvm_range, itree);
  301. else
  302. return NULL;
  303. }
  304. EXPORT_SYMBOL_GPL(drm_gpusvm_range_find);
  305. /**
  306. * drm_gpusvm_notifier_invalidate() - Invalidate a GPU SVM notifier.
  307. * @mni: Pointer to the mmu_interval_notifier structure.
  308. * @mmu_range: Pointer to the mmu_notifier_range structure.
  309. * @cur_seq: Current sequence number.
  310. *
  311. * This function serves as a generic MMU notifier for GPU SVM. It sets the MMU
  312. * notifier sequence number and calls the driver invalidate vfunc under
  313. * gpusvm->notifier_lock.
  314. *
  315. * Return: true if the operation succeeds, false otherwise.
  316. */
  317. static bool
  318. drm_gpusvm_notifier_invalidate(struct mmu_interval_notifier *mni,
  319. const struct mmu_notifier_range *mmu_range,
  320. unsigned long cur_seq)
  321. {
  322. struct drm_gpusvm_notifier *notifier =
  323. container_of(mni, typeof(*notifier), notifier);
  324. struct drm_gpusvm *gpusvm = notifier->gpusvm;
  325. if (!mmu_notifier_range_blockable(mmu_range))
  326. return false;
  327. down_write(&gpusvm->notifier_lock);
  328. mmu_interval_set_seq(mni, cur_seq);
  329. gpusvm->ops->invalidate(gpusvm, notifier, mmu_range);
  330. up_write(&gpusvm->notifier_lock);
  331. return true;
  332. }
  333. /*
  334. * drm_gpusvm_notifier_ops - MMU interval notifier operations for GPU SVM
  335. */
  336. static const struct mmu_interval_notifier_ops drm_gpusvm_notifier_ops = {
  337. .invalidate = drm_gpusvm_notifier_invalidate,
  338. };
  339. /**
  340. * drm_gpusvm_init() - Initialize the GPU SVM.
  341. * @gpusvm: Pointer to the GPU SVM structure.
  342. * @name: Name of the GPU SVM.
  343. * @drm: Pointer to the DRM device structure.
  344. * @mm: Pointer to the mm_struct for the address space.
  345. * @mm_start: Start address of GPU SVM.
  346. * @mm_range: Range of the GPU SVM.
  347. * @notifier_size: Size of individual notifiers.
  348. * @ops: Pointer to the operations structure for GPU SVM.
  349. * @chunk_sizes: Pointer to the array of chunk sizes used in range allocation.
  350. * Entries should be powers of 2 in descending order with last
  351. * entry being SZ_4K.
  352. * @num_chunks: Number of chunks.
  353. *
  354. * This function initializes the GPU SVM.
  355. *
  356. * Note: If only using the simple drm_gpusvm_pages API (get/unmap/free),
  357. * then only @gpusvm, @name, and @drm are expected. However, the same base
  358. * @gpusvm can also be used with both modes together in which case the full
  359. * setup is needed, where the core drm_gpusvm_pages API will simply never use
  360. * the other fields.
  361. *
  362. * Return: 0 on success, a negative error code on failure.
  363. */
  364. int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
  365. const char *name, struct drm_device *drm,
  366. struct mm_struct *mm,
  367. unsigned long mm_start, unsigned long mm_range,
  368. unsigned long notifier_size,
  369. const struct drm_gpusvm_ops *ops,
  370. const unsigned long *chunk_sizes, int num_chunks)
  371. {
  372. if (mm) {
  373. if (!ops->invalidate || !num_chunks)
  374. return -EINVAL;
  375. mmgrab(mm);
  376. } else {
  377. /* No full SVM mode, only core drm_gpusvm_pages API. */
  378. if (ops || num_chunks || mm_range || notifier_size)
  379. return -EINVAL;
  380. }
  381. gpusvm->name = name;
  382. gpusvm->drm = drm;
  383. gpusvm->mm = mm;
  384. gpusvm->mm_start = mm_start;
  385. gpusvm->mm_range = mm_range;
  386. gpusvm->notifier_size = notifier_size;
  387. gpusvm->ops = ops;
  388. gpusvm->chunk_sizes = chunk_sizes;
  389. gpusvm->num_chunks = num_chunks;
  390. gpusvm->root = RB_ROOT_CACHED;
  391. INIT_LIST_HEAD(&gpusvm->notifier_list);
  392. init_rwsem(&gpusvm->notifier_lock);
  393. fs_reclaim_acquire(GFP_KERNEL);
  394. might_lock(&gpusvm->notifier_lock);
  395. fs_reclaim_release(GFP_KERNEL);
  396. #ifdef CONFIG_LOCKDEP
  397. gpusvm->lock_dep_map = NULL;
  398. #endif
  399. return 0;
  400. }
  401. EXPORT_SYMBOL_GPL(drm_gpusvm_init);
  402. /**
  403. * to_drm_gpusvm_notifier() - retrieve the container struct for a given rbtree node
  404. * @node: a pointer to the rbtree node embedded within a drm_gpusvm_notifier struct
  405. *
  406. * Return: A pointer to the containing drm_gpusvm_notifier structure.
  407. */
  408. static struct drm_gpusvm_notifier *to_drm_gpusvm_notifier(struct rb_node *node)
  409. {
  410. return container_of(node, struct drm_gpusvm_notifier, itree.rb);
  411. }
  412. /**
  413. * drm_gpusvm_notifier_insert() - Insert GPU SVM notifier
  414. * @gpusvm: Pointer to the GPU SVM structure
  415. * @notifier: Pointer to the GPU SVM notifier structure
  416. *
  417. * This function inserts the GPU SVM notifier into the GPU SVM RB tree and list.
  418. */
  419. static void drm_gpusvm_notifier_insert(struct drm_gpusvm *gpusvm,
  420. struct drm_gpusvm_notifier *notifier)
  421. {
  422. struct rb_node *node;
  423. struct list_head *head;
  424. interval_tree_insert(&notifier->itree, &gpusvm->root);
  425. node = rb_prev(&notifier->itree.rb);
  426. if (node)
  427. head = &(to_drm_gpusvm_notifier(node))->entry;
  428. else
  429. head = &gpusvm->notifier_list;
  430. list_add(&notifier->entry, head);
  431. }
  432. /**
  433. * drm_gpusvm_notifier_remove() - Remove GPU SVM notifier
  434. * @gpusvm: Pointer to the GPU SVM tructure
  435. * @notifier: Pointer to the GPU SVM notifier structure
  436. *
  437. * This function removes the GPU SVM notifier from the GPU SVM RB tree and list.
  438. */
  439. static void drm_gpusvm_notifier_remove(struct drm_gpusvm *gpusvm,
  440. struct drm_gpusvm_notifier *notifier)
  441. {
  442. interval_tree_remove(&notifier->itree, &gpusvm->root);
  443. list_del(&notifier->entry);
  444. }
  445. /**
  446. * drm_gpusvm_fini() - Finalize the GPU SVM.
  447. * @gpusvm: Pointer to the GPU SVM structure.
  448. *
  449. * This function finalizes the GPU SVM by cleaning up any remaining ranges and
  450. * notifiers, and dropping a reference to struct MM.
  451. */
  452. void drm_gpusvm_fini(struct drm_gpusvm *gpusvm)
  453. {
  454. struct drm_gpusvm_notifier *notifier, *next;
  455. drm_gpusvm_for_each_notifier_safe(notifier, next, gpusvm, 0, LONG_MAX) {
  456. struct drm_gpusvm_range *range, *__next;
  457. /*
  458. * Remove notifier first to avoid racing with any invalidation
  459. */
  460. mmu_interval_notifier_remove(&notifier->notifier);
  461. notifier->flags.removed = true;
  462. drm_gpusvm_for_each_range_safe(range, __next, notifier, 0,
  463. LONG_MAX)
  464. drm_gpusvm_range_remove(gpusvm, range);
  465. }
  466. if (gpusvm->mm)
  467. mmdrop(gpusvm->mm);
  468. WARN_ON(!RB_EMPTY_ROOT(&gpusvm->root.rb_root));
  469. }
  470. EXPORT_SYMBOL_GPL(drm_gpusvm_fini);
  471. /**
  472. * drm_gpusvm_notifier_alloc() - Allocate GPU SVM notifier
  473. * @gpusvm: Pointer to the GPU SVM structure
  474. * @fault_addr: Fault address
  475. *
  476. * This function allocates and initializes the GPU SVM notifier structure.
  477. *
  478. * Return: Pointer to the allocated GPU SVM notifier on success, ERR_PTR() on failure.
  479. */
  480. static struct drm_gpusvm_notifier *
  481. drm_gpusvm_notifier_alloc(struct drm_gpusvm *gpusvm, unsigned long fault_addr)
  482. {
  483. struct drm_gpusvm_notifier *notifier;
  484. if (gpusvm->ops->notifier_alloc)
  485. notifier = gpusvm->ops->notifier_alloc();
  486. else
  487. notifier = kzalloc_obj(*notifier);
  488. if (!notifier)
  489. return ERR_PTR(-ENOMEM);
  490. notifier->gpusvm = gpusvm;
  491. notifier->itree.start = ALIGN_DOWN(fault_addr, gpusvm->notifier_size);
  492. notifier->itree.last = ALIGN(fault_addr + 1, gpusvm->notifier_size) - 1;
  493. INIT_LIST_HEAD(&notifier->entry);
  494. notifier->root = RB_ROOT_CACHED;
  495. INIT_LIST_HEAD(&notifier->range_list);
  496. return notifier;
  497. }
  498. /**
  499. * drm_gpusvm_notifier_free() - Free GPU SVM notifier
  500. * @gpusvm: Pointer to the GPU SVM structure
  501. * @notifier: Pointer to the GPU SVM notifier structure
  502. *
  503. * This function frees the GPU SVM notifier structure.
  504. */
  505. static void drm_gpusvm_notifier_free(struct drm_gpusvm *gpusvm,
  506. struct drm_gpusvm_notifier *notifier)
  507. {
  508. WARN_ON(!RB_EMPTY_ROOT(&notifier->root.rb_root));
  509. if (gpusvm->ops->notifier_free)
  510. gpusvm->ops->notifier_free(notifier);
  511. else
  512. kfree(notifier);
  513. }
  514. /**
  515. * to_drm_gpusvm_range() - retrieve the container struct for a given rbtree node
  516. * @node: a pointer to the rbtree node embedded within a drm_gpusvm_range struct
  517. *
  518. * Return: A pointer to the containing drm_gpusvm_range structure.
  519. */
  520. static struct drm_gpusvm_range *to_drm_gpusvm_range(struct rb_node *node)
  521. {
  522. return container_of(node, struct drm_gpusvm_range, itree.rb);
  523. }
  524. /**
  525. * drm_gpusvm_range_insert() - Insert GPU SVM range
  526. * @notifier: Pointer to the GPU SVM notifier structure
  527. * @range: Pointer to the GPU SVM range structure
  528. *
  529. * This function inserts the GPU SVM range into the notifier RB tree and list.
  530. */
  531. static void drm_gpusvm_range_insert(struct drm_gpusvm_notifier *notifier,
  532. struct drm_gpusvm_range *range)
  533. {
  534. struct rb_node *node;
  535. struct list_head *head;
  536. drm_gpusvm_notifier_lock(notifier->gpusvm);
  537. interval_tree_insert(&range->itree, &notifier->root);
  538. node = rb_prev(&range->itree.rb);
  539. if (node)
  540. head = &(to_drm_gpusvm_range(node))->entry;
  541. else
  542. head = &notifier->range_list;
  543. list_add(&range->entry, head);
  544. drm_gpusvm_notifier_unlock(notifier->gpusvm);
  545. }
  546. /**
  547. * __drm_gpusvm_range_remove() - Remove GPU SVM range
  548. * @notifier: Pointer to the GPU SVM notifier structure
  549. * @range: Pointer to the GPU SVM range structure
  550. *
  551. * This macro removes the GPU SVM range from the notifier RB tree and list.
  552. */
  553. static void __drm_gpusvm_range_remove(struct drm_gpusvm_notifier *notifier,
  554. struct drm_gpusvm_range *range)
  555. {
  556. interval_tree_remove(&range->itree, &notifier->root);
  557. list_del(&range->entry);
  558. }
  559. /**
  560. * drm_gpusvm_range_alloc() - Allocate GPU SVM range
  561. * @gpusvm: Pointer to the GPU SVM structure
  562. * @notifier: Pointer to the GPU SVM notifier structure
  563. * @fault_addr: Fault address
  564. * @chunk_size: Chunk size
  565. * @migrate_devmem: Flag indicating whether to migrate device memory
  566. *
  567. * This function allocates and initializes the GPU SVM range structure.
  568. *
  569. * Return: Pointer to the allocated GPU SVM range on success, ERR_PTR() on failure.
  570. */
  571. static struct drm_gpusvm_range *
  572. drm_gpusvm_range_alloc(struct drm_gpusvm *gpusvm,
  573. struct drm_gpusvm_notifier *notifier,
  574. unsigned long fault_addr, unsigned long chunk_size,
  575. bool migrate_devmem)
  576. {
  577. struct drm_gpusvm_range *range;
  578. if (gpusvm->ops->range_alloc)
  579. range = gpusvm->ops->range_alloc(gpusvm);
  580. else
  581. range = kzalloc_obj(*range);
  582. if (!range)
  583. return ERR_PTR(-ENOMEM);
  584. kref_init(&range->refcount);
  585. range->gpusvm = gpusvm;
  586. range->notifier = notifier;
  587. range->itree.start = ALIGN_DOWN(fault_addr, chunk_size);
  588. range->itree.last = ALIGN(fault_addr + 1, chunk_size) - 1;
  589. INIT_LIST_HEAD(&range->entry);
  590. range->pages.notifier_seq = LONG_MAX;
  591. range->pages.flags.migrate_devmem = migrate_devmem ? 1 : 0;
  592. return range;
  593. }
  594. /**
  595. * drm_gpusvm_hmm_pfn_to_order() - Get the largest CPU mapping order.
  596. * @hmm_pfn: The current hmm_pfn.
  597. * @hmm_pfn_index: Index of the @hmm_pfn within the pfn array.
  598. * @npages: Number of pages within the pfn array i.e the hmm range size.
  599. *
  600. * To allow skipping PFNs with the same flags (like when they belong to
  601. * the same huge PTE) when looping over the pfn array, take a given a hmm_pfn,
  602. * and return the largest order that will fit inside the CPU PTE, but also
  603. * crucially accounting for the original hmm range boundaries.
  604. *
  605. * Return: The largest order that will safely fit within the size of the hmm_pfn
  606. * CPU PTE.
  607. */
  608. static unsigned int drm_gpusvm_hmm_pfn_to_order(unsigned long hmm_pfn,
  609. unsigned long hmm_pfn_index,
  610. unsigned long npages)
  611. {
  612. unsigned long size;
  613. size = 1UL << hmm_pfn_to_map_order(hmm_pfn);
  614. size -= (hmm_pfn & ~HMM_PFN_FLAGS) & (size - 1);
  615. hmm_pfn_index += size;
  616. if (hmm_pfn_index > npages)
  617. size -= (hmm_pfn_index - npages);
  618. return ilog2(size);
  619. }
  620. /**
  621. * drm_gpusvm_check_pages() - Check pages
  622. * @gpusvm: Pointer to the GPU SVM structure
  623. * @notifier: Pointer to the GPU SVM notifier structure
  624. * @start: Start address
  625. * @end: End address
  626. * @dev_private_owner: The device private page owner
  627. *
  628. * Check if pages between start and end have been faulted in on the CPU. Use to
  629. * prevent migration of pages without CPU backing store.
  630. *
  631. * Return: True if pages have been faulted into CPU, False otherwise
  632. */
  633. static bool drm_gpusvm_check_pages(struct drm_gpusvm *gpusvm,
  634. struct drm_gpusvm_notifier *notifier,
  635. unsigned long start, unsigned long end,
  636. void *dev_private_owner)
  637. {
  638. struct hmm_range hmm_range = {
  639. .default_flags = 0,
  640. .notifier = &notifier->notifier,
  641. .start = start,
  642. .end = end,
  643. .dev_private_owner = dev_private_owner,
  644. };
  645. unsigned long timeout =
  646. jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
  647. unsigned long *pfns;
  648. unsigned long npages = npages_in_range(start, end);
  649. int err, i;
  650. mmap_assert_locked(gpusvm->mm);
  651. pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
  652. if (!pfns)
  653. return false;
  654. hmm_range.notifier_seq = mmu_interval_read_begin(&notifier->notifier);
  655. hmm_range.hmm_pfns = pfns;
  656. while (true) {
  657. err = hmm_range_fault(&hmm_range);
  658. if (err == -EBUSY) {
  659. if (time_after(jiffies, timeout))
  660. break;
  661. hmm_range.notifier_seq =
  662. mmu_interval_read_begin(&notifier->notifier);
  663. continue;
  664. }
  665. break;
  666. }
  667. if (err)
  668. goto err_free;
  669. for (i = 0; i < npages;) {
  670. if (!(pfns[i] & HMM_PFN_VALID)) {
  671. err = -EFAULT;
  672. goto err_free;
  673. }
  674. i += 0x1 << drm_gpusvm_hmm_pfn_to_order(pfns[i], i, npages);
  675. }
  676. err_free:
  677. kvfree(pfns);
  678. return err ? false : true;
  679. }
  680. /**
  681. * drm_gpusvm_scan_mm() - Check the migration state of a drm_gpusvm_range
  682. * @range: Pointer to the struct drm_gpusvm_range to check.
  683. * @dev_private_owner: The struct dev_private_owner to use to determine
  684. * compatible device-private pages.
  685. * @pagemap: The struct dev_pagemap pointer to use for pagemap-specific
  686. * checks.
  687. *
  688. * Scan the CPU address space corresponding to @range and return the
  689. * current migration state. Note that the result may be invalid as
  690. * soon as the function returns. It's an advisory check.
  691. *
  692. * TODO: Bail early and call hmm_range_fault() for subranges.
  693. *
  694. * Return: See &enum drm_gpusvm_scan_result.
  695. */
  696. enum drm_gpusvm_scan_result drm_gpusvm_scan_mm(struct drm_gpusvm_range *range,
  697. void *dev_private_owner,
  698. const struct dev_pagemap *pagemap)
  699. {
  700. struct mmu_interval_notifier *notifier = &range->notifier->notifier;
  701. unsigned long start = drm_gpusvm_range_start(range);
  702. unsigned long end = drm_gpusvm_range_end(range);
  703. struct hmm_range hmm_range = {
  704. .default_flags = 0,
  705. .notifier = notifier,
  706. .start = start,
  707. .end = end,
  708. .dev_private_owner = dev_private_owner,
  709. };
  710. unsigned long timeout =
  711. jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
  712. enum drm_gpusvm_scan_result state = DRM_GPUSVM_SCAN_UNPOPULATED, new_state;
  713. unsigned long *pfns;
  714. unsigned long npages = npages_in_range(start, end);
  715. const struct dev_pagemap *other = NULL;
  716. int err, i;
  717. pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
  718. if (!pfns)
  719. return DRM_GPUSVM_SCAN_UNPOPULATED;
  720. hmm_range.hmm_pfns = pfns;
  721. retry:
  722. hmm_range.notifier_seq = mmu_interval_read_begin(notifier);
  723. mmap_read_lock(range->gpusvm->mm);
  724. while (true) {
  725. err = hmm_range_fault(&hmm_range);
  726. if (err == -EBUSY) {
  727. if (time_after(jiffies, timeout))
  728. break;
  729. hmm_range.notifier_seq =
  730. mmu_interval_read_begin(notifier);
  731. continue;
  732. }
  733. break;
  734. }
  735. mmap_read_unlock(range->gpusvm->mm);
  736. if (err)
  737. goto err_free;
  738. drm_gpusvm_notifier_lock(range->gpusvm);
  739. if (mmu_interval_read_retry(notifier, hmm_range.notifier_seq)) {
  740. drm_gpusvm_notifier_unlock(range->gpusvm);
  741. goto retry;
  742. }
  743. for (i = 0; i < npages;) {
  744. struct page *page;
  745. const struct dev_pagemap *cur = NULL;
  746. if (!(pfns[i] & HMM_PFN_VALID)) {
  747. state = DRM_GPUSVM_SCAN_UNPOPULATED;
  748. goto err_free;
  749. }
  750. page = hmm_pfn_to_page(pfns[i]);
  751. if (is_device_private_page(page) ||
  752. is_device_coherent_page(page))
  753. cur = page_pgmap(page);
  754. if (cur == pagemap) {
  755. new_state = DRM_GPUSVM_SCAN_EQUAL;
  756. } else if (cur && (cur == other || !other)) {
  757. new_state = DRM_GPUSVM_SCAN_OTHER;
  758. other = cur;
  759. } else if (cur) {
  760. new_state = DRM_GPUSVM_SCAN_MIXED_DEVICE;
  761. } else {
  762. new_state = DRM_GPUSVM_SCAN_SYSTEM;
  763. }
  764. /*
  765. * TODO: Could use an array for state
  766. * transitions, and caller might want it
  767. * to bail early for some results.
  768. */
  769. if (state == DRM_GPUSVM_SCAN_UNPOPULATED) {
  770. state = new_state;
  771. } else if (state != new_state) {
  772. if (new_state == DRM_GPUSVM_SCAN_SYSTEM ||
  773. state == DRM_GPUSVM_SCAN_SYSTEM)
  774. state = DRM_GPUSVM_SCAN_MIXED;
  775. else if (state != DRM_GPUSVM_SCAN_MIXED)
  776. state = DRM_GPUSVM_SCAN_MIXED_DEVICE;
  777. }
  778. i += 1ul << drm_gpusvm_hmm_pfn_to_order(pfns[i], i, npages);
  779. }
  780. err_free:
  781. drm_gpusvm_notifier_unlock(range->gpusvm);
  782. kvfree(pfns);
  783. return state;
  784. }
  785. EXPORT_SYMBOL(drm_gpusvm_scan_mm);
  786. /**
  787. * drm_gpusvm_range_chunk_size() - Determine chunk size for GPU SVM range
  788. * @gpusvm: Pointer to the GPU SVM structure
  789. * @notifier: Pointer to the GPU SVM notifier structure
  790. * @vas: Pointer to the virtual memory area structure
  791. * @fault_addr: Fault address
  792. * @gpuva_start: Start address of GPUVA which mirrors CPU
  793. * @gpuva_end: End address of GPUVA which mirrors CPU
  794. * @check_pages_threshold: Check CPU pages for present threshold
  795. * @dev_private_owner: The device private page owner
  796. *
  797. * This function determines the chunk size for the GPU SVM range based on the
  798. * fault address, GPU SVM chunk sizes, existing GPU SVM ranges, and the virtual
  799. * memory area boundaries.
  800. *
  801. * Return: Chunk size on success, LONG_MAX on failure.
  802. */
  803. static unsigned long
  804. drm_gpusvm_range_chunk_size(struct drm_gpusvm *gpusvm,
  805. struct drm_gpusvm_notifier *notifier,
  806. struct vm_area_struct *vas,
  807. unsigned long fault_addr,
  808. unsigned long gpuva_start,
  809. unsigned long gpuva_end,
  810. unsigned long check_pages_threshold,
  811. void *dev_private_owner)
  812. {
  813. unsigned long start, end;
  814. int i = 0;
  815. retry:
  816. for (; i < gpusvm->num_chunks; ++i) {
  817. start = ALIGN_DOWN(fault_addr, gpusvm->chunk_sizes[i]);
  818. end = ALIGN(fault_addr + 1, gpusvm->chunk_sizes[i]);
  819. if (start >= vas->vm_start && end <= vas->vm_end &&
  820. start >= drm_gpusvm_notifier_start(notifier) &&
  821. end <= drm_gpusvm_notifier_end(notifier) &&
  822. start >= gpuva_start && end <= gpuva_end)
  823. break;
  824. }
  825. if (i == gpusvm->num_chunks)
  826. return LONG_MAX;
  827. /*
  828. * If allocation more than page, ensure not to overlap with existing
  829. * ranges.
  830. */
  831. if (end - start != SZ_4K) {
  832. struct drm_gpusvm_range *range;
  833. range = drm_gpusvm_range_find(notifier, start, end);
  834. if (range) {
  835. ++i;
  836. goto retry;
  837. }
  838. /*
  839. * XXX: Only create range on pages CPU has faulted in. Without
  840. * this check, or prefault, on BMG 'xe_exec_system_allocator --r
  841. * process-many-malloc' fails. In the failure case, each process
  842. * mallocs 16k but the CPU VMA is ~128k which results in 64k SVM
  843. * ranges. When migrating the SVM ranges, some processes fail in
  844. * drm_pagemap_migrate_to_devmem with 'migrate.cpages != npages'
  845. * and then upon drm_gpusvm_range_get_pages device pages from
  846. * other processes are collected + faulted in which creates all
  847. * sorts of problems. Unsure exactly how this happening, also
  848. * problem goes away if 'xe_exec_system_allocator --r
  849. * process-many-malloc' mallocs at least 64k at a time.
  850. */
  851. if (end - start <= check_pages_threshold &&
  852. !drm_gpusvm_check_pages(gpusvm, notifier, start, end, dev_private_owner)) {
  853. ++i;
  854. goto retry;
  855. }
  856. }
  857. return end - start;
  858. }
  859. #ifdef CONFIG_LOCKDEP
  860. /**
  861. * drm_gpusvm_driver_lock_held() - Assert GPU SVM driver lock is held
  862. * @gpusvm: Pointer to the GPU SVM structure.
  863. *
  864. * Ensure driver lock is held.
  865. */
  866. static void drm_gpusvm_driver_lock_held(struct drm_gpusvm *gpusvm)
  867. {
  868. if ((gpusvm)->lock_dep_map)
  869. lockdep_assert(lock_is_held_type((gpusvm)->lock_dep_map, 0));
  870. }
  871. #else
  872. static void drm_gpusvm_driver_lock_held(struct drm_gpusvm *gpusvm)
  873. {
  874. }
  875. #endif
  876. /**
  877. * drm_gpusvm_find_vma_start() - Find start address for first VMA in range
  878. * @gpusvm: Pointer to the GPU SVM structure
  879. * @start: The inclusive start user address.
  880. * @end: The exclusive end user address.
  881. *
  882. * Returns: The start address of first VMA within the provided range,
  883. * ULONG_MAX otherwise. Assumes start_addr < end_addr.
  884. */
  885. unsigned long
  886. drm_gpusvm_find_vma_start(struct drm_gpusvm *gpusvm,
  887. unsigned long start,
  888. unsigned long end)
  889. {
  890. struct mm_struct *mm = gpusvm->mm;
  891. struct vm_area_struct *vma;
  892. unsigned long addr = ULONG_MAX;
  893. if (!mmget_not_zero(mm))
  894. return addr;
  895. mmap_read_lock(mm);
  896. vma = find_vma_intersection(mm, start, end);
  897. if (vma)
  898. addr = vma->vm_start;
  899. mmap_read_unlock(mm);
  900. mmput(mm);
  901. return addr;
  902. }
  903. EXPORT_SYMBOL_GPL(drm_gpusvm_find_vma_start);
  904. /**
  905. * drm_gpusvm_range_find_or_insert() - Find or insert GPU SVM range
  906. * @gpusvm: Pointer to the GPU SVM structure
  907. * @fault_addr: Fault address
  908. * @gpuva_start: Start address of GPUVA which mirrors CPU
  909. * @gpuva_end: End address of GPUVA which mirrors CPU
  910. * @ctx: GPU SVM context
  911. *
  912. * This function finds or inserts a newly allocated a GPU SVM range based on the
  913. * fault address. Caller must hold a lock to protect range lookup and insertion.
  914. *
  915. * Return: Pointer to the GPU SVM range on success, ERR_PTR() on failure.
  916. */
  917. struct drm_gpusvm_range *
  918. drm_gpusvm_range_find_or_insert(struct drm_gpusvm *gpusvm,
  919. unsigned long fault_addr,
  920. unsigned long gpuva_start,
  921. unsigned long gpuva_end,
  922. const struct drm_gpusvm_ctx *ctx)
  923. {
  924. struct drm_gpusvm_notifier *notifier;
  925. struct drm_gpusvm_range *range;
  926. struct mm_struct *mm = gpusvm->mm;
  927. struct vm_area_struct *vas;
  928. bool notifier_alloc = false;
  929. unsigned long chunk_size;
  930. int err;
  931. bool migrate_devmem;
  932. drm_gpusvm_driver_lock_held(gpusvm);
  933. if (fault_addr < gpusvm->mm_start ||
  934. fault_addr > gpusvm->mm_start + gpusvm->mm_range)
  935. return ERR_PTR(-EINVAL);
  936. if (!mmget_not_zero(mm))
  937. return ERR_PTR(-EFAULT);
  938. notifier = drm_gpusvm_notifier_find(gpusvm, fault_addr, fault_addr + 1);
  939. if (!notifier) {
  940. notifier = drm_gpusvm_notifier_alloc(gpusvm, fault_addr);
  941. if (IS_ERR(notifier)) {
  942. err = PTR_ERR(notifier);
  943. goto err_mmunlock;
  944. }
  945. notifier_alloc = true;
  946. err = mmu_interval_notifier_insert(&notifier->notifier,
  947. mm,
  948. drm_gpusvm_notifier_start(notifier),
  949. drm_gpusvm_notifier_size(notifier),
  950. &drm_gpusvm_notifier_ops);
  951. if (err)
  952. goto err_notifier;
  953. }
  954. mmap_read_lock(mm);
  955. vas = vma_lookup(mm, fault_addr);
  956. if (!vas) {
  957. err = -ENOENT;
  958. goto err_notifier_remove;
  959. }
  960. if (!ctx->read_only && !(vas->vm_flags & VM_WRITE)) {
  961. err = -EPERM;
  962. goto err_notifier_remove;
  963. }
  964. range = drm_gpusvm_range_find(notifier, fault_addr, fault_addr + 1);
  965. if (range)
  966. goto out_mmunlock;
  967. /*
  968. * XXX: Short-circuiting migration based on migrate_vma_* current
  969. * limitations. If/when migrate_vma_* add more support, this logic will
  970. * have to change.
  971. */
  972. migrate_devmem = ctx->devmem_possible &&
  973. vma_is_anonymous(vas) && !is_vm_hugetlb_page(vas);
  974. chunk_size = drm_gpusvm_range_chunk_size(gpusvm, notifier, vas,
  975. fault_addr, gpuva_start,
  976. gpuva_end,
  977. ctx->check_pages_threshold,
  978. ctx->device_private_page_owner);
  979. if (chunk_size == LONG_MAX) {
  980. err = -EINVAL;
  981. goto err_notifier_remove;
  982. }
  983. range = drm_gpusvm_range_alloc(gpusvm, notifier, fault_addr, chunk_size,
  984. migrate_devmem);
  985. if (IS_ERR(range)) {
  986. err = PTR_ERR(range);
  987. goto err_notifier_remove;
  988. }
  989. drm_gpusvm_range_insert(notifier, range);
  990. if (notifier_alloc)
  991. drm_gpusvm_notifier_insert(gpusvm, notifier);
  992. out_mmunlock:
  993. mmap_read_unlock(mm);
  994. mmput(mm);
  995. return range;
  996. err_notifier_remove:
  997. mmap_read_unlock(mm);
  998. if (notifier_alloc)
  999. mmu_interval_notifier_remove(&notifier->notifier);
  1000. err_notifier:
  1001. if (notifier_alloc)
  1002. drm_gpusvm_notifier_free(gpusvm, notifier);
  1003. err_mmunlock:
  1004. mmput(mm);
  1005. return ERR_PTR(err);
  1006. }
  1007. EXPORT_SYMBOL_GPL(drm_gpusvm_range_find_or_insert);
  1008. /**
  1009. * __drm_gpusvm_unmap_pages() - Unmap pages associated with GPU SVM pages (internal)
  1010. * @gpusvm: Pointer to the GPU SVM structure
  1011. * @svm_pages: Pointer to the GPU SVM pages structure
  1012. * @npages: Number of pages to unmap
  1013. *
  1014. * This function unmap pages associated with a GPU SVM pages struct. Assumes and
  1015. * asserts correct locking is in place when called.
  1016. */
  1017. static void __drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
  1018. struct drm_gpusvm_pages *svm_pages,
  1019. unsigned long npages)
  1020. {
  1021. struct drm_pagemap *dpagemap = svm_pages->dpagemap;
  1022. struct device *dev = gpusvm->drm->dev;
  1023. unsigned long i, j;
  1024. lockdep_assert_held(&gpusvm->notifier_lock);
  1025. if (svm_pages->flags.has_dma_mapping) {
  1026. struct drm_gpusvm_pages_flags flags = {
  1027. .__flags = svm_pages->flags.__flags,
  1028. };
  1029. for (i = 0, j = 0; i < npages; j++) {
  1030. struct drm_pagemap_addr *addr = &svm_pages->dma_addr[j];
  1031. if (addr->proto == DRM_INTERCONNECT_SYSTEM)
  1032. dma_unmap_page(dev,
  1033. addr->addr,
  1034. PAGE_SIZE << addr->order,
  1035. addr->dir);
  1036. else if (dpagemap && dpagemap->ops->device_unmap)
  1037. dpagemap->ops->device_unmap(dpagemap,
  1038. dev, addr);
  1039. i += 1 << addr->order;
  1040. }
  1041. /* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */
  1042. flags.has_devmem_pages = false;
  1043. flags.has_dma_mapping = false;
  1044. WRITE_ONCE(svm_pages->flags.__flags, flags.__flags);
  1045. drm_pagemap_put(svm_pages->dpagemap);
  1046. svm_pages->dpagemap = NULL;
  1047. }
  1048. }
  1049. /**
  1050. * __drm_gpusvm_free_pages() - Free dma array associated with GPU SVM pages
  1051. * @gpusvm: Pointer to the GPU SVM structure
  1052. * @svm_pages: Pointer to the GPU SVM pages structure
  1053. *
  1054. * This function frees the dma address array associated with a GPU SVM range.
  1055. */
  1056. static void __drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
  1057. struct drm_gpusvm_pages *svm_pages)
  1058. {
  1059. lockdep_assert_held(&gpusvm->notifier_lock);
  1060. if (svm_pages->dma_addr) {
  1061. kvfree(svm_pages->dma_addr);
  1062. svm_pages->dma_addr = NULL;
  1063. }
  1064. }
  1065. /**
  1066. * drm_gpusvm_free_pages() - Free dma-mapping associated with GPU SVM pages
  1067. * struct
  1068. * @gpusvm: Pointer to the GPU SVM structure
  1069. * @svm_pages: Pointer to the GPU SVM pages structure
  1070. * @npages: Number of mapped pages
  1071. *
  1072. * This function unmaps and frees the dma address array associated with a GPU
  1073. * SVM pages struct.
  1074. */
  1075. void drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
  1076. struct drm_gpusvm_pages *svm_pages,
  1077. unsigned long npages)
  1078. {
  1079. drm_gpusvm_notifier_lock(gpusvm);
  1080. __drm_gpusvm_unmap_pages(gpusvm, svm_pages, npages);
  1081. __drm_gpusvm_free_pages(gpusvm, svm_pages);
  1082. drm_gpusvm_notifier_unlock(gpusvm);
  1083. }
  1084. EXPORT_SYMBOL_GPL(drm_gpusvm_free_pages);
  1085. /**
  1086. * drm_gpusvm_range_remove() - Remove GPU SVM range
  1087. * @gpusvm: Pointer to the GPU SVM structure
  1088. * @range: Pointer to the GPU SVM range to be removed
  1089. *
  1090. * This function removes the specified GPU SVM range and also removes the parent
  1091. * GPU SVM notifier if no more ranges remain in the notifier. The caller must
  1092. * hold a lock to protect range and notifier removal.
  1093. */
  1094. void drm_gpusvm_range_remove(struct drm_gpusvm *gpusvm,
  1095. struct drm_gpusvm_range *range)
  1096. {
  1097. unsigned long npages = npages_in_range(drm_gpusvm_range_start(range),
  1098. drm_gpusvm_range_end(range));
  1099. struct drm_gpusvm_notifier *notifier;
  1100. drm_gpusvm_driver_lock_held(gpusvm);
  1101. notifier = drm_gpusvm_notifier_find(gpusvm,
  1102. drm_gpusvm_range_start(range),
  1103. drm_gpusvm_range_start(range) + 1);
  1104. if (WARN_ON_ONCE(!notifier))
  1105. return;
  1106. drm_gpusvm_notifier_lock(gpusvm);
  1107. __drm_gpusvm_unmap_pages(gpusvm, &range->pages, npages);
  1108. __drm_gpusvm_free_pages(gpusvm, &range->pages);
  1109. __drm_gpusvm_range_remove(notifier, range);
  1110. drm_gpusvm_notifier_unlock(gpusvm);
  1111. drm_gpusvm_range_put(range);
  1112. if (RB_EMPTY_ROOT(&notifier->root.rb_root)) {
  1113. if (!notifier->flags.removed)
  1114. mmu_interval_notifier_remove(&notifier->notifier);
  1115. drm_gpusvm_notifier_remove(gpusvm, notifier);
  1116. drm_gpusvm_notifier_free(gpusvm, notifier);
  1117. }
  1118. }
  1119. EXPORT_SYMBOL_GPL(drm_gpusvm_range_remove);
  1120. /**
  1121. * drm_gpusvm_range_get() - Get a reference to GPU SVM range
  1122. * @range: Pointer to the GPU SVM range
  1123. *
  1124. * This function increments the reference count of the specified GPU SVM range.
  1125. *
  1126. * Return: Pointer to the GPU SVM range.
  1127. */
  1128. struct drm_gpusvm_range *
  1129. drm_gpusvm_range_get(struct drm_gpusvm_range *range)
  1130. {
  1131. kref_get(&range->refcount);
  1132. return range;
  1133. }
  1134. EXPORT_SYMBOL_GPL(drm_gpusvm_range_get);
  1135. /**
  1136. * drm_gpusvm_range_destroy() - Destroy GPU SVM range
  1137. * @refcount: Pointer to the reference counter embedded in the GPU SVM range
  1138. *
  1139. * This function destroys the specified GPU SVM range when its reference count
  1140. * reaches zero. If a custom range-free function is provided, it is invoked to
  1141. * free the range; otherwise, the range is deallocated using kfree().
  1142. */
  1143. static void drm_gpusvm_range_destroy(struct kref *refcount)
  1144. {
  1145. struct drm_gpusvm_range *range =
  1146. container_of(refcount, struct drm_gpusvm_range, refcount);
  1147. struct drm_gpusvm *gpusvm = range->gpusvm;
  1148. if (gpusvm->ops->range_free)
  1149. gpusvm->ops->range_free(range);
  1150. else
  1151. kfree(range);
  1152. }
  1153. /**
  1154. * drm_gpusvm_range_put() - Put a reference to GPU SVM range
  1155. * @range: Pointer to the GPU SVM range
  1156. *
  1157. * This function decrements the reference count of the specified GPU SVM range
  1158. * and frees it when the count reaches zero.
  1159. */
  1160. void drm_gpusvm_range_put(struct drm_gpusvm_range *range)
  1161. {
  1162. kref_put(&range->refcount, drm_gpusvm_range_destroy);
  1163. }
  1164. EXPORT_SYMBOL_GPL(drm_gpusvm_range_put);
  1165. /**
  1166. * drm_gpusvm_pages_valid() - GPU SVM range pages valid
  1167. * @gpusvm: Pointer to the GPU SVM structure
  1168. * @svm_pages: Pointer to the GPU SVM pages structure
  1169. *
  1170. * This function determines if a GPU SVM range pages are valid. Expected be
  1171. * called holding gpusvm->notifier_lock and as the last step before committing a
  1172. * GPU binding. This is akin to a notifier seqno check in the HMM documentation
  1173. * but due to wider notifiers (i.e., notifiers which span multiple ranges) this
  1174. * function is required for finer grained checking (i.e., per range) if pages
  1175. * are valid.
  1176. *
  1177. * Return: True if GPU SVM range has valid pages, False otherwise
  1178. */
  1179. static bool drm_gpusvm_pages_valid(struct drm_gpusvm *gpusvm,
  1180. struct drm_gpusvm_pages *svm_pages)
  1181. {
  1182. lockdep_assert_held(&gpusvm->notifier_lock);
  1183. return svm_pages->flags.has_devmem_pages || svm_pages->flags.has_dma_mapping;
  1184. }
  1185. /**
  1186. * drm_gpusvm_range_pages_valid() - GPU SVM range pages valid
  1187. * @gpusvm: Pointer to the GPU SVM structure
  1188. * @range: Pointer to the GPU SVM range structure
  1189. *
  1190. * This function determines if a GPU SVM range pages are valid. Expected be
  1191. * called holding gpusvm->notifier_lock and as the last step before committing a
  1192. * GPU binding. This is akin to a notifier seqno check in the HMM documentation
  1193. * but due to wider notifiers (i.e., notifiers which span multiple ranges) this
  1194. * function is required for finer grained checking (i.e., per range) if pages
  1195. * are valid.
  1196. *
  1197. * Return: True if GPU SVM range has valid pages, False otherwise
  1198. */
  1199. bool drm_gpusvm_range_pages_valid(struct drm_gpusvm *gpusvm,
  1200. struct drm_gpusvm_range *range)
  1201. {
  1202. return drm_gpusvm_pages_valid(gpusvm, &range->pages);
  1203. }
  1204. EXPORT_SYMBOL_GPL(drm_gpusvm_range_pages_valid);
  1205. /**
  1206. * drm_gpusvm_pages_valid_unlocked() - GPU SVM pages valid unlocked
  1207. * @gpusvm: Pointer to the GPU SVM structure
  1208. * @svm_pages: Pointer to the GPU SVM pages structure
  1209. *
  1210. * This function determines if a GPU SVM pages are valid. Expected be called
  1211. * without holding gpusvm->notifier_lock.
  1212. *
  1213. * Return: True if GPU SVM pages are valid, False otherwise
  1214. */
  1215. static bool drm_gpusvm_pages_valid_unlocked(struct drm_gpusvm *gpusvm,
  1216. struct drm_gpusvm_pages *svm_pages)
  1217. {
  1218. bool pages_valid;
  1219. if (!svm_pages->dma_addr)
  1220. return false;
  1221. drm_gpusvm_notifier_lock(gpusvm);
  1222. pages_valid = drm_gpusvm_pages_valid(gpusvm, svm_pages);
  1223. if (!pages_valid)
  1224. __drm_gpusvm_free_pages(gpusvm, svm_pages);
  1225. drm_gpusvm_notifier_unlock(gpusvm);
  1226. return pages_valid;
  1227. }
  1228. /**
  1229. * drm_gpusvm_get_pages() - Get pages and populate GPU SVM pages struct
  1230. * @gpusvm: Pointer to the GPU SVM structure
  1231. * @svm_pages: The SVM pages to populate. This will contain the dma-addresses
  1232. * @mm: The mm corresponding to the CPU range
  1233. * @notifier: The corresponding notifier for the given CPU range
  1234. * @pages_start: Start CPU address for the pages
  1235. * @pages_end: End CPU address for the pages (exclusive)
  1236. * @ctx: GPU SVM context
  1237. *
  1238. * This function gets and maps pages for CPU range and ensures they are
  1239. * mapped for DMA access.
  1240. *
  1241. * Return: 0 on success, negative error code on failure.
  1242. */
  1243. int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
  1244. struct drm_gpusvm_pages *svm_pages,
  1245. struct mm_struct *mm,
  1246. struct mmu_interval_notifier *notifier,
  1247. unsigned long pages_start, unsigned long pages_end,
  1248. const struct drm_gpusvm_ctx *ctx)
  1249. {
  1250. struct hmm_range hmm_range = {
  1251. .default_flags = HMM_PFN_REQ_FAULT | (ctx->read_only ? 0 :
  1252. HMM_PFN_REQ_WRITE),
  1253. .notifier = notifier,
  1254. .start = pages_start,
  1255. .end = pages_end,
  1256. .dev_private_owner = ctx->device_private_page_owner,
  1257. };
  1258. void *zdd;
  1259. unsigned long timeout =
  1260. jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
  1261. unsigned long i, j;
  1262. unsigned long npages = npages_in_range(pages_start, pages_end);
  1263. unsigned long num_dma_mapped;
  1264. unsigned int order = 0;
  1265. unsigned long *pfns;
  1266. int err = 0;
  1267. struct dev_pagemap *pagemap;
  1268. struct drm_pagemap *dpagemap;
  1269. struct drm_gpusvm_pages_flags flags;
  1270. enum dma_data_direction dma_dir = ctx->read_only ? DMA_TO_DEVICE :
  1271. DMA_BIDIRECTIONAL;
  1272. retry:
  1273. if (time_after(jiffies, timeout))
  1274. return -EBUSY;
  1275. hmm_range.notifier_seq = mmu_interval_read_begin(notifier);
  1276. if (drm_gpusvm_pages_valid_unlocked(gpusvm, svm_pages))
  1277. goto set_seqno;
  1278. pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
  1279. if (!pfns)
  1280. return -ENOMEM;
  1281. if (!mmget_not_zero(mm)) {
  1282. err = -EFAULT;
  1283. goto err_free;
  1284. }
  1285. hmm_range.hmm_pfns = pfns;
  1286. while (true) {
  1287. mmap_read_lock(mm);
  1288. err = hmm_range_fault(&hmm_range);
  1289. mmap_read_unlock(mm);
  1290. if (err == -EBUSY) {
  1291. if (time_after(jiffies, timeout))
  1292. break;
  1293. hmm_range.notifier_seq =
  1294. mmu_interval_read_begin(notifier);
  1295. continue;
  1296. }
  1297. break;
  1298. }
  1299. mmput(mm);
  1300. if (err)
  1301. goto err_free;
  1302. map_pages:
  1303. /*
  1304. * Perform all dma mappings under the notifier lock to not
  1305. * access freed pages. A notifier will either block on
  1306. * the notifier lock or unmap dma.
  1307. */
  1308. drm_gpusvm_notifier_lock(gpusvm);
  1309. flags.__flags = svm_pages->flags.__flags;
  1310. if (flags.unmapped) {
  1311. drm_gpusvm_notifier_unlock(gpusvm);
  1312. err = -EFAULT;
  1313. goto err_free;
  1314. }
  1315. if (mmu_interval_read_retry(notifier, hmm_range.notifier_seq)) {
  1316. drm_gpusvm_notifier_unlock(gpusvm);
  1317. kvfree(pfns);
  1318. goto retry;
  1319. }
  1320. if (!svm_pages->dma_addr) {
  1321. /* Unlock and restart mapping to allocate memory. */
  1322. drm_gpusvm_notifier_unlock(gpusvm);
  1323. svm_pages->dma_addr =
  1324. kvmalloc_objs(*svm_pages->dma_addr, npages);
  1325. if (!svm_pages->dma_addr) {
  1326. err = -ENOMEM;
  1327. goto err_free;
  1328. }
  1329. goto map_pages;
  1330. }
  1331. zdd = NULL;
  1332. pagemap = NULL;
  1333. num_dma_mapped = 0;
  1334. for (i = 0, j = 0; i < npages; ++j) {
  1335. struct page *page = hmm_pfn_to_page(pfns[i]);
  1336. order = drm_gpusvm_hmm_pfn_to_order(pfns[i], i, npages);
  1337. if (is_device_private_page(page) ||
  1338. is_device_coherent_page(page)) {
  1339. if (!ctx->allow_mixed &&
  1340. zdd != page->zone_device_data && i > 0) {
  1341. err = -EOPNOTSUPP;
  1342. goto err_unmap;
  1343. }
  1344. zdd = page->zone_device_data;
  1345. if (pagemap != page_pgmap(page)) {
  1346. if (i > 0) {
  1347. err = -EOPNOTSUPP;
  1348. goto err_unmap;
  1349. }
  1350. pagemap = page_pgmap(page);
  1351. dpagemap = drm_pagemap_page_to_dpagemap(page);
  1352. if (drm_WARN_ON(gpusvm->drm, !dpagemap)) {
  1353. /*
  1354. * Raced. This is not supposed to happen
  1355. * since hmm_range_fault() should've migrated
  1356. * this page to system.
  1357. */
  1358. err = -EAGAIN;
  1359. goto err_unmap;
  1360. }
  1361. }
  1362. svm_pages->dma_addr[j] =
  1363. dpagemap->ops->device_map(dpagemap,
  1364. gpusvm->drm->dev,
  1365. page, order,
  1366. dma_dir);
  1367. if (dma_mapping_error(gpusvm->drm->dev,
  1368. svm_pages->dma_addr[j].addr)) {
  1369. err = -EFAULT;
  1370. goto err_unmap;
  1371. }
  1372. } else {
  1373. dma_addr_t addr;
  1374. if (is_zone_device_page(page) ||
  1375. (pagemap && !ctx->allow_mixed)) {
  1376. err = -EOPNOTSUPP;
  1377. goto err_unmap;
  1378. }
  1379. if (ctx->devmem_only) {
  1380. err = -EFAULT;
  1381. goto err_unmap;
  1382. }
  1383. addr = dma_map_page(gpusvm->drm->dev,
  1384. page, 0,
  1385. PAGE_SIZE << order,
  1386. dma_dir);
  1387. if (dma_mapping_error(gpusvm->drm->dev, addr)) {
  1388. err = -EFAULT;
  1389. goto err_unmap;
  1390. }
  1391. svm_pages->dma_addr[j] = drm_pagemap_addr_encode
  1392. (addr, DRM_INTERCONNECT_SYSTEM, order,
  1393. dma_dir);
  1394. }
  1395. i += 1 << order;
  1396. num_dma_mapped = i;
  1397. flags.has_dma_mapping = true;
  1398. }
  1399. if (pagemap) {
  1400. flags.has_devmem_pages = true;
  1401. drm_pagemap_get(dpagemap);
  1402. drm_pagemap_put(svm_pages->dpagemap);
  1403. svm_pages->dpagemap = dpagemap;
  1404. }
  1405. /* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */
  1406. WRITE_ONCE(svm_pages->flags.__flags, flags.__flags);
  1407. drm_gpusvm_notifier_unlock(gpusvm);
  1408. kvfree(pfns);
  1409. set_seqno:
  1410. svm_pages->notifier_seq = hmm_range.notifier_seq;
  1411. return 0;
  1412. err_unmap:
  1413. __drm_gpusvm_unmap_pages(gpusvm, svm_pages, num_dma_mapped);
  1414. drm_gpusvm_notifier_unlock(gpusvm);
  1415. err_free:
  1416. kvfree(pfns);
  1417. if (err == -EAGAIN)
  1418. goto retry;
  1419. return err;
  1420. }
  1421. EXPORT_SYMBOL_GPL(drm_gpusvm_get_pages);
  1422. /**
  1423. * drm_gpusvm_range_get_pages() - Get pages for a GPU SVM range
  1424. * @gpusvm: Pointer to the GPU SVM structure
  1425. * @range: Pointer to the GPU SVM range structure
  1426. * @ctx: GPU SVM context
  1427. *
  1428. * This function gets pages for a GPU SVM range and ensures they are mapped for
  1429. * DMA access.
  1430. *
  1431. * Return: 0 on success, negative error code on failure.
  1432. */
  1433. int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
  1434. struct drm_gpusvm_range *range,
  1435. const struct drm_gpusvm_ctx *ctx)
  1436. {
  1437. return drm_gpusvm_get_pages(gpusvm, &range->pages, gpusvm->mm,
  1438. &range->notifier->notifier,
  1439. drm_gpusvm_range_start(range),
  1440. drm_gpusvm_range_end(range), ctx);
  1441. }
  1442. EXPORT_SYMBOL_GPL(drm_gpusvm_range_get_pages);
  1443. /**
  1444. * drm_gpusvm_unmap_pages() - Unmap GPU svm pages
  1445. * @gpusvm: Pointer to the GPU SVM structure
  1446. * @svm_pages: Pointer to the GPU SVM pages structure
  1447. * @npages: Number of pages in @svm_pages.
  1448. * @ctx: GPU SVM context
  1449. *
  1450. * This function unmaps pages associated with a GPU SVM pages struct. If
  1451. * @in_notifier is set, it is assumed that gpusvm->notifier_lock is held in
  1452. * write mode; if it is clear, it acquires gpusvm->notifier_lock in read mode.
  1453. * Must be called in the invalidate() callback of the corresponding notifier for
  1454. * IOMMU security model.
  1455. */
  1456. void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
  1457. struct drm_gpusvm_pages *svm_pages,
  1458. unsigned long npages,
  1459. const struct drm_gpusvm_ctx *ctx)
  1460. {
  1461. if (ctx->in_notifier)
  1462. lockdep_assert_held_write(&gpusvm->notifier_lock);
  1463. else
  1464. drm_gpusvm_notifier_lock(gpusvm);
  1465. __drm_gpusvm_unmap_pages(gpusvm, svm_pages, npages);
  1466. if (!ctx->in_notifier)
  1467. drm_gpusvm_notifier_unlock(gpusvm);
  1468. }
  1469. EXPORT_SYMBOL_GPL(drm_gpusvm_unmap_pages);
  1470. /**
  1471. * drm_gpusvm_range_unmap_pages() - Unmap pages associated with a GPU SVM range
  1472. * @gpusvm: Pointer to the GPU SVM structure
  1473. * @range: Pointer to the GPU SVM range structure
  1474. * @ctx: GPU SVM context
  1475. *
  1476. * This function unmaps pages associated with a GPU SVM range. If @in_notifier
  1477. * is set, it is assumed that gpusvm->notifier_lock is held in write mode; if it
  1478. * is clear, it acquires gpusvm->notifier_lock in read mode. Must be called on
  1479. * each GPU SVM range attached to notifier in gpusvm->ops->invalidate for IOMMU
  1480. * security model.
  1481. */
  1482. void drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
  1483. struct drm_gpusvm_range *range,
  1484. const struct drm_gpusvm_ctx *ctx)
  1485. {
  1486. unsigned long npages = npages_in_range(drm_gpusvm_range_start(range),
  1487. drm_gpusvm_range_end(range));
  1488. return drm_gpusvm_unmap_pages(gpusvm, &range->pages, npages, ctx);
  1489. }
  1490. EXPORT_SYMBOL_GPL(drm_gpusvm_range_unmap_pages);
  1491. /**
  1492. * drm_gpusvm_range_evict() - Evict GPU SVM range
  1493. * @gpusvm: Pointer to the GPU SVM structure
  1494. * @range: Pointer to the GPU SVM range to be removed
  1495. *
  1496. * This function evicts the specified GPU SVM range.
  1497. *
  1498. * Return: 0 on success, a negative error code on failure.
  1499. */
  1500. int drm_gpusvm_range_evict(struct drm_gpusvm *gpusvm,
  1501. struct drm_gpusvm_range *range)
  1502. {
  1503. struct mmu_interval_notifier *notifier = &range->notifier->notifier;
  1504. struct hmm_range hmm_range = {
  1505. .default_flags = HMM_PFN_REQ_FAULT,
  1506. .notifier = notifier,
  1507. .start = drm_gpusvm_range_start(range),
  1508. .end = drm_gpusvm_range_end(range),
  1509. .dev_private_owner = NULL,
  1510. };
  1511. unsigned long timeout =
  1512. jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
  1513. unsigned long *pfns;
  1514. unsigned long npages = npages_in_range(drm_gpusvm_range_start(range),
  1515. drm_gpusvm_range_end(range));
  1516. int err = 0;
  1517. struct mm_struct *mm = gpusvm->mm;
  1518. if (!mmget_not_zero(mm))
  1519. return -EFAULT;
  1520. pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
  1521. if (!pfns)
  1522. return -ENOMEM;
  1523. hmm_range.hmm_pfns = pfns;
  1524. while (!time_after(jiffies, timeout)) {
  1525. hmm_range.notifier_seq = mmu_interval_read_begin(notifier);
  1526. if (time_after(jiffies, timeout)) {
  1527. err = -ETIME;
  1528. break;
  1529. }
  1530. mmap_read_lock(mm);
  1531. err = hmm_range_fault(&hmm_range);
  1532. mmap_read_unlock(mm);
  1533. if (err != -EBUSY)
  1534. break;
  1535. }
  1536. kvfree(pfns);
  1537. mmput(mm);
  1538. return err;
  1539. }
  1540. EXPORT_SYMBOL_GPL(drm_gpusvm_range_evict);
  1541. /**
  1542. * drm_gpusvm_has_mapping() - Check if GPU SVM has mapping for the given address range
  1543. * @gpusvm: Pointer to the GPU SVM structure.
  1544. * @start: Start address
  1545. * @end: End address
  1546. *
  1547. * Return: True if GPU SVM has mapping, False otherwise
  1548. */
  1549. bool drm_gpusvm_has_mapping(struct drm_gpusvm *gpusvm, unsigned long start,
  1550. unsigned long end)
  1551. {
  1552. struct drm_gpusvm_notifier *notifier;
  1553. drm_gpusvm_for_each_notifier(notifier, gpusvm, start, end) {
  1554. struct drm_gpusvm_range *range = NULL;
  1555. drm_gpusvm_for_each_range(range, notifier, start, end)
  1556. return true;
  1557. }
  1558. return false;
  1559. }
  1560. EXPORT_SYMBOL_GPL(drm_gpusvm_has_mapping);
  1561. /**
  1562. * drm_gpusvm_range_set_unmapped() - Mark a GPU SVM range as unmapped
  1563. * @range: Pointer to the GPU SVM range structure.
  1564. * @mmu_range: Pointer to the MMU notifier range structure.
  1565. *
  1566. * This function marks a GPU SVM range as unmapped and sets the partial_unmap flag
  1567. * if the range partially falls within the provided MMU notifier range.
  1568. */
  1569. void drm_gpusvm_range_set_unmapped(struct drm_gpusvm_range *range,
  1570. const struct mmu_notifier_range *mmu_range)
  1571. {
  1572. lockdep_assert_held_write(&range->gpusvm->notifier_lock);
  1573. range->pages.flags.unmapped = true;
  1574. if (drm_gpusvm_range_start(range) < mmu_range->start ||
  1575. drm_gpusvm_range_end(range) > mmu_range->end)
  1576. range->pages.flags.partial_unmap = true;
  1577. }
  1578. EXPORT_SYMBOL_GPL(drm_gpusvm_range_set_unmapped);
  1579. MODULE_DESCRIPTION("DRM GPUSVM");
  1580. MODULE_LICENSE("GPL");