@@ -359,6 +359,16 @@ pasid_set_flpm(struct pasid_entry *pe, u64 value)
359
359
pasid_set_bits (& pe -> val [2 ], GENMASK_ULL (3 , 2 ), value << 2 );
360
360
}
361
361
362
+ /*
363
+ * Setup the Extended Access Flag Enable (EAFE) field (Bit 135)
364
+ * of a scalable mode PASID entry.
365
+ */
366
+ static inline void
367
+ pasid_set_eafe (struct pasid_entry * pe )
368
+ {
369
+ pasid_set_bits (& pe -> val [2 ], 1 << 7 , 1 << 7 );
370
+ }
371
+
362
372
static void
363
373
pasid_cache_invalidation_with_pasid (struct intel_iommu * iommu ,
364
374
u16 did , int pasid )
@@ -492,7 +502,7 @@ int intel_pasid_setup_first_level(struct intel_iommu *iommu,
492
502
pasid_set_page_snoop (pte , !!ecap_smpwc (iommu -> ecap ));
493
503
494
504
/* Setup Present and PASID Granular Transfer Type: */
495
- pasid_set_translation_type (pte , 1 );
505
+ pasid_set_translation_type (pte , PASID_ENTRY_PGTT_FL_ONLY );
496
506
pasid_set_present (pte );
497
507
pasid_flush_caches (iommu , pte , pasid , did );
498
508
@@ -561,7 +571,7 @@ int intel_pasid_setup_second_level(struct intel_iommu *iommu,
561
571
pasid_set_domain_id (pte , did );
562
572
pasid_set_slptr (pte , pgd_val );
563
573
pasid_set_address_width (pte , agaw );
564
- pasid_set_translation_type (pte , 2 );
574
+ pasid_set_translation_type (pte , PASID_ENTRY_PGTT_SL_ONLY );
565
575
pasid_set_fault_enable (pte );
566
576
pasid_set_page_snoop (pte , !!ecap_smpwc (iommu -> ecap ));
567
577
@@ -595,7 +605,7 @@ int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
595
605
pasid_clear_entry (pte );
596
606
pasid_set_domain_id (pte , did );
597
607
pasid_set_address_width (pte , iommu -> agaw );
598
- pasid_set_translation_type (pte , 4 );
608
+ pasid_set_translation_type (pte , PASID_ENTRY_PGTT_PT );
599
609
pasid_set_fault_enable (pte );
600
610
pasid_set_page_snoop (pte , !!ecap_smpwc (iommu -> ecap ));
601
611
@@ -609,3 +619,161 @@ int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
609
619
610
620
return 0 ;
611
621
}
622
+
623
+ static int
624
+ intel_pasid_setup_bind_data (struct intel_iommu * iommu , struct pasid_entry * pte ,
625
+ struct iommu_gpasid_bind_data_vtd * pasid_data )
626
+ {
627
+ /*
628
+ * Not all guest PASID table entry fields are passed down during bind,
629
+ * here we only set up the ones that are dependent on guest settings.
630
+ * Execution related bits such as NXE, SMEP are not supported.
631
+ * Other fields, such as snoop related, are set based on host needs
632
+ * regardless of guest settings.
633
+ */
634
+ if (pasid_data -> flags & IOMMU_SVA_VTD_GPASID_SRE ) {
635
+ if (!ecap_srs (iommu -> ecap )) {
636
+ pr_err_ratelimited ("No supervisor request support on %s\n" ,
637
+ iommu -> name );
638
+ return - EINVAL ;
639
+ }
640
+ pasid_set_sre (pte );
641
+ }
642
+
643
+ if (pasid_data -> flags & IOMMU_SVA_VTD_GPASID_EAFE ) {
644
+ if (!ecap_eafs (iommu -> ecap )) {
645
+ pr_err_ratelimited ("No extended access flag support on %s\n" ,
646
+ iommu -> name );
647
+ return - EINVAL ;
648
+ }
649
+ pasid_set_eafe (pte );
650
+ }
651
+
652
+ /*
653
+ * Memory type is only applicable to devices inside processor coherent
654
+ * domain. Will add MTS support once coherent devices are available.
655
+ */
656
+ if (pasid_data -> flags & IOMMU_SVA_VTD_GPASID_MTS_MASK ) {
657
+ pr_warn_ratelimited ("No memory type support %s\n" ,
658
+ iommu -> name );
659
+ return - EINVAL ;
660
+ }
661
+
662
+ return 0 ;
663
+ }
664
+
665
+ /**
666
+ * intel_pasid_setup_nested() - Set up PASID entry for nested translation.
667
+ * This could be used for guest shared virtual address. In this case, the
668
+ * first level page tables are used for GVA-GPA translation in the guest,
669
+ * second level page tables are used for GPA-HPA translation.
670
+ *
671
+ * @iommu: IOMMU which the device belong to
672
+ * @dev: Device to be set up for translation
673
+ * @gpgd: FLPTPTR: First Level Page translation pointer in GPA
674
+ * @pasid: PASID to be programmed in the device PASID table
675
+ * @pasid_data: Additional PASID info from the guest bind request
676
+ * @domain: Domain info for setting up second level page tables
677
+ * @addr_width: Address width of the first level (guest)
678
+ */
679
+ int intel_pasid_setup_nested (struct intel_iommu * iommu , struct device * dev ,
680
+ pgd_t * gpgd , int pasid ,
681
+ struct iommu_gpasid_bind_data_vtd * pasid_data ,
682
+ struct dmar_domain * domain , int addr_width )
683
+ {
684
+ struct pasid_entry * pte ;
685
+ struct dma_pte * pgd ;
686
+ int ret = 0 ;
687
+ u64 pgd_val ;
688
+ int agaw ;
689
+ u16 did ;
690
+
691
+ if (!ecap_nest (iommu -> ecap )) {
692
+ pr_err_ratelimited ("IOMMU: %s: No nested translation support\n" ,
693
+ iommu -> name );
694
+ return - EINVAL ;
695
+ }
696
+
697
+ if (!(domain -> flags & DOMAIN_FLAG_NESTING_MODE )) {
698
+ pr_err_ratelimited ("Domain is not in nesting mode, %x\n" ,
699
+ domain -> flags );
700
+ return - EINVAL ;
701
+ }
702
+
703
+ pte = intel_pasid_get_entry (dev , pasid );
704
+ if (WARN_ON (!pte ))
705
+ return - EINVAL ;
706
+
707
+ /*
708
+ * Caller must ensure PASID entry is not in use, i.e. not bind the
709
+ * same PASID to the same device twice.
710
+ */
711
+ if (pasid_pte_is_present (pte ))
712
+ return - EBUSY ;
713
+
714
+ pasid_clear_entry (pte );
715
+
716
+ /* Sanity checking performed by caller to make sure address
717
+ * width matching in two dimensions:
718
+ * 1. CPU vs. IOMMU
719
+ * 2. Guest vs. Host.
720
+ */
721
+ switch (addr_width ) {
722
+ #ifdef CONFIG_X86
723
+ case ADDR_WIDTH_5LEVEL :
724
+ if (!cpu_feature_enabled (X86_FEATURE_LA57 ) ||
725
+ !cap_5lp_support (iommu -> cap )) {
726
+ dev_err_ratelimited (dev ,
727
+ "5-level paging not supported\n" );
728
+ return - EINVAL ;
729
+ }
730
+
731
+ pasid_set_flpm (pte , 1 );
732
+ break ;
733
+ #endif
734
+ case ADDR_WIDTH_4LEVEL :
735
+ pasid_set_flpm (pte , 0 );
736
+ break ;
737
+ default :
738
+ dev_err_ratelimited (dev , "Invalid guest address width %d\n" ,
739
+ addr_width );
740
+ return - EINVAL ;
741
+ }
742
+
743
+ /* First level PGD is in GPA, must be supported by the second level */
744
+ if ((unsigned long long )gpgd > domain -> max_addr ) {
745
+ dev_err_ratelimited (dev ,
746
+ "Guest PGD %llx not supported, max %llx\n" ,
747
+ (unsigned long long )gpgd , domain -> max_addr );
748
+ return - EINVAL ;
749
+ }
750
+ pasid_set_flptr (pte , (u64 )gpgd );
751
+
752
+ ret = intel_pasid_setup_bind_data (iommu , pte , pasid_data );
753
+ if (ret )
754
+ return ret ;
755
+
756
+ /* Setup the second level based on the given domain */
757
+ pgd = domain -> pgd ;
758
+
759
+ agaw = iommu_skip_agaw (domain , iommu , & pgd );
760
+ if (agaw < 0 ) {
761
+ dev_err_ratelimited (dev , "Invalid domain page table\n" );
762
+ return - EINVAL ;
763
+ }
764
+ pgd_val = virt_to_phys (pgd );
765
+ pasid_set_slptr (pte , pgd_val );
766
+ pasid_set_fault_enable (pte );
767
+
768
+ did = domain -> iommu_did [iommu -> seq_id ];
769
+ pasid_set_domain_id (pte , did );
770
+
771
+ pasid_set_address_width (pte , agaw );
772
+ pasid_set_page_snoop (pte , !!ecap_smpwc (iommu -> ecap ));
773
+
774
+ pasid_set_translation_type (pte , PASID_ENTRY_PGTT_NESTED );
775
+ pasid_set_present (pte );
776
+ pasid_flush_caches (iommu , pte , pasid , did );
777
+
778
+ return ret ;
779
+ }
0 commit comments