2 * Copyright 2018 Red Hat Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
22 #include "nouveau_svm.h"
23 #include "nouveau_drv.h"
24 #include "nouveau_chan.h"
25 #include "nouveau_dmem.h"
27 #include <nvif/notify.h>
28 #include <nvif/object.h>
31 #include <nvif/class.h>
32 #include <nvif/clb069.h>
33 #include <nvif/ifc00d.h>
35 #include <linux/sched/mm.h>
36 #include <linux/sort.h>
37 #include <linux/hmm.h>
40 struct nouveau_drm
*drm
;
42 struct list_head inst
;
44 struct nouveau_svm_fault_buffer
{
46 struct nvif_object object
;
52 struct nvif_notify notify
;
54 struct nouveau_svm_fault
{
64 struct nouveau_svmm
*svmm
;
70 #define SVM_DBG(s,f,a...) NV_DEBUG((s)->drm, "svm: "f"\n", ##a)
71 #define SVM_ERR(s,f,a...) NV_WARN((s)->drm, "svm: "f"\n", ##a)
74 struct nouveau_svmm
*svmm
;
76 struct list_head head
;
79 static struct nouveau_ivmm
*
80 nouveau_ivmm_find(struct nouveau_svm
*svm
, u64 inst
)
82 struct nouveau_ivmm
*ivmm
;
83 list_for_each_entry(ivmm
, &svm
->inst
, head
) {
84 if (ivmm
->inst
== inst
)
91 struct mmu_notifier notifier
;
92 struct nouveau_vmm
*vmm
;
101 #define SVMM_DBG(s,f,a...) \
102 NV_DEBUG((s)->vmm->cli->drm, "svm-%p: "f"\n", (s), ##a)
103 #define SVMM_ERR(s,f,a...) \
104 NV_WARN((s)->vmm->cli->drm, "svm-%p: "f"\n", (s), ##a)
107 nouveau_svmm_bind(struct drm_device
*dev
, void *data
,
108 struct drm_file
*file_priv
)
110 struct nouveau_cli
*cli
= nouveau_cli(file_priv
);
111 struct drm_nouveau_svm_bind
*args
= data
;
112 unsigned target
, cmd
, priority
;
113 unsigned long addr
, end
, size
;
114 struct mm_struct
*mm
;
116 args
->va_start
&= PAGE_MASK
;
117 args
->va_end
&= PAGE_MASK
;
119 /* Sanity check arguments */
120 if (args
->reserved0
|| args
->reserved1
)
122 if (args
->header
& (~NOUVEAU_SVM_BIND_VALID_MASK
))
124 if (args
->va_start
>= args
->va_end
)
129 cmd
= args
->header
>> NOUVEAU_SVM_BIND_COMMAND_SHIFT
;
130 cmd
&= NOUVEAU_SVM_BIND_COMMAND_MASK
;
132 case NOUVEAU_SVM_BIND_COMMAND__MIGRATE
:
138 priority
= args
->header
>> NOUVEAU_SVM_BIND_PRIORITY_SHIFT
;
139 priority
&= NOUVEAU_SVM_BIND_PRIORITY_MASK
;
141 /* FIXME support CPU target ie all target value < GPU_VRAM */
142 target
= args
->header
>> NOUVEAU_SVM_BIND_TARGET_SHIFT
;
143 target
&= NOUVEAU_SVM_BIND_TARGET_MASK
;
145 case NOUVEAU_SVM_BIND_TARGET__GPU_VRAM
:
152 * FIXME: For now refuse non 0 stride, we need to change the migrate
153 * kernel function to handle stride to avoid to create a mess within
154 * each device driver.
159 size
= ((unsigned long)args
->npages
) << PAGE_SHIFT
;
160 if ((args
->va_start
+ size
) <= args
->va_start
)
162 if ((args
->va_start
+ size
) > args
->va_end
)
166 * Ok we are ask to do something sane, for now we only support migrate
167 * commands but we will add things like memory policy (what to do on
168 * page fault) and maybe some other commands.
171 mm
= get_task_mm(current
);
172 down_read(&mm
->mmap_sem
);
174 for (addr
= args
->va_start
, end
= args
->va_start
+ size
; addr
< end
;) {
175 struct vm_area_struct
*vma
;
178 vma
= find_vma_intersection(mm
, addr
, end
);
182 next
= min(vma
->vm_end
, end
);
183 /* This is a best effort so we ignore errors */
184 nouveau_dmem_migrate_vma(cli
->drm
, vma
, addr
, next
);
189 * FIXME Return the number of page we have migrated, again we need to
190 * update the migrate API to return that information so that we can
191 * report it to user space.
195 up_read(&mm
->mmap_sem
);
201 /* Unlink channel instance from SVMM. */
203 nouveau_svmm_part(struct nouveau_svmm
*svmm
, u64 inst
)
205 struct nouveau_ivmm
*ivmm
;
207 mutex_lock(&svmm
->vmm
->cli
->drm
->svm
->mutex
);
208 ivmm
= nouveau_ivmm_find(svmm
->vmm
->cli
->drm
->svm
, inst
);
210 list_del(&ivmm
->head
);
213 mutex_unlock(&svmm
->vmm
->cli
->drm
->svm
->mutex
);
217 /* Link channel instance to SVMM. */
219 nouveau_svmm_join(struct nouveau_svmm
*svmm
, u64 inst
)
221 struct nouveau_ivmm
*ivmm
;
223 if (!(ivmm
= kmalloc(sizeof(*ivmm
), GFP_KERNEL
)))
228 mutex_lock(&svmm
->vmm
->cli
->drm
->svm
->mutex
);
229 list_add(&ivmm
->head
, &svmm
->vmm
->cli
->drm
->svm
->inst
);
230 mutex_unlock(&svmm
->vmm
->cli
->drm
->svm
->mutex
);
235 /* Invalidate SVMM address-range on GPU. */
237 nouveau_svmm_invalidate(struct nouveau_svmm
*svmm
, u64 start
, u64 limit
)
240 bool super
= svmm
->vmm
->vmm
.object
.client
->super
;
241 svmm
->vmm
->vmm
.object
.client
->super
= true;
242 nvif_object_mthd(&svmm
->vmm
->vmm
.object
, NVIF_VMM_V0_PFNCLR
,
243 &(struct nvif_vmm_pfnclr_v0
) {
245 .size
= limit
- start
,
246 }, sizeof(struct nvif_vmm_pfnclr_v0
));
247 svmm
->vmm
->vmm
.object
.client
->super
= super
;
252 nouveau_svmm_invalidate_range_start(struct mmu_notifier
*mn
,
253 const struct mmu_notifier_range
*update
)
255 struct nouveau_svmm
*svmm
=
256 container_of(mn
, struct nouveau_svmm
, notifier
);
257 unsigned long start
= update
->start
;
258 unsigned long limit
= update
->end
;
260 if (!mmu_notifier_range_blockable(update
))
263 SVMM_DBG(svmm
, "invalidate %016lx-%016lx", start
, limit
);
265 mutex_lock(&svmm
->mutex
);
266 if (unlikely(!svmm
->vmm
))
269 if (limit
> svmm
->unmanaged
.start
&& start
< svmm
->unmanaged
.limit
) {
270 if (start
< svmm
->unmanaged
.start
) {
271 nouveau_svmm_invalidate(svmm
, start
,
272 svmm
->unmanaged
.limit
);
274 start
= svmm
->unmanaged
.limit
;
277 nouveau_svmm_invalidate(svmm
, start
, limit
);
280 mutex_unlock(&svmm
->mutex
);
284 static void nouveau_svmm_free_notifier(struct mmu_notifier
*mn
)
286 kfree(container_of(mn
, struct nouveau_svmm
, notifier
));
289 static const struct mmu_notifier_ops nouveau_mn_ops
= {
290 .invalidate_range_start
= nouveau_svmm_invalidate_range_start
,
291 .free_notifier
= nouveau_svmm_free_notifier
,
295 nouveau_svmm_fini(struct nouveau_svmm
**psvmm
)
297 struct nouveau_svmm
*svmm
= *psvmm
;
299 mutex_lock(&svmm
->mutex
);
301 mutex_unlock(&svmm
->mutex
);
302 mmu_notifier_put(&svmm
->notifier
);
308 nouveau_svmm_init(struct drm_device
*dev
, void *data
,
309 struct drm_file
*file_priv
)
311 struct nouveau_cli
*cli
= nouveau_cli(file_priv
);
312 struct nouveau_svmm
*svmm
;
313 struct drm_nouveau_svm_init
*args
= data
;
316 /* Allocate tracking for SVM-enabled VMM. */
317 if (!(svmm
= kzalloc(sizeof(*svmm
), GFP_KERNEL
)))
319 svmm
->vmm
= &cli
->svm
;
320 svmm
->unmanaged
.start
= args
->unmanaged_addr
;
321 svmm
->unmanaged
.limit
= args
->unmanaged_addr
+ args
->unmanaged_size
;
322 mutex_init(&svmm
->mutex
);
324 /* Check that SVM isn't already enabled for the client. */
325 mutex_lock(&cli
->mutex
);
331 /* Allocate a new GPU VMM that can support SVM (managed by the
332 * client, with replayable faults enabled).
334 * All future channel/memory allocations will make use of this
335 * VMM instead of the standard one.
337 ret
= nvif_vmm_init(&cli
->mmu
, cli
->vmm
.vmm
.object
.oclass
, true,
338 args
->unmanaged_addr
, args
->unmanaged_size
,
339 &(struct gp100_vmm_v0
) {
340 .fault_replay
= true,
341 }, sizeof(struct gp100_vmm_v0
), &cli
->svm
.vmm
);
345 down_write(¤t
->mm
->mmap_sem
);
346 svmm
->notifier
.ops
= &nouveau_mn_ops
;
347 ret
= __mmu_notifier_register(&svmm
->notifier
, current
->mm
);
350 /* Note, ownership of svmm transfers to mmu_notifier */
352 cli
->svm
.svmm
= svmm
;
354 up_write(¤t
->mm
->mmap_sem
);
355 mutex_unlock(&cli
->mutex
);
359 up_write(¤t
->mm
->mmap_sem
);
361 mutex_unlock(&cli
->mutex
);
367 nouveau_svm_pfn_flags
[HMM_PFN_FLAG_MAX
] = {
368 [HMM_PFN_VALID
] = NVIF_VMM_PFNMAP_V0_V
,
369 [HMM_PFN_WRITE
] = NVIF_VMM_PFNMAP_V0_W
,
370 [HMM_PFN_DEVICE_PRIVATE
] = NVIF_VMM_PFNMAP_V0_VRAM
,
374 nouveau_svm_pfn_values
[HMM_PFN_VALUE_MAX
] = {
375 [HMM_PFN_ERROR
] = ~NVIF_VMM_PFNMAP_V0_V
,
376 [HMM_PFN_NONE
] = NVIF_VMM_PFNMAP_V0_NONE
,
377 [HMM_PFN_SPECIAL
] = ~NVIF_VMM_PFNMAP_V0_V
,
380 /* Issue fault replay for GPU to retry accesses that faulted previously. */
382 nouveau_svm_fault_replay(struct nouveau_svm
*svm
)
384 SVM_DBG(svm
, "replay");
385 WARN_ON(nvif_object_mthd(&svm
->drm
->client
.vmm
.vmm
.object
,
386 GP100_VMM_VN_FAULT_REPLAY
,
387 &(struct gp100_vmm_fault_replay_vn
) {},
388 sizeof(struct gp100_vmm_fault_replay_vn
)));
391 /* Cancel a replayable fault that could not be handled.
393 * Cancelling the fault will trigger recovery to reset the engine
394 * and kill the offending channel (ie. GPU SIGSEGV).
397 nouveau_svm_fault_cancel(struct nouveau_svm
*svm
,
398 u64 inst
, u8 hub
, u8 gpc
, u8 client
)
400 SVM_DBG(svm
, "cancel %016llx %d %02x %02x", inst
, hub
, gpc
, client
);
401 WARN_ON(nvif_object_mthd(&svm
->drm
->client
.vmm
.vmm
.object
,
402 GP100_VMM_VN_FAULT_CANCEL
,
403 &(struct gp100_vmm_fault_cancel_v0
) {
408 }, sizeof(struct gp100_vmm_fault_cancel_v0
)));
412 nouveau_svm_fault_cancel_fault(struct nouveau_svm
*svm
,
413 struct nouveau_svm_fault
*fault
)
415 nouveau_svm_fault_cancel(svm
, fault
->inst
,
422 nouveau_svm_fault_cmp(const void *a
, const void *b
)
424 const struct nouveau_svm_fault
*fa
= *(struct nouveau_svm_fault
**)a
;
425 const struct nouveau_svm_fault
*fb
= *(struct nouveau_svm_fault
**)b
;
427 if ((ret
= (s64
)fa
->inst
- fb
->inst
))
429 if ((ret
= (s64
)fa
->addr
- fb
->addr
))
432 return (fa
->access
== 0 || fa
->access
== 3) -
433 (fb
->access
== 0 || fb
->access
== 3);
437 nouveau_svm_fault_cache(struct nouveau_svm
*svm
,
438 struct nouveau_svm_fault_buffer
*buffer
, u32 offset
)
440 struct nvif_object
*memory
= &buffer
->object
;
441 const u32 instlo
= nvif_rd32(memory
, offset
+ 0x00);
442 const u32 insthi
= nvif_rd32(memory
, offset
+ 0x04);
443 const u32 addrlo
= nvif_rd32(memory
, offset
+ 0x08);
444 const u32 addrhi
= nvif_rd32(memory
, offset
+ 0x0c);
445 const u32 timelo
= nvif_rd32(memory
, offset
+ 0x10);
446 const u32 timehi
= nvif_rd32(memory
, offset
+ 0x14);
447 const u32 engine
= nvif_rd32(memory
, offset
+ 0x18);
448 const u32 info
= nvif_rd32(memory
, offset
+ 0x1c);
449 const u64 inst
= (u64
)insthi
<< 32 | instlo
;
450 const u8 gpc
= (info
& 0x1f000000) >> 24;
451 const u8 hub
= (info
& 0x00100000) >> 20;
452 const u8 client
= (info
& 0x00007f00) >> 8;
453 struct nouveau_svm_fault
*fault
;
455 //XXX: i think we're supposed to spin waiting */
456 if (WARN_ON(!(info
& 0x80000000)))
459 nvif_mask(memory
, offset
+ 0x1c, 0x80000000, 0x00000000);
461 if (!buffer
->fault
[buffer
->fault_nr
]) {
462 fault
= kmalloc(sizeof(*fault
), GFP_KERNEL
);
463 if (WARN_ON(!fault
)) {
464 nouveau_svm_fault_cancel(svm
, inst
, hub
, gpc
, client
);
467 buffer
->fault
[buffer
->fault_nr
] = fault
;
470 fault
= buffer
->fault
[buffer
->fault_nr
++];
472 fault
->addr
= (u64
)addrhi
<< 32 | addrlo
;
473 fault
->time
= (u64
)timehi
<< 32 | timelo
;
474 fault
->engine
= engine
;
477 fault
->access
= (info
& 0x000f0000) >> 16;
478 fault
->client
= client
;
479 fault
->fault
= (info
& 0x0000001f);
481 SVM_DBG(svm
, "fault %016llx %016llx %02x",
482 fault
->inst
, fault
->addr
, fault
->access
);
485 struct svm_notifier
{
486 struct mmu_interval_notifier notifier
;
487 struct nouveau_svmm
*svmm
;
490 static bool nouveau_svm_range_invalidate(struct mmu_interval_notifier
*mni
,
491 const struct mmu_notifier_range
*range
,
492 unsigned long cur_seq
)
494 struct svm_notifier
*sn
=
495 container_of(mni
, struct svm_notifier
, notifier
);
498 * serializes the update to mni->invalidate_seq done by caller and
499 * prevents invalidation of the PTE from progressing while HW is being
500 * programmed. This is very hacky and only works because the normal
501 * notifier that does invalidation is always called after the range
504 if (mmu_notifier_range_blockable(range
))
505 mutex_lock(&sn
->svmm
->mutex
);
506 else if (!mutex_trylock(&sn
->svmm
->mutex
))
508 mmu_interval_set_seq(mni
, cur_seq
);
509 mutex_unlock(&sn
->svmm
->mutex
);
513 static const struct mmu_interval_notifier_ops nouveau_svm_mni_ops
= {
514 .invalidate
= nouveau_svm_range_invalidate
,
517 static int nouveau_range_fault(struct nouveau_svmm
*svmm
,
518 struct nouveau_drm
*drm
, void *data
, u32 size
,
519 u64
*pfns
, struct svm_notifier
*notifier
)
521 unsigned long timeout
=
522 jiffies
+ msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT
);
523 /* Have HMM fault pages within the fault window to the GPU. */
524 struct hmm_range range
= {
525 .notifier
= ¬ifier
->notifier
,
526 .start
= notifier
->notifier
.interval_tree
.start
,
527 .end
= notifier
->notifier
.interval_tree
.last
+ 1,
529 .flags
= nouveau_svm_pfn_flags
,
530 .values
= nouveau_svm_pfn_values
,
531 .pfn_shift
= NVIF_VMM_PFNMAP_V0_ADDR_SHIFT
,
533 struct mm_struct
*mm
= notifier
->notifier
.mm
;
537 if (time_after(jiffies
, timeout
))
540 range
.notifier_seq
= mmu_interval_read_begin(range
.notifier
);
541 range
.default_flags
= 0;
542 range
.pfn_flags_mask
= -1UL;
543 down_read(&mm
->mmap_sem
);
544 ret
= hmm_range_fault(&range
, 0);
545 up_read(&mm
->mmap_sem
);
547 if (ret
== 0 || ret
== -EBUSY
)
552 mutex_lock(&svmm
->mutex
);
553 if (mmu_interval_read_retry(range
.notifier
,
554 range
.notifier_seq
)) {
555 mutex_unlock(&svmm
->mutex
);
561 nouveau_dmem_convert_pfn(drm
, &range
);
563 svmm
->vmm
->vmm
.object
.client
->super
= true;
564 ret
= nvif_object_ioctl(&svmm
->vmm
->vmm
.object
, data
, size
, NULL
);
565 svmm
->vmm
->vmm
.object
.client
->super
= false;
566 mutex_unlock(&svmm
->mutex
);
572 nouveau_svm_fault(struct nvif_notify
*notify
)
574 struct nouveau_svm_fault_buffer
*buffer
=
575 container_of(notify
, typeof(*buffer
), notify
);
576 struct nouveau_svm
*svm
=
577 container_of(buffer
, typeof(*svm
), buffer
[buffer
->id
]);
578 struct nvif_object
*device
= &svm
->drm
->client
.device
.object
;
579 struct nouveau_svmm
*svmm
;
582 struct nvif_ioctl_v0 i
;
583 struct nvif_ioctl_mthd_v0 m
;
584 struct nvif_vmm_pfnmap_v0 p
;
588 struct vm_area_struct
*vma
;
589 u64 inst
, start
, limit
;
590 int fi
, fn
, pi
, fill
;
593 /* Parse available fault buffer entries into a cache, and update
594 * the GET pointer so HW can reuse the entries.
596 SVM_DBG(svm
, "fault handler");
597 if (buffer
->get
== buffer
->put
) {
598 buffer
->put
= nvif_rd32(device
, buffer
->putaddr
);
599 buffer
->get
= nvif_rd32(device
, buffer
->getaddr
);
600 if (buffer
->get
== buffer
->put
)
601 return NVIF_NOTIFY_KEEP
;
603 buffer
->fault_nr
= 0;
605 SVM_DBG(svm
, "get %08x put %08x", buffer
->get
, buffer
->put
);
606 while (buffer
->get
!= buffer
->put
) {
607 nouveau_svm_fault_cache(svm
, buffer
, buffer
->get
* 0x20);
608 if (++buffer
->get
== buffer
->entries
)
611 nvif_wr32(device
, buffer
->getaddr
, buffer
->get
);
612 SVM_DBG(svm
, "%d fault(s) pending", buffer
->fault_nr
);
614 /* Sort parsed faults by instance pointer to prevent unnecessary
615 * instance to SVMM translations, followed by address and access
616 * type to reduce the amount of work when handling the faults.
618 sort(buffer
->fault
, buffer
->fault_nr
, sizeof(*buffer
->fault
),
619 nouveau_svm_fault_cmp
, NULL
);
621 /* Lookup SVMM structure for each unique instance pointer. */
622 mutex_lock(&svm
->mutex
);
623 for (fi
= 0, svmm
= NULL
; fi
< buffer
->fault_nr
; fi
++) {
624 if (!svmm
|| buffer
->fault
[fi
]->inst
!= inst
) {
625 struct nouveau_ivmm
*ivmm
=
626 nouveau_ivmm_find(svm
, buffer
->fault
[fi
]->inst
);
627 svmm
= ivmm
? ivmm
->svmm
: NULL
;
628 inst
= buffer
->fault
[fi
]->inst
;
629 SVM_DBG(svm
, "inst %016llx -> svm-%p", inst
, svmm
);
631 buffer
->fault
[fi
]->svmm
= svmm
;
633 mutex_unlock(&svm
->mutex
);
635 /* Process list of faults. */
636 args
.i
.i
.version
= 0;
637 args
.i
.i
.type
= NVIF_IOCTL_V0_MTHD
;
638 args
.i
.m
.version
= 0;
639 args
.i
.m
.method
= NVIF_VMM_V0_PFNMAP
;
640 args
.i
.p
.version
= 0;
642 for (fi
= 0; fn
= fi
+ 1, fi
< buffer
->fault_nr
; fi
= fn
) {
643 struct svm_notifier notifier
;
644 struct mm_struct
*mm
;
646 /* Cancel any faults from non-SVM channels. */
647 if (!(svmm
= buffer
->fault
[fi
]->svmm
)) {
648 nouveau_svm_fault_cancel_fault(svm
, buffer
->fault
[fi
]);
651 SVMM_DBG(svmm
, "addr %016llx", buffer
->fault
[fi
]->addr
);
653 /* We try and group handling of faults within a small
654 * window into a single update.
656 start
= buffer
->fault
[fi
]->addr
;
657 limit
= start
+ (ARRAY_SIZE(args
.phys
) << PAGE_SHIFT
);
658 if (start
< svmm
->unmanaged
.limit
)
659 limit
= min_t(u64
, limit
, svmm
->unmanaged
.start
);
661 if (limit
> svmm
->unmanaged
.start
)
662 start
= max_t(u64
, start
, svmm
->unmanaged
.limit
);
663 SVMM_DBG(svmm
, "wndw %016llx-%016llx", start
, limit
);
665 mm
= svmm
->notifier
.mm
;
666 if (!mmget_not_zero(mm
)) {
667 nouveau_svm_fault_cancel_fault(svm
, buffer
->fault
[fi
]);
671 /* Intersect fault window with the CPU VMA, cancelling
672 * the fault if the address is invalid.
674 down_read(&mm
->mmap_sem
);
675 vma
= find_vma_intersection(mm
, start
, limit
);
677 SVMM_ERR(svmm
, "wndw %016llx-%016llx", start
, limit
);
678 up_read(&mm
->mmap_sem
);
680 nouveau_svm_fault_cancel_fault(svm
, buffer
->fault
[fi
]);
683 start
= max_t(u64
, start
, vma
->vm_start
);
684 limit
= min_t(u64
, limit
, vma
->vm_end
);
685 up_read(&mm
->mmap_sem
);
686 SVMM_DBG(svmm
, "wndw %016llx-%016llx", start
, limit
);
688 if (buffer
->fault
[fi
]->addr
!= start
) {
689 SVMM_ERR(svmm
, "addr %016llx", buffer
->fault
[fi
]->addr
);
691 nouveau_svm_fault_cancel_fault(svm
, buffer
->fault
[fi
]);
695 /* Prepare the GPU-side update of all pages within the
696 * fault window, determining required pages and access
697 * permissions based on pending faults.
699 args
.i
.p
.page
= PAGE_SHIFT
;
700 args
.i
.p
.addr
= start
;
701 for (fn
= fi
, pi
= 0;;) {
702 /* Determine required permissions based on GPU fault
706 if (buffer
->fault
[fn
]->access
!= 0 /* READ. */ &&
707 buffer
->fault
[fn
]->access
!= 3 /* PREFETCH. */) {
708 args
.phys
[pi
++] = NVIF_VMM_PFNMAP_V0_V
|
709 NVIF_VMM_PFNMAP_V0_W
;
711 args
.phys
[pi
++] = NVIF_VMM_PFNMAP_V0_V
;
713 args
.i
.p
.size
= pi
<< PAGE_SHIFT
;
715 /* It's okay to skip over duplicate addresses from the
716 * same SVMM as faults are ordered by access type such
717 * that only the first one needs to be handled.
719 * ie. WRITE faults appear first, thus any handling of
720 * pending READ faults will already be satisfied.
722 while (++fn
< buffer
->fault_nr
&&
723 buffer
->fault
[fn
]->svmm
== svmm
&&
724 buffer
->fault
[fn
]->addr
==
725 buffer
->fault
[fn
- 1]->addr
);
727 /* If the next fault is outside the window, or all GPU
728 * faults have been dealt with, we're done here.
730 if (fn
>= buffer
->fault_nr
||
731 buffer
->fault
[fn
]->svmm
!= svmm
||
732 buffer
->fault
[fn
]->addr
>= limit
)
735 /* Fill in the gap between this fault and the next. */
736 fill
= (buffer
->fault
[fn
]->addr
-
737 buffer
->fault
[fn
- 1]->addr
) >> PAGE_SHIFT
;
739 args
.phys
[pi
++] = NVIF_VMM_PFNMAP_V0_NONE
;
742 SVMM_DBG(svmm
, "wndw %016llx-%016llx covering %d fault(s)",
744 args
.i
.p
.addr
+ args
.i
.p
.size
, fn
- fi
);
746 notifier
.svmm
= svmm
;
747 ret
= mmu_interval_notifier_insert(¬ifier
.notifier
,
749 args
.i
.p
.addr
, args
.i
.p
.size
,
750 &nouveau_svm_mni_ops
);
752 ret
= nouveau_range_fault(
753 svmm
, svm
->drm
, &args
,
754 sizeof(args
.i
) + pi
* sizeof(args
.phys
[0]),
755 args
.phys
, ¬ifier
);
756 mmu_interval_notifier_remove(¬ifier
.notifier
);
760 /* Cancel any faults in the window whose pages didn't manage
761 * to keep their valid bit, or stay writeable when required.
763 * If handling failed completely, cancel all faults.
766 struct nouveau_svm_fault
*fault
= buffer
->fault
[fi
++];
767 pi
= (fault
->addr
- args
.i
.p
.addr
) >> PAGE_SHIFT
;
769 !(args
.phys
[pi
] & NVIF_VMM_PFNMAP_V0_V
) ||
770 (!(args
.phys
[pi
] & NVIF_VMM_PFNMAP_V0_W
) &&
771 fault
->access
!= 0 && fault
->access
!= 3)) {
772 nouveau_svm_fault_cancel_fault(svm
, fault
);
779 /* Issue fault replay to the GPU. */
781 nouveau_svm_fault_replay(svm
);
782 return NVIF_NOTIFY_KEEP
;
786 nouveau_svm_fault_buffer_fini(struct nouveau_svm
*svm
, int id
)
788 struct nouveau_svm_fault_buffer
*buffer
= &svm
->buffer
[id
];
789 nvif_notify_put(&buffer
->notify
);
793 nouveau_svm_fault_buffer_init(struct nouveau_svm
*svm
, int id
)
795 struct nouveau_svm_fault_buffer
*buffer
= &svm
->buffer
[id
];
796 struct nvif_object
*device
= &svm
->drm
->client
.device
.object
;
797 buffer
->get
= nvif_rd32(device
, buffer
->getaddr
);
798 buffer
->put
= nvif_rd32(device
, buffer
->putaddr
);
799 SVM_DBG(svm
, "get %08x put %08x (init)", buffer
->get
, buffer
->put
);
800 return nvif_notify_get(&buffer
->notify
);
804 nouveau_svm_fault_buffer_dtor(struct nouveau_svm
*svm
, int id
)
806 struct nouveau_svm_fault_buffer
*buffer
= &svm
->buffer
[id
];
810 for (i
= 0; buffer
->fault
[i
] && i
< buffer
->entries
; i
++)
811 kfree(buffer
->fault
[i
]);
812 kvfree(buffer
->fault
);
815 nouveau_svm_fault_buffer_fini(svm
, id
);
817 nvif_notify_fini(&buffer
->notify
);
818 nvif_object_fini(&buffer
->object
);
822 nouveau_svm_fault_buffer_ctor(struct nouveau_svm
*svm
, s32 oclass
, int id
)
824 struct nouveau_svm_fault_buffer
*buffer
= &svm
->buffer
[id
];
825 struct nouveau_drm
*drm
= svm
->drm
;
826 struct nvif_object
*device
= &drm
->client
.device
.object
;
827 struct nvif_clb069_v0 args
= {};
832 ret
= nvif_object_init(device
, 0, oclass
, &args
, sizeof(args
),
835 SVM_ERR(svm
, "Fault buffer allocation failed: %d", ret
);
839 nvif_object_map(&buffer
->object
, NULL
, 0);
840 buffer
->entries
= args
.entries
;
841 buffer
->getaddr
= args
.get
;
842 buffer
->putaddr
= args
.put
;
844 ret
= nvif_notify_init(&buffer
->object
, nouveau_svm_fault
, true,
845 NVB069_V0_NTFY_FAULT
, NULL
, 0, 0,
850 buffer
->fault
= kvzalloc(sizeof(*buffer
->fault
) * buffer
->entries
, GFP_KERNEL
);
854 return nouveau_svm_fault_buffer_init(svm
, id
);
858 nouveau_svm_resume(struct nouveau_drm
*drm
)
860 struct nouveau_svm
*svm
= drm
->svm
;
862 nouveau_svm_fault_buffer_init(svm
, 0);
866 nouveau_svm_suspend(struct nouveau_drm
*drm
)
868 struct nouveau_svm
*svm
= drm
->svm
;
870 nouveau_svm_fault_buffer_fini(svm
, 0);
874 nouveau_svm_fini(struct nouveau_drm
*drm
)
876 struct nouveau_svm
*svm
= drm
->svm
;
878 nouveau_svm_fault_buffer_dtor(svm
, 0);
885 nouveau_svm_init(struct nouveau_drm
*drm
)
887 static const struct nvif_mclass buffers
[] = {
888 { VOLTA_FAULT_BUFFER_A
, 0 },
889 { MAXWELL_FAULT_BUFFER_A
, 0 },
892 struct nouveau_svm
*svm
;
895 /* Disable on Volta and newer until channel recovery is fixed,
896 * otherwise clients will have a trivial way to trash the GPU
899 if (drm
->client
.device
.info
.family
> NV_DEVICE_INFO_V0_PASCAL
)
902 if (!(drm
->svm
= svm
= kzalloc(sizeof(*drm
->svm
), GFP_KERNEL
)))
906 mutex_init(&drm
->svm
->mutex
);
907 INIT_LIST_HEAD(&drm
->svm
->inst
);
909 ret
= nvif_mclass(&drm
->client
.device
.object
, buffers
);
911 SVM_DBG(svm
, "No supported fault buffer class");
912 nouveau_svm_fini(drm
);
916 ret
= nouveau_svm_fault_buffer_ctor(svm
, buffers
[ret
].oclass
, 0);
918 nouveau_svm_fini(drm
);
922 SVM_DBG(svm
, "Initialised");