[PATCH v2 08/14] iommu/riscv: Prepare info->domain for concurrent RCU read access

From: Andrew Jones

Date: Fri Jul 24 2026 - 11:33:48 EST


An upcoming compose_msi_msg() implementation reads info->domain from
potentially atomic context, concurrent with domain switches. Apply
RCU in preparation.

Signed-off-by: Andrew Jones <andrew.jones@xxxxxxxxxxxxxxxx>
---
drivers/iommu/riscv/iommu.c | 14 ++++++++------
drivers/iommu/riscv/iommu.h | 3 ++-
2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c
index bfe606a0cb9a..27dfd60834ac 100644
--- a/drivers/iommu/riscv/iommu.c
+++ b/drivers/iommu/riscv/iommu.c
@@ -1241,6 +1241,8 @@ static void riscv_iommu_free_paging_domain(struct iommu_domain *iommu_domain)

WARN_ON(!list_empty(&domain->bonds));

+ synchronize_rcu();
+
riscv_iommu_ir_free_paging_domain(iommu_domain);

if ((int)domain->pscid > 0)
@@ -1296,8 +1298,8 @@ static int riscv_iommu_attach_paging_domain(struct iommu_domain *iommu_domain,
}

riscv_iommu_iodir_update(iommu, dev, fsc, ta);
- riscv_iommu_bond_unlink(info->domain, dev);
- info->domain = domain;
+ riscv_iommu_bond_unlink(rcu_access_pointer(info->domain), dev);
+ rcu_assign_pointer(info->domain, domain);

return 0;
}
@@ -1373,8 +1375,8 @@ static int riscv_iommu_attach_blocking_domain(struct iommu_domain *iommu_domain,

/* Make device context invalid, translation requests will fault w/ #258 */
riscv_iommu_iodir_update(iommu, dev, RISCV_IOMMU_FSC_BARE, 0);
- riscv_iommu_bond_unlink(info->domain, dev);
- info->domain = NULL;
+ riscv_iommu_bond_unlink(rcu_access_pointer(info->domain), dev);
+ rcu_assign_pointer(info->domain, NULL);

return 0;
}
@@ -1394,8 +1396,8 @@ static int riscv_iommu_attach_identity_domain(struct iommu_domain *iommu_domain,
struct riscv_iommu_info *info = dev_iommu_priv_get(dev);

riscv_iommu_iodir_update(iommu, dev, RISCV_IOMMU_FSC_BARE, RISCV_IOMMU_PC_TA_V);
- riscv_iommu_bond_unlink(info->domain, dev);
- info->domain = NULL;
+ riscv_iommu_bond_unlink(rcu_access_pointer(info->domain), dev);
+ rcu_assign_pointer(info->domain, NULL);

return 0;
}
diff --git a/drivers/iommu/riscv/iommu.h b/drivers/iommu/riscv/iommu.h
index 5d83537911b6..ded18aec8010 100644
--- a/drivers/iommu/riscv/iommu.h
+++ b/drivers/iommu/riscv/iommu.h
@@ -15,6 +15,7 @@
#include <linux/types.h>
#include <linux/iopoll.h>
#include <linux/irqdomain.h>
+#include <linux/rcupdate.h>
#include <linux/generic_pt/iommu.h>

#include "iommu-bits.h"
@@ -33,7 +34,7 @@ PT_IOMMU_CHECK_DOMAIN(struct riscv_iommu_domain, riscvpt.iommu, domain);

/* Private IOMMU data for managed devices, dev_iommu_priv_* */
struct riscv_iommu_info {
- struct riscv_iommu_domain *domain;
+ struct riscv_iommu_domain __rcu *domain;
struct irq_domain *irqdomain;
};

--
2.43.0