@@ -514,38 +514,57 @@ static const struct mmu_interval_notifier_ops nouveau_svm_mni_ops = {
514
514
};
515
515
516
516
static void nouveau_hmm_convert_pfn (struct nouveau_drm * drm ,
517
- struct hmm_range * range , u64 * ioctl_addr )
517
+ struct hmm_range * range ,
518
+ struct nouveau_pfnmap_args * args )
518
519
{
519
520
struct page * page ;
520
521
521
522
/*
522
- * The ioctl_addr prepared here is passed through nvif_object_ioctl()
523
+ * The address prepared here is passed through nvif_object_ioctl()
523
524
* to an eventual DMA map in something like gp100_vmm_pgt_pfn()
524
525
*
525
526
* This is all just encoding the internal hmm representation into a
526
527
* different nouveau internal representation.
527
528
*/
528
529
if (!(range -> hmm_pfns [0 ] & HMM_PFN_VALID )) {
529
- ioctl_addr [0 ] = 0 ;
530
+ args -> p . phys [0 ] = 0 ;
530
531
return ;
531
532
}
532
533
533
534
page = hmm_pfn_to_page (range -> hmm_pfns [0 ]);
535
+ /*
536
+ * Only map compound pages to the GPU if the CPU is also mapping the
537
+ * page as a compound page. Otherwise, the PTE protections might not be
538
+ * consistent (e.g., CPU only maps part of a compound page).
539
+ * Note that the underlying page might still be larger than the
540
+ * CPU mapping (e.g., a PUD sized compound page partially mapped with
541
+ * a PMD sized page table entry).
542
+ */
543
+ if (hmm_pfn_to_map_order (range -> hmm_pfns [0 ])) {
544
+ unsigned long addr = args -> p .addr ;
545
+
546
+ args -> p .page = hmm_pfn_to_map_order (range -> hmm_pfns [0 ]) +
547
+ PAGE_SHIFT ;
548
+ args -> p .size = 1UL << args -> p .page ;
549
+ args -> p .addr &= ~(args -> p .size - 1 );
550
+ page -= (addr - args -> p .addr ) >> PAGE_SHIFT ;
551
+ }
534
552
if (is_device_private_page (page ))
535
- ioctl_addr [0 ] = nouveau_dmem_page_addr (page ) |
553
+ args -> p . phys [0 ] = nouveau_dmem_page_addr (page ) |
536
554
NVIF_VMM_PFNMAP_V0_V |
537
555
NVIF_VMM_PFNMAP_V0_VRAM ;
538
556
else
539
- ioctl_addr [0 ] = page_to_phys (page ) |
557
+ args -> p . phys [0 ] = page_to_phys (page ) |
540
558
NVIF_VMM_PFNMAP_V0_V |
541
559
NVIF_VMM_PFNMAP_V0_HOST ;
542
560
if (range -> hmm_pfns [0 ] & HMM_PFN_WRITE )
543
- ioctl_addr [0 ] |= NVIF_VMM_PFNMAP_V0_W ;
561
+ args -> p . phys [0 ] |= NVIF_VMM_PFNMAP_V0_W ;
544
562
}
545
563
546
564
static int nouveau_range_fault (struct nouveau_svmm * svmm ,
547
- struct nouveau_drm * drm , void * data , u32 size ,
548
- u64 * ioctl_addr , unsigned long hmm_flags ,
565
+ struct nouveau_drm * drm ,
566
+ struct nouveau_pfnmap_args * args , u32 size ,
567
+ unsigned long hmm_flags ,
549
568
struct svm_notifier * notifier )
550
569
{
551
570
unsigned long timeout =
@@ -585,10 +604,10 @@ static int nouveau_range_fault(struct nouveau_svmm *svmm,
585
604
break ;
586
605
}
587
606
588
- nouveau_hmm_convert_pfn (drm , & range , ioctl_addr );
607
+ nouveau_hmm_convert_pfn (drm , & range , args );
589
608
590
609
svmm -> vmm -> vmm .object .client -> super = true;
591
- ret = nvif_object_ioctl (& svmm -> vmm -> vmm .object , data , size , NULL );
610
+ ret = nvif_object_ioctl (& svmm -> vmm -> vmm .object , args , size , NULL );
592
611
svmm -> vmm -> vmm .object .client -> super = false;
593
612
mutex_unlock (& svmm -> mutex );
594
613
@@ -717,22 +736,30 @@ nouveau_svm_fault(struct nvif_notify *notify)
717
736
args .i .p .addr , args .i .p .size ,
718
737
& nouveau_svm_mni_ops );
719
738
if (!ret ) {
720
- ret = nouveau_range_fault (svmm , svm -> drm , & args ,
721
- sizeof (args ), args . phys , hmm_flags , & notifier );
739
+ ret = nouveau_range_fault (svmm , svm -> drm , & args . i ,
740
+ sizeof (args ), hmm_flags , & notifier );
722
741
mmu_interval_notifier_remove (& notifier .notifier );
723
742
}
724
743
mmput (mm );
725
744
745
+ limit = args .i .p .addr + args .i .p .size ;
726
746
for (fn = fi ; ++ fn < buffer -> fault_nr ; ) {
727
747
/* It's okay to skip over duplicate addresses from the
728
748
* same SVMM as faults are ordered by access type such
729
749
* that only the first one needs to be handled.
730
750
*
731
751
* ie. WRITE faults appear first, thus any handling of
732
752
* pending READ faults will already be satisfied.
753
+ * But if a large page is mapped, make sure subsequent
754
+ * fault addresses have sufficient access permission.
733
755
*/
734
756
if (buffer -> fault [fn ]-> svmm != svmm ||
735
- buffer -> fault [fn ]-> addr >= limit )
757
+ buffer -> fault [fn ]-> addr >= limit ||
758
+ (buffer -> fault [fi ]-> access == 0 /* READ. */ &&
759
+ !(args .phys [0 ] & NVIF_VMM_PFNMAP_V0_V )) ||
760
+ (buffer -> fault [fi ]-> access != 0 /* READ. */ &&
761
+ buffer -> fault [fi ]-> access != 3 /* PREFETCH. */ &&
762
+ !(args .phys [0 ] & NVIF_VMM_PFNMAP_V0_W )))
736
763
break ;
737
764
}
738
765
0 commit comments