@@ -516,7 +516,7 @@ static const struct mmu_interval_notifier_ops nouveau_svm_mni_ops = {
516516static void nouveau_hmm_convert_pfn (struct nouveau_drm * drm ,
517517 struct hmm_range * range , u64 * ioctl_addr )
518518{
519- unsigned long i , npages ;
519+ struct page * page ;
520520
521521 /*
522522 * 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,
525525 * This is all just encoding the internal hmm representation into a
526526 * different nouveau internal representation.
527527 */
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 ;
548531 }
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 ;
549544}
550545
551546static int nouveau_range_fault (struct nouveau_svmm * svmm ,
552547 struct nouveau_drm * drm , void * data , u32 size ,
553- unsigned long hmm_pfns [], u64 * ioctl_addr ,
548+ u64 * ioctl_addr , unsigned long hmm_flags ,
554549 struct svm_notifier * notifier )
555550{
556551 unsigned long timeout =
557552 jiffies + msecs_to_jiffies (HMM_RANGE_DEFAULT_TIMEOUT );
558553 /* Have HMM fault pages within the fault window to the GPU. */
554+ unsigned long hmm_pfns [1 ];
559555 struct hmm_range range = {
560556 .notifier = & notifier -> notifier ,
561557 .start = notifier -> notifier .interval_tree .start ,
562558 .end = notifier -> notifier .interval_tree .last + 1 ,
563- .pfn_flags_mask = HMM_PFN_REQ_FAULT | HMM_PFN_REQ_WRITE ,
559+ .default_flags = hmm_flags ,
564560 .hmm_pfns = hmm_pfns ,
565561 };
566562 struct mm_struct * mm = notifier -> notifier .mm ;
@@ -575,11 +571,6 @@ static int nouveau_range_fault(struct nouveau_svmm *svmm,
575571 ret = hmm_range_fault (& range );
576572 mmap_read_unlock (mm );
577573 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- */
583574 if (ret == - EBUSY )
584575 continue ;
585576 return ret ;
@@ -614,17 +605,12 @@ nouveau_svm_fault(struct nvif_notify *notify)
614605 struct nvif_object * device = & svm -> drm -> client .device .object ;
615606 struct nouveau_svmm * svmm ;
616607 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 ];
623610 } args ;
624- unsigned long hmm_pfns [ARRAY_SIZE (args .phys )];
625- struct vm_area_struct * vma ;
611+ unsigned long hmm_flags ;
626612 u64 inst , start , limit ;
627- int fi , fn , pi , fill ;
613+ int fi , fn ;
628614 int replay = 0 , ret ;
629615
630616 /* Parse available fault buffer entries into a cache, and update
@@ -691,128 +677,75 @@ nouveau_svm_fault(struct nvif_notify *notify)
691677 * window into a single update.
692678 */
693679 start = buffer -> fault [fi ]-> addr ;
694- limit = start + ( ARRAY_SIZE ( args . phys ) << PAGE_SHIFT ) ;
680+ limit = start + PAGE_SIZE ;
695681 if (start < svmm -> unmanaged .limit )
696682 limit = min_t (u64 , limit , svmm -> unmanaged .start );
697- SVMM_DBG (svmm , "wndw %016llx-%016llx" , start , limit );
698683
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.
707688 */
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 ;
716707 }
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 );
721708
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 )) {
725711 nouveau_svm_fault_cancel_fault (svm , buffer -> fault [fi ]);
726712 continue ;
727713 }
728714
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 );
753725
726+ for (fn = fi ; ++ fn < buffer -> fault_nr ; ) {
754727 /* It's okay to skip over duplicate addresses from the
755728 * same SVMM as faults are ordered by access type such
756729 * that only the first one needs to be handled.
757730 *
758731 * ie. WRITE faults appear first, thus any handling of
759732 * pending READ faults will already be satisfied.
760733 */
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 ||
771735 buffer -> fault [fn ]-> addr >= limit )
772736 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 ;
779737 }
780738
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 ++ ];
798744
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 )) {
811745 nouveau_svm_fault_cancel_fault (svm , fault );
812- continue ;
813746 }
747+ } else
814748 replay ++ ;
815- }
816749 }
817750
818751 /* Issue fault replay to the GPU. */
0 commit comments