@@ -225,6 +225,9 @@ 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 ];
230+ u64 * shadow_ttbr [DART_MAX_STREAMS ][DART_MAX_TTBR ];
228231};
229232
230233/*
@@ -371,6 +374,89 @@ apple_dart_hw_clear_all_ttbrs(struct apple_dart_stream_map *stream_map)
371374 apple_dart_hw_clear_ttbr (stream_map , i );
372375}
373376
377+ static int
378+ apple_dart_hw_set_locked_ttbr (struct apple_dart_stream_map * stream_map , u8 idx ,
379+ phys_addr_t paddr )
380+ {
381+ struct apple_dart * dart = stream_map -> dart ;
382+ int sid ;
383+
384+ WARN_ON (!dart -> locked );
385+ WARN_ON (paddr & ((1 << dart -> hw -> ttbr_shift ) - 1 ));
386+ for_each_set_bit (sid , stream_map -> sidmap , dart -> num_streams ) {
387+ u32 ttbr ;
388+ phys_addr_t phys ;
389+ u64 * l1_tbl , * l1_shadow ;
390+
391+ ttbr = readl (dart -> regs + DART_TTBR (dart , sid , idx ));
392+
393+ WARN_ON (!(ttbr & dart -> hw -> ttbr_valid ));
394+ ttbr &= ~dart -> hw -> ttbr_valid ;
395+
396+ if (dart -> hw -> ttbr_addr_field_shift )
397+ ttbr >>= dart -> hw -> ttbr_addr_field_shift ;
398+ phys = ((phys_addr_t ) ttbr ) << dart -> hw -> ttbr_shift ;
399+
400+ l1_tbl = devm_memremap (dart -> dev , phys , dart -> pgsize ,
401+ MEMREMAP_WB );
402+ if (!l1_tbl )
403+ return - ENOMEM ;
404+ l1_shadow = devm_memremap (dart -> dev , paddr , dart -> pgsize ,
405+ MEMREMAP_WB );
406+ if (!l1_shadow )
407+ return - ENOMEM ;
408+
409+ dart -> locked_ttbr [sid ][idx ] = l1_tbl ;
410+ dart -> shadow_ttbr [sid ][idx ] = l1_shadow ;
411+ }
412+
413+ return 0 ;
414+ }
415+
416+ static int
417+ apple_dart_hw_clear_locked_ttbr (struct apple_dart_stream_map * stream_map ,
418+ u8 idx )
419+ {
420+ struct apple_dart * dart = stream_map -> dart ;
421+ int sid ;
422+
423+ WARN_ON (!dart -> locked );
424+ for_each_set_bit (sid , stream_map -> sidmap , dart -> num_streams ) {
425+ /* TODO: locked L1 table might need to be restored to boot state */
426+ if (dart -> locked_ttbr [sid ][idx ]) {
427+ memset (dart -> locked_ttbr [sid ][idx ], 0 , dart -> pgsize );
428+ devm_memunmap (dart -> dev , dart -> locked_ttbr [sid ][idx ]);
429+ }
430+ dart -> locked_ttbr [sid ][idx ] = NULL ;
431+ if (dart -> shadow_ttbr [sid ][idx ])
432+ devm_memunmap (dart -> dev , dart -> shadow_ttbr [sid ][idx ]);
433+ dart -> shadow_ttbr [sid ][idx ] = NULL ;
434+ }
435+
436+ return 0 ;
437+ }
438+
439+ static int
440+ apple_dart_hw_sync_locked (struct apple_dart_stream_map * stream_map )
441+ {
442+ struct apple_dart * dart = stream_map -> dart ;
443+ int sid ;
444+
445+ WARN_ON (!dart -> locked );
446+ for_each_set_bit (sid , stream_map -> sidmap , dart -> num_streams ) {
447+ for (int idx = 0 ; idx < dart -> hw -> ttbr_count ; idx ++ ) {
448+ u64 * ttbrep = dart -> locked_ttbr [sid ][idx ];
449+ u64 * ptep = dart -> shadow_ttbr [sid ][idx ];
450+ if (!ttbrep || !ptep )
451+ continue ;
452+ for (int entry = 0 ; entry < dart -> pgsize / sizeof (* ptep ); entry ++ )
453+ ttbrep [entry ] = ptep [entry ];
454+ }
455+ }
456+
457+ return 0 ;
458+ }
459+
374460static int
375461apple_dart_t8020_hw_stream_command (struct apple_dart_stream_map * stream_map ,
376462 u32 command )
@@ -491,6 +577,10 @@ static void apple_dart_domain_flush_tlb(struct apple_dart_domain *domain)
491577 for (j = 0 ; j < BITS_TO_LONGS (stream_map .dart -> num_streams ); j ++ )
492578 stream_map .sidmap [j ] = atomic_long_read (& domain_stream_map -> sidmap [j ]);
493579
580+
581+ if (stream_map .dart -> locked )
582+ apple_dart_hw_sync_locked (& stream_map );
583+
494584 stream_map .dart -> hw -> invalidate_tlb (& stream_map );
495585 }
496586}
@@ -559,17 +649,62 @@ apple_dart_setup_translation(struct apple_dart_domain *domain,
559649 struct io_pgtable_cfg * pgtbl_cfg =
560650 & io_pgtable_ops_to_pgtable (domain -> pgtbl_ops )-> cfg ;
561651
562- for (i = 0 ; i < pgtbl_cfg -> apple_dart_cfg .n_ttbrs ; ++ i )
563- apple_dart_hw_set_ttbr (stream_map , i ,
564- pgtbl_cfg -> apple_dart_cfg .ttbr [i ]);
565- for (; i < stream_map -> dart -> hw -> ttbr_count ; ++ i )
566- apple_dart_hw_clear_ttbr (stream_map , i );
652+ /* Locked DARTs are set up by the bootloader. */
653+ if (stream_map -> dart -> locked ) {
654+ for (i = 0 ; i < pgtbl_cfg -> apple_dart_cfg .n_ttbrs ; ++ i )
655+ apple_dart_hw_set_locked_ttbr (stream_map , i ,
656+ pgtbl_cfg -> apple_dart_cfg .ttbr [i ]);
657+ for (; i < stream_map -> dart -> hw -> ttbr_count ; ++ i )
658+ apple_dart_hw_clear_locked_ttbr (stream_map , i );
659+ apple_dart_hw_sync_locked (stream_map );
660+ } else {
661+ for (i = 0 ; i < pgtbl_cfg -> apple_dart_cfg .n_ttbrs ; ++ i )
662+ apple_dart_hw_set_ttbr (stream_map , i ,
663+ pgtbl_cfg -> apple_dart_cfg .ttbr [i ]);
664+ for (; i < stream_map -> dart -> hw -> ttbr_count ; ++ i )
665+ apple_dart_hw_clear_ttbr (stream_map , i );
567666
568- apple_dart_hw_enable_translation (stream_map );
667+ apple_dart_hw_enable_translation (stream_map );
668+ }
569669 stream_map -> dart -> hw -> invalidate_tlb (stream_map );
570670}
571671
672+ static int apple_dart_setup_resv_locked (struct iommu_domain * domain ,
673+ struct device * dev , size_t pgsize )
674+ {
675+ struct iommu_resv_region * region ;
676+ LIST_HEAD (resv_regions );
677+ int ret = 0 ;
678+
679+ of_iommu_get_resv_regions (dev , & resv_regions );
680+ list_for_each_entry (region , & resv_regions , list ) {
681+ size_t mapped = 0 ;
682+
683+ /* Only map translated reserved regions */
684+ if (region -> type != IOMMU_RESV_TRANSLATED )
685+ continue ;
686+
687+ while (mapped < region -> length ) {
688+ phys_addr_t paddr = region -> start + mapped ;
689+ unsigned long iova = region -> dva + mapped ;
690+ size_t length = region -> length - mapped ;
691+ size_t pgcount = length / pgsize ;
692+
693+ ret = apple_dart_map_pages (domain , iova ,
694+ paddr , pgsize , pgcount ,
695+ region -> prot , GFP_KERNEL , & mapped );
696+
697+ if (ret )
698+ goto end_put ;
699+ }
700+ }
701+ end_put :
702+ iommu_put_resv_regions (dev , & resv_regions );
703+ return ret ;
704+ }
705+
572706static int apple_dart_finalize_domain (struct apple_dart_domain * dart_domain ,
707+ struct device * dev ,
573708 struct apple_dart_master_cfg * cfg )
574709{
575710 struct apple_dart * dart = cfg -> stream_maps [0 ].dart ;
@@ -600,6 +735,21 @@ static int apple_dart_finalize_domain(struct apple_dart_domain *dart_domain,
600735 .iommu_dev = dart -> dev ,
601736 };
602737
738+ if (dart -> locked ) {
739+ unsigned long * sidmap ;
740+ int sid ;
741+ u32 ttbr ;
742+
743+ /* Locked DARTs can only have a single stream bound */
744+ sidmap = cfg -> stream_maps [0 ].sidmap ;
745+ sid = find_first_bit (sidmap , dart -> num_streams );
746+
747+ WARN_ON ((sid < 0 ) || bitmap_weight (sidmap , dart -> num_streams ) > 1 );
748+ ttbr = readl (dart -> regs + DART_TTBR (dart , sid , 0 ));
749+
750+ WARN_ON (!(ttbr & dart -> hw -> ttbr_valid ));
751+ }
752+
603753 dart_domain -> pgtbl_ops = alloc_io_pgtable_ops (dart -> hw -> fmt , & pgtbl_cfg ,
604754 & dart_domain -> domain );
605755 if (!dart_domain -> pgtbl_ops ) {
@@ -615,6 +765,7 @@ static int apple_dart_finalize_domain(struct apple_dart_domain *dart_domain,
615765
616766 dart_domain -> finalized = true;
617767
768+ ret = apple_dart_setup_resv_locked (& dart_domain -> domain , dev , dart -> pgsize );
618769done :
619770 mutex_unlock (& dart_domain -> init_lock );
620771 return ret ;
@@ -663,7 +814,7 @@ static int apple_dart_attach_dev_paging(struct iommu_domain *domain,
663814 struct apple_dart_master_cfg * cfg = dev_iommu_priv_get (dev );
664815 struct apple_dart_domain * dart_domain = to_dart_domain (domain );
665816
666- ret = apple_dart_finalize_domain (dart_domain , cfg );
817+ ret = apple_dart_finalize_domain (dart_domain , dev , cfg );
667818 if (ret )
668819 return ret ;
669820
@@ -743,8 +894,16 @@ static struct iommu_device *apple_dart_probe_device(struct device *dev)
743894
744895static void apple_dart_release_device (struct device * dev )
745896{
897+ int i , j ;
898+ struct apple_dart_stream_map * stream_map ;
746899 struct apple_dart_master_cfg * cfg = dev_iommu_priv_get (dev );
747900
901+ for_each_stream_map (j , cfg , stream_map ) {
902+ if (stream_map -> dart -> locked )
903+ for (i = 0 ; i < stream_map -> dart -> hw -> ttbr_count ; ++ i )
904+ apple_dart_hw_clear_locked_ttbr (stream_map , i );
905+ }
906+
748907 kfree (cfg );
749908}
750909
@@ -762,7 +921,7 @@ static struct iommu_domain *apple_dart_domain_alloc_paging(struct device *dev)
762921 struct apple_dart_master_cfg * cfg = dev_iommu_priv_get (dev );
763922 int ret ;
764923
765- ret = apple_dart_finalize_domain (dart_domain , cfg );
924+ ret = apple_dart_finalize_domain (dart_domain , dev , cfg );
766925 if (ret ) {
767926 kfree (dart_domain );
768927 return ERR_PTR (ret );
0 commit comments