@@ -150,13 +150,28 @@ to_mock_nested(struct iommu_domain *domain)
150150struct mock_viommu {
151151 struct iommufd_viommu core ;
152152 struct mock_iommu_domain * s2_parent ;
153+ struct mock_hw_queue * hw_queue [IOMMU_TEST_HW_QUEUE_MAX ];
154+ struct mutex queue_mutex ;
153155};
154156
155157static inline struct mock_viommu * to_mock_viommu (struct iommufd_viommu * viommu )
156158{
157159 return container_of (viommu , struct mock_viommu , core );
158160}
159161
162+ struct mock_hw_queue {
163+ struct iommufd_hw_queue core ;
164+ struct mock_viommu * mock_viommu ;
165+ struct mock_hw_queue * prev ;
166+ u16 index ;
167+ };
168+
169+ static inline struct mock_hw_queue *
170+ to_mock_hw_queue (struct iommufd_hw_queue * hw_queue )
171+ {
172+ return container_of (hw_queue , struct mock_hw_queue , core );
173+ }
174+
160175enum selftest_obj_type {
161176 TYPE_IDEV ,
162177};
@@ -670,9 +685,11 @@ static void mock_viommu_destroy(struct iommufd_viommu *viommu)
670685{
671686 struct mock_iommu_device * mock_iommu = container_of (
672687 viommu -> iommu_dev , struct mock_iommu_device , iommu_dev );
688+ struct mock_viommu * mock_viommu = to_mock_viommu (viommu );
673689
674690 if (refcount_dec_and_test (& mock_iommu -> users ))
675691 complete (& mock_iommu -> complete );
692+ mutex_destroy (& mock_viommu -> queue_mutex );
676693
677694 /* iommufd core frees mock_viommu and viommu */
678695}
@@ -764,10 +781,86 @@ static int mock_viommu_cache_invalidate(struct iommufd_viommu *viommu,
764781 return rc ;
765782}
766783
784+ static size_t mock_viommu_get_hw_queue_size (struct iommufd_viommu * viommu ,
785+ enum iommu_hw_queue_type queue_type )
786+ {
787+ if (queue_type != IOMMU_HW_QUEUE_TYPE_SELFTEST )
788+ return 0 ;
789+ return HW_QUEUE_STRUCT_SIZE (struct mock_hw_queue , core );
790+ }
791+
792+ static void mock_hw_queue_destroy (struct iommufd_hw_queue * hw_queue )
793+ {
794+ struct mock_hw_queue * mock_hw_queue = to_mock_hw_queue (hw_queue );
795+ struct mock_viommu * mock_viommu = mock_hw_queue -> mock_viommu ;
796+
797+ mutex_lock (& mock_viommu -> queue_mutex );
798+ mock_viommu -> hw_queue [mock_hw_queue -> index ] = NULL ;
799+ if (mock_hw_queue -> prev )
800+ iommufd_hw_queue_undepend (mock_hw_queue , mock_hw_queue -> prev ,
801+ core );
802+ mutex_unlock (& mock_viommu -> queue_mutex );
803+ }
804+
805+ /* Test iommufd_hw_queue_depend/undepend() */
806+ static int mock_hw_queue_init_phys (struct iommufd_hw_queue * hw_queue , u32 index ,
807+ phys_addr_t base_addr_pa )
808+ {
809+ struct mock_viommu * mock_viommu = to_mock_viommu (hw_queue -> viommu );
810+ struct mock_hw_queue * mock_hw_queue = to_mock_hw_queue (hw_queue );
811+ struct mock_hw_queue * prev = NULL ;
812+ int rc = 0 ;
813+
814+ if (index >= IOMMU_TEST_HW_QUEUE_MAX )
815+ return - EINVAL ;
816+
817+ mutex_lock (& mock_viommu -> queue_mutex );
818+
819+ if (mock_viommu -> hw_queue [index ]) {
820+ rc = - EEXIST ;
821+ goto unlock ;
822+ }
823+
824+ if (index ) {
825+ prev = mock_viommu -> hw_queue [index - 1 ];
826+ if (!prev ) {
827+ rc = - EIO ;
828+ goto unlock ;
829+ }
830+ }
831+
832+ /*
833+ * Test to catch a kernel bug if the core converted the physical address
834+ * incorrectly. Let mock_domain_iova_to_phys() WARN_ON if it fails.
835+ */
836+ if (base_addr_pa != iommu_iova_to_phys (& mock_viommu -> s2_parent -> domain ,
837+ hw_queue -> base_addr )) {
838+ rc = - EFAULT ;
839+ goto unlock ;
840+ }
841+
842+ if (prev ) {
843+ rc = iommufd_hw_queue_depend (mock_hw_queue , prev , core );
844+ if (rc )
845+ goto unlock ;
846+ }
847+
848+ mock_hw_queue -> prev = prev ;
849+ mock_hw_queue -> mock_viommu = mock_viommu ;
850+ mock_viommu -> hw_queue [index ] = mock_hw_queue ;
851+
852+ hw_queue -> destroy = & mock_hw_queue_destroy ;
853+ unlock :
854+ mutex_unlock (& mock_viommu -> queue_mutex );
855+ return rc ;
856+ }
857+
767858static struct iommufd_viommu_ops mock_viommu_ops = {
768859 .destroy = mock_viommu_destroy ,
769860 .alloc_domain_nested = mock_viommu_alloc_domain_nested ,
770861 .cache_invalidate = mock_viommu_cache_invalidate ,
862+ .get_hw_queue_size = mock_viommu_get_hw_queue_size ,
863+ .hw_queue_init_phys = mock_hw_queue_init_phys ,
771864};
772865
773866static size_t mock_get_viommu_size (struct device * dev ,
@@ -784,6 +877,7 @@ static int mock_viommu_init(struct iommufd_viommu *viommu,
784877{
785878 struct mock_iommu_device * mock_iommu = container_of (
786879 viommu -> iommu_dev , struct mock_iommu_device , iommu_dev );
880+ struct mock_viommu * mock_viommu = to_mock_viommu (viommu );
787881 struct iommu_viommu_selftest data ;
788882 int rc ;
789883
@@ -801,6 +895,9 @@ static int mock_viommu_init(struct iommufd_viommu *viommu,
801895 }
802896
803897 refcount_inc (& mock_iommu -> users );
898+ mutex_init (& mock_viommu -> queue_mutex );
899+ mock_viommu -> s2_parent = to_mock_domain (parent_domain );
900+
804901 viommu -> ops = & mock_viommu_ops ;
805902 return 0 ;
806903}
0 commit comments