@@ -225,6 +225,8 @@ struct apple_dart {
225225
226226 u32 save_tcr [DART_MAX_STREAMS ];
227227 u32 save_ttbr [DART_MAX_STREAMS ][DART_MAX_TTBR ];
228+
229+ u64 * locked_ttbr [DART_MAX_STREAMS ][DART_MAX_TTBR ];
228230};
229231
230232/*
@@ -369,6 +371,82 @@ apple_dart_hw_clear_all_ttbrs(struct apple_dart_stream_map *stream_map)
369371 apple_dart_hw_clear_ttbr (stream_map , i );
370372}
371373
374+ static int
375+ apple_dart_hw_map_locked_ttbr (struct apple_dart_stream_map * stream_map , u8 idx )
376+ {
377+ struct apple_dart * dart = stream_map -> dart ;
378+ int sid ;
379+
380+ for_each_set_bit (sid , stream_map -> sidmap , dart -> num_streams ) {
381+ u32 ttbr ;
382+ phys_addr_t phys ;
383+ u64 * l1_tbl ;
384+
385+ ttbr = readl (dart -> regs + DART_TTBR (dart , sid , idx ));
386+
387+ if (!(ttbr & dart -> hw -> ttbr_valid )) {
388+ dev_err (dart -> dev , "Invalid ttbr[%u] for locked dart\n" ,
389+ idx );
390+ return - EIO ;
391+ }
392+
393+ ttbr &= ~dart -> hw -> ttbr_valid ;
394+
395+ if (dart -> hw -> ttbr_addr_field_shift )
396+ ttbr >>= dart -> hw -> ttbr_addr_field_shift ;
397+ phys = ((phys_addr_t ) ttbr ) << dart -> hw -> ttbr_shift ;
398+
399+ l1_tbl = devm_memremap (dart -> dev , phys , dart -> pgsize ,
400+ MEMREMAP_WB );
401+ if (!l1_tbl )
402+ return - ENOMEM ;
403+
404+ dart -> locked_ttbr [sid ][idx ] = l1_tbl ;
405+ }
406+
407+ return 0 ;
408+ }
409+
410+ static int
411+ apple_dart_hw_unmap_locked_ttbr (struct apple_dart_stream_map * stream_map ,
412+ u8 idx )
413+ {
414+ struct apple_dart * dart = stream_map -> dart ;
415+ int sid ;
416+
417+ for_each_set_bit (sid , stream_map -> sidmap , dart -> num_streams ) {
418+ /* TODO: locked L1 table might need to be restored to boot state */
419+ if (dart -> locked_ttbr [sid ][idx ]) {
420+ memset (dart -> locked_ttbr [sid ][idx ], 0 , dart -> pgsize );
421+ devm_memunmap (dart -> dev , dart -> locked_ttbr [sid ][idx ]);
422+ }
423+ dart -> locked_ttbr [sid ][idx ] = NULL ;
424+ }
425+
426+ return 0 ;
427+ }
428+
429+ static int
430+ apple_dart_hw_sync_locked (struct io_pgtable_cfg * cfg ,
431+ struct apple_dart_stream_map * stream_map )
432+ {
433+ struct apple_dart * dart = stream_map -> dart ;
434+ int sid ;
435+
436+ for_each_set_bit (sid , stream_map -> sidmap , dart -> num_streams ) {
437+ for (int idx = 0 ; idx < dart -> hw -> ttbr_count ; idx ++ ) {
438+ u64 * ttbrep = dart -> locked_ttbr [sid ][idx ];
439+ u64 * ptep = cfg -> apple_dart_cfg .ttbr [idx ];
440+ if (!ttbrep || !ptep )
441+ continue ;
442+ for (int entry = 0 ; entry < dart -> pgsize / sizeof (* ptep ); entry ++ )
443+ ttbrep [entry ] = ptep [entry ];
444+ }
445+ }
446+
447+ return 0 ;
448+ }
449+
372450static int
373451apple_dart_t8020_hw_stream_command (struct apple_dart_stream_map * stream_map ,
374452 u32 command )
@@ -490,13 +568,18 @@ static void apple_dart_domain_flush_tlb(struct apple_dart_domain *domain)
490568 int i , j ;
491569 struct apple_dart_atomic_stream_map * domain_stream_map ;
492570 struct apple_dart_stream_map stream_map ;
571+ struct io_pgtable_cfg * pgtbl_cfg =
572+ & io_pgtable_ops_to_pgtable (domain -> pgtbl_ops )-> cfg ;
493573
494574 for_each_stream_map (i , domain , domain_stream_map ) {
495575 stream_map .dart = domain_stream_map -> dart ;
496576
497577 for (j = 0 ; j < BITS_TO_LONGS (stream_map .dart -> num_streams ); j ++ )
498578 stream_map .sidmap [j ] = atomic_long_read (& domain_stream_map -> sidmap [j ]);
499579
580+ if (stream_map .dart -> locked )
581+ apple_dart_hw_sync_locked (pgtbl_cfg , & stream_map );
582+
500583 stream_map .dart -> hw -> invalidate_tlb (& stream_map );
501584 }
502585}
@@ -576,6 +659,24 @@ apple_dart_setup_translation(struct apple_dart_domain *domain,
576659 stream_map -> dart -> hw -> invalidate_tlb (stream_map );
577660}
578661
662+ static void
663+ apple_dart_setup_translation_locked (struct apple_dart_domain * domain ,
664+ struct apple_dart_stream_map * stream_map )
665+ {
666+ int i ;
667+ struct io_pgtable_cfg * pgtbl_cfg =
668+ & io_pgtable_ops_to_pgtable (domain -> pgtbl_ops )-> cfg ;
669+
670+ /* Locked DARTs are set up by the bootloader. */
671+ for (i = 0 ; i < pgtbl_cfg -> apple_dart_cfg .n_ttbrs ; ++ i )
672+ apple_dart_hw_map_locked_ttbr (stream_map , i );
673+ for (; i < stream_map -> dart -> hw -> ttbr_count ; ++ i )
674+ apple_dart_hw_unmap_locked_ttbr (stream_map , i );
675+
676+ apple_dart_hw_sync_locked (pgtbl_cfg , stream_map );
677+ stream_map -> dart -> hw -> invalidate_tlb (stream_map );
678+ }
679+
579680static int apple_dart_finalize_domain (struct apple_dart_domain * dart_domain ,
580681 struct apple_dart_master_cfg * cfg )
581682{
@@ -607,6 +708,21 @@ static int apple_dart_finalize_domain(struct apple_dart_domain *dart_domain,
607708 .iommu_dev = dart -> dev ,
608709 };
609710
711+ if (dart -> locked ) {
712+ unsigned long * sidmap ;
713+ int sid ;
714+ u32 ttbr ;
715+
716+ /* Locked DARTs can only have a single stream bound */
717+ sidmap = cfg -> stream_maps [0 ].sidmap ;
718+ sid = find_first_bit (sidmap , dart -> num_streams );
719+
720+ WARN_ON ((sid < 0 ) || bitmap_weight (sidmap , dart -> num_streams ) > 1 );
721+ ttbr = readl (dart -> regs + DART_TTBR (dart , sid , 0 ));
722+
723+ WARN_ON (!(ttbr & dart -> hw -> ttbr_valid ));
724+ }
725+
610726 dart_domain -> pgtbl_ops = alloc_io_pgtable_ops (dart -> hw -> fmt , & pgtbl_cfg ,
611727 & dart_domain -> domain );
612728 if (!dart_domain -> pgtbl_ops ) {
@@ -678,8 +794,14 @@ static int apple_dart_attach_dev_paging(struct iommu_domain *domain,
678794 if (ret )
679795 return ret ;
680796
681- for_each_stream_map (i , cfg , stream_map )
682- apple_dart_setup_translation (dart_domain , stream_map );
797+ for_each_stream_map (i , cfg , stream_map ) {
798+ if (!stream_map -> dart -> locked )
799+ apple_dart_setup_translation (dart_domain , stream_map );
800+ else
801+ apple_dart_setup_translation_locked (dart_domain ,
802+ stream_map );
803+ }
804+
683805 return 0 ;
684806}
685807
@@ -747,8 +869,16 @@ static struct iommu_device *apple_dart_probe_device(struct device *dev)
747869
748870static void apple_dart_release_device (struct device * dev )
749871{
872+ int i , j ;
873+ struct apple_dart_stream_map * stream_map ;
750874 struct apple_dart_master_cfg * cfg = dev_iommu_priv_get (dev );
751875
876+ for_each_stream_map (j , cfg , stream_map ) {
877+ if (stream_map -> dart -> locked )
878+ for (i = 0 ; i < stream_map -> dart -> hw -> ttbr_count ; ++ i )
879+ apple_dart_hw_unmap_locked_ttbr (stream_map , i );
880+ }
881+
752882 kfree (cfg );
753883}
754884
@@ -1025,6 +1155,11 @@ static const struct iommu_ops apple_dart_iommu_no_bypass_ops = {
10251155 APPLE_DART_IOMMU_COMMON_OPS ()
10261156};
10271157
1158+ static const struct iommu_ops apple_dart_iommu_locked_ops = {
1159+ .def_domain_type = apple_dart_def_domain_type_dma ,
1160+ APPLE_DART_IOMMU_COMMON_OPS ()
1161+ };
1162+
10281163static irqreturn_t apple_dart_t8020_irq (int irq , void * dev )
10291164{
10301165 struct apple_dart * dart = dev ;
@@ -1190,7 +1325,9 @@ static int apple_dart_probe(struct platform_device *pdev)
11901325 if (ret )
11911326 goto err_free_irq ;
11921327
1193- if (!dart -> supports_bypass )
1328+ if (dart -> locked )
1329+ ret = iommu_device_register (& dart -> iommu , & apple_dart_iommu_locked_ops , dev );
1330+ else if (!dart -> supports_bypass )
11941331 ret = iommu_device_register (& dart -> iommu , & apple_dart_iommu_no_bypass_ops , dev );
11951332 else
11961333 ret = iommu_device_register (& dart -> iommu , & apple_dart_iommu_ops , dev );
0 commit comments