[PATCH v2 08/14] iommu/riscv: Prepare info->domain for concurrent RCU read access
Andrew Jones <[email protected]> Fri, 24 Jul 2026 17:12:12 +0200
| Newsgroups | dev.linux.lists.iommu,org.infradead.lists.linux-riscv,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
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 <[email protected]> --- 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