With the right (or wrong;-) definition of v1 SMMU node in DTB it is
possible to trigger a division by zero in arm_smmu_init_domain_context
(if number of context irqs is 0):

       if (smmu->version == 1) {
               root_cfg->irptndx = atomic_inc_return(&smmu->irptndx);
 →             root_cfg->irptndx %= smmu->num_context_irqs;
       } else {

Avoid this by checking for num_context_irqs > 0 before trying to
assign interrupts to contexts.

Signed-off-by: Andreas Herrmann <[email protected]>
---
 drivers/iommu/arm-smmu.c |   31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index f5a856e..0dfd255 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -828,21 +828,24 @@ static int arm_smmu_init_domain_context(struct 
iommu_domain *domain,
                return ret;
 
        root_cfg->cbndx = ret;
-       if (smmu->version == 1) {
-               root_cfg->irptndx = atomic_inc_return(&smmu->irptndx);
-               root_cfg->irptndx %= smmu->num_context_irqs;
-       } else {
-               root_cfg->irptndx = root_cfg->cbndx;
-       }
 
-       irq = smmu->irqs[smmu->num_global_irqs + root_cfg->irptndx];
-       ret = request_irq(irq, arm_smmu_context_fault, IRQF_SHARED,
-                         "arm-smmu-context-fault", domain);
-       if (IS_ERR_VALUE(ret)) {
-               dev_err(smmu->dev, "failed to request context IRQ %d (%u)\n",
-                       root_cfg->irptndx, irq);
-               root_cfg->irptndx = -1;
-               goto out_free_context;
+       if (smmu->num_context_irqs) {
+               if (smmu->version == 1) {
+                       root_cfg->irptndx = atomic_inc_return(&smmu->irptndx);
+                       root_cfg->irptndx %= smmu->num_context_irqs;
+               } else {
+                       root_cfg->irptndx = root_cfg->cbndx;
+               }
+
+               irq = smmu->irqs[smmu->num_global_irqs + root_cfg->irptndx];
+               ret = request_irq(irq, arm_smmu_context_fault, IRQF_SHARED,
+                               "arm-smmu-context-fault", domain);
+               if (IS_ERR_VALUE(ret)) {
+                       dev_err(smmu->dev, "failed to request context IRQ %d 
(%u)\n",
+                               root_cfg->irptndx, irq);
+                       root_cfg->irptndx = -1;
+                       goto out_free_context;
+               }
        }
 
        root_cfg->smmu = smmu;
-- 
1.7.9.5

_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to