@@ -516,7 +516,7 @@ static const struct mmu_interval_notifier_ops nouveau_svm_mni_ops = {
516
516
static void nouveau_hmm_convert_pfn (struct nouveau_drm * drm ,
517
517
struct hmm_range * range , u64 * ioctl_addr )
518
518
{
519
- unsigned long i , npages ;
519
+ struct page * page ;
520
520
521
521
/*
522
522
* The ioctl_addr prepared here is passed through nvif_object_ioctl()
@@ -525,42 +525,38 @@ static void nouveau_hmm_convert_pfn(struct nouveau_drm *drm,
525
525
* This is all just encoding the internal hmm representation into a
526
526
* different nouveau internal representation.
527
527
*/
528
- npages = (range -> end - range -> start ) >> PAGE_SHIFT ;
529
- for (i = 0 ; i < npages ; ++ i ) {
530
- struct page * page ;
531
-
532
- if (!(range -> hmm_pfns [i ] & HMM_PFN_VALID )) {
533
- ioctl_addr [i ] = 0 ;
534
- continue ;
535
- }
536
-
537
- page = hmm_pfn_to_page (range -> hmm_pfns [i ]);
538
- if (is_device_private_page (page ))
539
- ioctl_addr [i ] = nouveau_dmem_page_addr (page ) |
540
- NVIF_VMM_PFNMAP_V0_V |
541
- NVIF_VMM_PFNMAP_V0_VRAM ;
542
- else
543
- ioctl_addr [i ] = page_to_phys (page ) |
544
- NVIF_VMM_PFNMAP_V0_V |
545
- NVIF_VMM_PFNMAP_V0_HOST ;
546
- if (range -> hmm_pfns [i ] & HMM_PFN_WRITE )
547
- ioctl_addr [i ] |= NVIF_VMM_PFNMAP_V0_W ;
528
+ if (!(range -> hmm_pfns [0 ] & HMM_PFN_VALID )) {
529
+ ioctl_addr [0 ] = 0 ;
530
+ return ;
548
531
}
532
+
533
+ page = hmm_pfn_to_page (range -> hmm_pfns [0 ]);
534
+ if (is_device_private_page (page ))
535
+ ioctl_addr [0 ] = nouveau_dmem_page_addr (page ) |
536
+ NVIF_VMM_PFNMAP_V0_V |
537
+ NVIF_VMM_PFNMAP_V0_VRAM ;
538
+ else
539
+ ioctl_addr [0 ] = page_to_phys (page ) |
540
+ NVIF_VMM_PFNMAP_V0_V |
541
+ NVIF_VMM_PFNMAP_V0_HOST ;
542
+ if (range -> hmm_pfns [0 ] & HMM_PFN_WRITE )
543
+ ioctl_addr [0 ] |= NVIF_VMM_PFNMAP_V0_W ;
549
544
}
550
545
551
546
static int nouveau_range_fault (struct nouveau_svmm * svmm ,
552
547
struct nouveau_drm * drm , void * data , u32 size ,
553
- unsigned long hmm_pfns [], u64 * ioctl_addr ,
548
+ u64 * ioctl_addr , unsigned long hmm_flags ,
554
549
struct svm_notifier * notifier )
555
550
{
556
551
unsigned long timeout =
557
552
jiffies + msecs_to_jiffies (HMM_RANGE_DEFAULT_TIMEOUT );
558
553
/* Have HMM fault pages within the fault window to the GPU. */
554
+ unsigned long hmm_pfns [1 ];
559
555
struct hmm_range range = {
560
556
.notifier = & notifier -> notifier ,
561
557
.start = notifier -> notifier .interval_tree .start ,
562
558
.end = notifier -> notifier .interval_tree .last + 1 ,
563
- .pfn_flags_mask = HMM_PFN_REQ_FAULT | HMM_PFN_REQ_WRITE ,
559
+ .default_flags = hmm_flags ,
564
560
.hmm_pfns = hmm_pfns ,
565
561
};
566
562
struct mm_struct * mm = notifier -> notifier .mm ;
@@ -575,11 +571,6 @@ static int nouveau_range_fault(struct nouveau_svmm *svmm,
575
571
ret = hmm_range_fault (& range );
576
572
mmap_read_unlock (mm );
577
573
if (ret ) {
578
- /*
579
- * FIXME: the input PFN_REQ flags are destroyed on
580
- * -EBUSY, we need to regenerate them, also for the
581
- * other continue below
582
- */
583
574
if (ret == - EBUSY )
584
575
continue ;
585
576
return ret ;
@@ -614,17 +605,12 @@ nouveau_svm_fault(struct nvif_notify *notify)
614
605
struct nvif_object * device = & svm -> drm -> client .device .object ;
615
606
struct nouveau_svmm * svmm ;
616
607
struct {
617
- struct {
618
- struct nvif_ioctl_v0 i ;
619
- struct nvif_ioctl_mthd_v0 m ;
620
- struct nvif_vmm_pfnmap_v0 p ;
621
- } i ;
622
- u64 phys [16 ];
608
+ struct nouveau_pfnmap_args i ;
609
+ u64 phys [1 ];
623
610
} args ;
624
- unsigned long hmm_pfns [ARRAY_SIZE (args .phys )];
625
- struct vm_area_struct * vma ;
611
+ unsigned long hmm_flags ;
626
612
u64 inst , start , limit ;
627
- int fi , fn , pi , fill ;
613
+ int fi , fn ;
628
614
int replay = 0 , ret ;
629
615
630
616
/* Parse available fault buffer entries into a cache, and update
@@ -691,128 +677,75 @@ nouveau_svm_fault(struct nvif_notify *notify)
691
677
* window into a single update.
692
678
*/
693
679
start = buffer -> fault [fi ]-> addr ;
694
- limit = start + ( ARRAY_SIZE ( args . phys ) << PAGE_SHIFT ) ;
680
+ limit = start + PAGE_SIZE ;
695
681
if (start < svmm -> unmanaged .limit )
696
682
limit = min_t (u64 , limit , svmm -> unmanaged .start );
697
- SVMM_DBG (svmm , "wndw %016llx-%016llx" , start , limit );
698
683
699
- mm = svmm -> notifier .mm ;
700
- if (!mmget_not_zero (mm )) {
701
- nouveau_svm_fault_cancel_fault (svm , buffer -> fault [fi ]);
702
- continue ;
703
- }
704
-
705
- /* Intersect fault window with the CPU VMA, cancelling
706
- * the fault if the address is invalid.
684
+ /*
685
+ * Prepare the GPU-side update of all pages within the
686
+ * fault window, determining required pages and access
687
+ * permissions based on pending faults.
707
688
*/
708
- mmap_read_lock (mm );
709
- vma = find_vma_intersection (mm , start , limit );
710
- if (!vma ) {
711
- SVMM_ERR (svmm , "wndw %016llx-%016llx" , start , limit );
712
- mmap_read_unlock (mm );
713
- mmput (mm );
714
- nouveau_svm_fault_cancel_fault (svm , buffer -> fault [fi ]);
715
- continue ;
689
+ args .i .p .addr = start ;
690
+ args .i .p .page = PAGE_SHIFT ;
691
+ args .i .p .size = PAGE_SIZE ;
692
+ /*
693
+ * Determine required permissions based on GPU fault
694
+ * access flags.
695
+ * XXX: atomic?
696
+ */
697
+ switch (buffer -> fault [fi ]-> access ) {
698
+ case 0 : /* READ. */
699
+ hmm_flags = HMM_PFN_REQ_FAULT ;
700
+ break ;
701
+ case 3 : /* PREFETCH. */
702
+ hmm_flags = 0 ;
703
+ break ;
704
+ default :
705
+ hmm_flags = HMM_PFN_REQ_FAULT | HMM_PFN_REQ_WRITE ;
706
+ break ;
716
707
}
717
- start = max_t (u64 , start , vma -> vm_start );
718
- limit = min_t (u64 , limit , vma -> vm_end );
719
- mmap_read_unlock (mm );
720
- SVMM_DBG (svmm , "wndw %016llx-%016llx" , start , limit );
721
708
722
- if (buffer -> fault [fi ]-> addr != start ) {
723
- SVMM_ERR (svmm , "addr %016llx" , buffer -> fault [fi ]-> addr );
724
- mmput (mm );
709
+ mm = svmm -> notifier .mm ;
710
+ if (!mmget_not_zero (mm )) {
725
711
nouveau_svm_fault_cancel_fault (svm , buffer -> fault [fi ]);
726
712
continue ;
727
713
}
728
714
729
- /* Prepare the GPU-side update of all pages within the
730
- * fault window, determining required pages and access
731
- * permissions based on pending faults.
732
- */
733
- args .i .p .page = PAGE_SHIFT ;
734
- args .i .p .addr = start ;
735
- for (fn = fi , pi = 0 ;;) {
736
- /* Determine required permissions based on GPU fault
737
- * access flags.
738
- *XXX: atomic?
739
- */
740
- switch (buffer -> fault [fn ]-> access ) {
741
- case 0 : /* READ. */
742
- hmm_pfns [pi ++ ] = HMM_PFN_REQ_FAULT ;
743
- break ;
744
- case 3 : /* PREFETCH. */
745
- hmm_pfns [pi ++ ] = 0 ;
746
- break ;
747
- default :
748
- hmm_pfns [pi ++ ] = HMM_PFN_REQ_FAULT |
749
- HMM_PFN_REQ_WRITE ;
750
- break ;
751
- }
752
- args .i .p .size = pi << PAGE_SHIFT ;
715
+ notifier .svmm = svmm ;
716
+ ret = mmu_interval_notifier_insert (& notifier .notifier , mm ,
717
+ args .i .p .addr , args .i .p .size ,
718
+ & nouveau_svm_mni_ops );
719
+ if (!ret ) {
720
+ ret = nouveau_range_fault (svmm , svm -> drm , & args ,
721
+ sizeof (args ), args .phys , hmm_flags , & notifier );
722
+ mmu_interval_notifier_remove (& notifier .notifier );
723
+ }
724
+ mmput (mm );
753
725
726
+ for (fn = fi ; ++ fn < buffer -> fault_nr ; ) {
754
727
/* It's okay to skip over duplicate addresses from the
755
728
* same SVMM as faults are ordered by access type such
756
729
* that only the first one needs to be handled.
757
730
*
758
731
* ie. WRITE faults appear first, thus any handling of
759
732
* pending READ faults will already be satisfied.
760
733
*/
761
- while (++ fn < buffer -> fault_nr &&
762
- buffer -> fault [fn ]-> svmm == svmm &&
763
- buffer -> fault [fn ]-> addr ==
764
- buffer -> fault [fn - 1 ]-> addr );
765
-
766
- /* If the next fault is outside the window, or all GPU
767
- * faults have been dealt with, we're done here.
768
- */
769
- if (fn >= buffer -> fault_nr ||
770
- buffer -> fault [fn ]-> svmm != svmm ||
734
+ if (buffer -> fault [fn ]-> svmm != svmm ||
771
735
buffer -> fault [fn ]-> addr >= limit )
772
736
break ;
773
-
774
- /* Fill in the gap between this fault and the next. */
775
- fill = (buffer -> fault [fn ]-> addr -
776
- buffer -> fault [fn - 1 ]-> addr ) >> PAGE_SHIFT ;
777
- while (-- fill )
778
- hmm_pfns [pi ++ ] = 0 ;
779
737
}
780
738
781
- SVMM_DBG (svmm , "wndw %016llx-%016llx covering %d fault(s)" ,
782
- args .i .p .addr ,
783
- args .i .p .addr + args .i .p .size , fn - fi );
784
-
785
- notifier .svmm = svmm ;
786
- ret = mmu_interval_notifier_insert (& notifier .notifier ,
787
- svmm -> notifier .mm ,
788
- args .i .p .addr , args .i .p .size ,
789
- & nouveau_svm_mni_ops );
790
- if (!ret ) {
791
- ret = nouveau_range_fault (
792
- svmm , svm -> drm , & args ,
793
- sizeof (args .i ) + pi * sizeof (args .phys [0 ]),
794
- hmm_pfns , args .phys , & notifier );
795
- mmu_interval_notifier_remove (& notifier .notifier );
796
- }
797
- mmput (mm );
739
+ /* If handling failed completely, cancel all faults. */
740
+ if (ret ) {
741
+ while (fi < fn ) {
742
+ struct nouveau_svm_fault * fault =
743
+ buffer -> fault [fi ++ ];
798
744
799
- /* Cancel any faults in the window whose pages didn't manage
800
- * to keep their valid bit, or stay writeable when required.
801
- *
802
- * If handling failed completely, cancel all faults.
803
- */
804
- while (fi < fn ) {
805
- struct nouveau_svm_fault * fault = buffer -> fault [fi ++ ];
806
- pi = (fault -> addr - args .i .p .addr ) >> PAGE_SHIFT ;
807
- if (ret ||
808
- !(args .phys [pi ] & NVIF_VMM_PFNMAP_V0_V ) ||
809
- (!(args .phys [pi ] & NVIF_VMM_PFNMAP_V0_W ) &&
810
- fault -> access != 0 && fault -> access != 3 )) {
811
745
nouveau_svm_fault_cancel_fault (svm , fault );
812
- continue ;
813
746
}
747
+ } else
814
748
replay ++ ;
815
- }
816
749
}
817
750
818
751
/* Issue fault replay to the GPU. */
0 commit comments