@@ -235,6 +235,8 @@ struct apple_dart {
235235
236236 u32 save_tcr [DART_MAX_STREAMS ];
237237 u32 save_ttbr [DART_MAX_STREAMS ][DART_MAX_TTBR ];
238+
239+ u64 * locked_ttbr [DART_MAX_STREAMS ][DART_MAX_TTBR ];
238240};
239241
240242/*
@@ -386,6 +388,82 @@ apple_dart_hw_clear_all_ttbrs(struct apple_dart_stream_map *stream_map)
386388 apple_dart_hw_clear_ttbr (stream_map , i );
387389}
388390
391+ static int
392+ apple_dart_hw_map_locked_ttbr (struct apple_dart_stream_map * stream_map , u8 idx )
393+ {
394+ struct apple_dart * dart = stream_map -> dart ;
395+ int sid ;
396+
397+ for_each_set_bit (sid , stream_map -> sidmap , dart -> num_streams ) {
398+ u32 ttbr ;
399+ phys_addr_t phys ;
400+ u64 * l1_tbl ;
401+
402+ ttbr = readl (dart -> regs + DART_TTBR (dart , sid , idx ));
403+
404+ if (!(ttbr & dart -> hw -> ttbr_valid )) {
405+ dev_err (dart -> dev , "Invalid ttbr[%u] for locked dart\n" ,
406+ idx );
407+ return - EIO ;
408+ }
409+
410+ ttbr &= ~dart -> hw -> ttbr_valid ;
411+
412+ if (dart -> hw -> ttbr_addr_field_shift )
413+ ttbr >>= dart -> hw -> ttbr_addr_field_shift ;
414+ phys = ((phys_addr_t ) ttbr ) << dart -> hw -> ttbr_shift ;
415+
416+ l1_tbl = devm_memremap (dart -> dev , phys , dart -> pgsize ,
417+ MEMREMAP_WB );
418+ if (!l1_tbl )
419+ return - ENOMEM ;
420+
421+ dart -> locked_ttbr [sid ][idx ] = l1_tbl ;
422+ }
423+
424+ return 0 ;
425+ }
426+
427+ static int
428+ apple_dart_hw_unmap_locked_ttbr (struct apple_dart_stream_map * stream_map ,
429+ u8 idx )
430+ {
431+ struct apple_dart * dart = stream_map -> dart ;
432+ int sid ;
433+
434+ for_each_set_bit (sid , stream_map -> sidmap , dart -> num_streams ) {
435+ /* TODO: locked L1 table might need to be restored to boot state */
436+ if (dart -> locked_ttbr [sid ][idx ]) {
437+ memset (dart -> locked_ttbr [sid ][idx ], 0 , dart -> pgsize );
438+ devm_memunmap (dart -> dev , dart -> locked_ttbr [sid ][idx ]);
439+ }
440+ dart -> locked_ttbr [sid ][idx ] = NULL ;
441+ }
442+
443+ return 0 ;
444+ }
445+
446+ static int
447+ apple_dart_hw_sync_locked (struct io_pgtable_cfg * cfg ,
448+ struct apple_dart_stream_map * stream_map )
449+ {
450+ struct apple_dart * dart = stream_map -> dart ;
451+ int sid ;
452+
453+ for_each_set_bit (sid , stream_map -> sidmap , dart -> num_streams ) {
454+ for (int idx = 0 ; idx < dart -> hw -> ttbr_count ; idx ++ ) {
455+ u64 * ttbrep = dart -> locked_ttbr [sid ][idx ];
456+ u64 * ptep = cfg -> apple_dart_cfg .ttbr [idx ];
457+ if (!ttbrep || !ptep )
458+ continue ;
459+ for (int entry = 0 ; entry < dart -> pgsize / sizeof (* ptep ); entry ++ )
460+ ttbrep [entry ] = ptep [entry ];
461+ }
462+ }
463+
464+ return 0 ;
465+ }
466+
389467static int
390468apple_dart_t8020_hw_stream_command (struct apple_dart_stream_map * stream_map ,
391469 u32 command )
@@ -507,6 +585,8 @@ static void apple_dart_domain_flush_tlb(struct apple_dart_domain *domain)
507585 int i , j ;
508586 struct apple_dart_atomic_stream_map * domain_stream_map ;
509587 struct apple_dart_stream_map stream_map ;
588+ struct io_pgtable_cfg * pgtbl_cfg =
589+ & io_pgtable_ops_to_pgtable (domain -> pgtbl_ops )-> cfg ;
510590
511591 for_each_stream_map (i , domain , domain_stream_map ) {
512592 stream_map .dart = domain_stream_map -> dart ;
@@ -515,6 +595,10 @@ static void apple_dart_domain_flush_tlb(struct apple_dart_domain *domain)
515595 stream_map .sidmap [j ] = atomic_long_read (& domain_stream_map -> sidmap [j ]);
516596
517597 WARN_ON (pm_runtime_get_sync (stream_map .dart -> dev ) < 0 );
598+
599+ if (stream_map .dart -> locked )
600+ apple_dart_hw_sync_locked (pgtbl_cfg , & stream_map );
601+
518602 stream_map .dart -> hw -> invalidate_tlb (& stream_map );
519603 pm_runtime_put (stream_map .dart -> dev );
520604 }
@@ -597,6 +681,24 @@ apple_dart_setup_translation(struct apple_dart_domain *domain,
597681 stream_map -> dart -> hw -> invalidate_tlb (stream_map );
598682}
599683
684+ static void
685+ apple_dart_setup_translation_locked (struct apple_dart_domain * domain ,
686+ struct apple_dart_stream_map * stream_map )
687+ {
688+ int i ;
689+ struct io_pgtable_cfg * pgtbl_cfg =
690+ & io_pgtable_ops_to_pgtable (domain -> pgtbl_ops )-> cfg ;
691+
692+ /* Locked DARTs are set up by the bootloader. */
693+ for (i = 0 ; i < pgtbl_cfg -> apple_dart_cfg .n_ttbrs ; ++ i )
694+ apple_dart_hw_map_locked_ttbr (stream_map , i );
695+ for (; i < stream_map -> dart -> hw -> ttbr_count ; ++ i )
696+ apple_dart_hw_unmap_locked_ttbr (stream_map , i );
697+
698+ apple_dart_hw_sync_locked (pgtbl_cfg , stream_map );
699+ stream_map -> dart -> hw -> invalidate_tlb (stream_map );
700+ }
701+
600702static int apple_dart_finalize_domain (struct apple_dart_domain * dart_domain ,
601703 struct apple_dart_master_cfg * cfg )
602704{
@@ -630,6 +732,42 @@ static int apple_dart_finalize_domain(struct apple_dart_domain *dart_domain,
630732 .iommu_dev = dart -> dev ,
631733 };
632734
735+ if (dart -> locked ) {
736+ unsigned long * sidmap ;
737+ int sid ;
738+ u32 ttbr ;
739+
740+ /* Locked DARTs can only have a single stream bound */
741+ sidmap = cfg -> stream_maps [0 ].sidmap ;
742+ sid = find_first_bit (sidmap , dart -> num_streams );
743+
744+ WARN_ON ((sid < 0 ) || bitmap_weight (sidmap , dart -> num_streams ) > 1 );
745+ ttbr = readl (dart -> regs + DART_TTBR (dart , sid , 0 ));
746+
747+ WARN_ON (!(ttbr & dart -> hw -> ttbr_valid ));
748+
749+ /* If the DART is locked, we need to keep the translation level count. */
750+ if (dart -> hw -> tcr_4level && dart -> ias > 36 ) {
751+ if (readl (dart -> regs + DART_TCR (dart , sid )) & dart -> hw -> tcr_4level ) {
752+ if (ias < 37 ) {
753+ dev_info (dart -> dev , "Expanded to ias=37 due to lock\n" );
754+ pgtbl_cfg .ias = 37 ;
755+ }
756+ } else if (ias > 36 ) {
757+ dev_info (dart -> dev , "Limited to ias=36 due to lock\n" );
758+ pgtbl_cfg .ias = 36 ;
759+ if (dart -> dma_min == 0 && dma_max == DMA_BIT_MASK (dart -> ias )) {
760+ dma_max = DMA_BIT_MASK (pgtbl_cfg .ias );
761+ } else if ((dart -> dma_min ^ dma_max ) & ~DMA_BIT_MASK (36 )) {
762+ dev_err (dart -> dev ,
763+ "Invalid DMA range for locked 3-level PT\n" );
764+ ret = - ENOMEM ;
765+ goto done ;
766+ }
767+ }
768+ }
769+ }
770+
633771 dart_domain -> pgtbl_ops = alloc_io_pgtable_ops (dart -> hw -> fmt , & pgtbl_cfg ,
634772 & dart_domain -> domain );
635773 if (!dart_domain -> pgtbl_ops ) {
@@ -710,8 +848,13 @@ static int apple_dart_attach_dev_paging(struct iommu_domain *domain,
710848 if (ret )
711849 goto err ;
712850
713- for_each_stream_map (i , cfg , stream_map )
714- apple_dart_setup_translation (dart_domain , stream_map );
851+ for_each_stream_map (i , cfg , stream_map ) {
852+ if (!stream_map -> dart -> locked )
853+ apple_dart_setup_translation (dart_domain , stream_map );
854+ else
855+ apple_dart_setup_translation_locked (dart_domain ,
856+ stream_map );
857+ }
715858
716859err :
717860 for_each_stream_map (i , cfg , stream_map )
@@ -795,8 +938,16 @@ static struct iommu_device *apple_dart_probe_device(struct device *dev)
795938
796939static void apple_dart_release_device (struct device * dev )
797940{
941+ int i , j ;
942+ struct apple_dart_stream_map * stream_map ;
798943 struct apple_dart_master_cfg * cfg = dev_iommu_priv_get (dev );
799944
945+ for_each_stream_map (j , cfg , stream_map ) {
946+ if (stream_map -> dart -> locked )
947+ for (i = 0 ; i < stream_map -> dart -> hw -> ttbr_count ; ++ i )
948+ apple_dart_hw_unmap_locked_ttbr (stream_map , i );
949+ }
950+
800951 kfree (cfg );
801952}
802953
@@ -1073,6 +1224,11 @@ static const struct iommu_ops apple_dart_iommu_no_bypass_ops = {
10731224 APPLE_DART_IOMMU_COMMON_OPS ()
10741225};
10751226
1227+ static const struct iommu_ops apple_dart_iommu_locked_ops = {
1228+ .def_domain_type = apple_dart_def_domain_type_dma ,
1229+ APPLE_DART_IOMMU_COMMON_OPS ()
1230+ };
1231+
10761232static irqreturn_t apple_dart_t8020_irq (int irq , void * dev )
10771233{
10781234 struct apple_dart * dart = dev ;
@@ -1282,7 +1438,9 @@ static int apple_dart_probe(struct platform_device *pdev)
12821438 if (ret )
12831439 goto err_free_irq ;
12841440
1285- if (!dart -> supports_bypass )
1441+ if (dart -> locked )
1442+ ret = iommu_device_register (& dart -> iommu , & apple_dart_iommu_locked_ops , dev );
1443+ else if (!dart -> supports_bypass )
12861444 ret = iommu_device_register (& dart -> iommu , & apple_dart_iommu_no_bypass_ops , dev );
12871445 else
12881446 ret = iommu_device_register (& dart -> iommu , & apple_dart_iommu_ops , dev );
0 commit comments