* [PATCH v5 0/9] Refactor the SMMU's CD table ownership
@ 2023-08-08 17:11 Michael Shavit
2023-08-08 17:11 ` [PATCH v5 1/9] iommu/arm-smmu-v3: Move ctx_desc out of s1_cfg Michael Shavit
` (8 more replies)
0 siblings, 9 replies; 45+ messages in thread
From: Michael Shavit @ 2023-08-08 17:11 UTC (permalink / raw)
To: iommu, linux-arm-kernel, linux-kernel
Cc: will, robin.murphy, nicolinc, jgg, jean-philippe, Michael Shavit
Hi all,
This series refactors stage 1 domains so that they describe a single CD
entry. These entries are now inserted into a CD table that is owned by
the arm_smmu_master instead of the domain.
This is conceptually cleaner and unblocks other features, such as
attaching domains with PASID (for unmanaged/dma domains).
This patch series was originally part of a larger patch series that
implemented the set_dev_pasid callback for non-SVA domains but is now
split into a distinct series.
This patch series is also available on gerrit with Jean's SMMU test
engine patches cherry-picked on top for testing:
https://linux-review.googlesource.com/c/linux/kernel/git/torvalds/linux/+/24742/8
Thanks,
Michael Shavit
Changes in v5:
- Clear the 0th CD entry when the domain is detached. Not clearing it
caused a bug in arm_smmu_write_ctx_desc which doesn't expect the entry
to already be set.
- Fix an issue where cd_table.installed wasn't correctly updated.
- Added commit to clean-up now unused master parameter in
arm_smmu_domain_finalise
- Link to v4: https://lore.kernel.org/all/20230802163328.2623773-1-mshavit@google.com/
Changes in v4:
- Added comment about the cd_table's dependency on the iommu core's
group mutex.
- Narrowed the range of code for which the domain's init_mutex is held
on attach since it now only protects the arm_smmu_domain_finalise
call.
- Link to v3: https://lore.kernel.org/all/20230801183845.4026101-1-mshavit@google.com/
Changes in v3:
- Add a helper to write a CD to all masters that a domain is attached
to.
- Fixed an issue where an arm_smmu_write_ctx_desc error return wasn't
correctly handled by its caller.
- Flip the cd_table.installed bit back off when table is detached
- re-order the commit later in the series since flipping the installed
bit to off isn't obvious when the cd_table is still shared by multiple
masters.
- Link to v2: https://lore.kernel.org/all/20230731104833.800114-1-mshavit@google.com/
Changes in v2:
- Allocate CD table when it's first needed instead of on probe.
- Minor changes
- Added commit to rename remaining usages of cdcfg to cd_table
- Link to v1: https://lore.kernel.org/all/20230727182647.4106140-1-mshavit@google.com/#r
Changes in v1:
- Replace s1_cfg with arm_smmu_ctx_desc_cfg representing the CD table
- Assume that the CD table is owned by the SMMU master for most
operations. This is forward-compatible with the nested patch series as
these operations wouldn't be called when the installed CD table comes
from nested domains.
- Split off as a distinct patch series from https://lore.kernel.org/all/20230621063825.268890-1-mshavit@google.com/
Michael Shavit (9):
iommu/arm-smmu-v3: Move ctx_desc out of s1_cfg
iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg
iommu/arm-smmu-v3: Encapsulate ctx_desc_cfg init in alloc_cd_tables
iommu/arm-smmu-v3: move stall_enabled to the cd table
iommu/arm-smmu-v3: Refactor write_ctx_desc
iommu/arm-smmu-v3: Move CD table to arm_smmu_master
iommu/arm-smmu-v3: Cleanup arm_smmu_domain_finalise
iommu/arm-smmu-v3: Skip cd sync if CD table isn't active
iommu/arm-smmu-v3: Rename cdcfg to cd_table
.../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 33 ++-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 255 +++++++++---------
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 22 +-
3 files changed, 161 insertions(+), 149 deletions(-)
base-commit: 5d0c230f1de8c7515b6567d9afba1f196fb4e2f4
--
2.41.0.640.ga95def55d0-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH v5 1/9] iommu/arm-smmu-v3: Move ctx_desc out of s1_cfg
2023-08-08 17:11 [PATCH v5 0/9] Refactor the SMMU's CD table ownership Michael Shavit
@ 2023-08-08 17:11 ` Michael Shavit
2023-08-08 17:11 ` [PATCH v5 2/9] iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg Michael Shavit
` (7 subsequent siblings)
8 siblings, 0 replies; 45+ messages in thread
From: Michael Shavit @ 2023-08-08 17:11 UTC (permalink / raw)
To: iommu, linux-arm-kernel, linux-kernel
Cc: will, robin.murphy, nicolinc, jgg, jean-philippe, Michael Shavit
s1_cfg describes the CD table that is inserted into an SMMU's STEs. It's
weird for s1_cfg to also own ctx_desc which describes a CD that is
inserted into that table. It is more appropriate for arm_smmu_domain to
own ctx_desc.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Michael Shavit <mshavit@google.com>
---
(no changes since v2)
Changes in v2:
- Undo over-reaching column alignment change
.../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 2 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 23 ++++++++++---------
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 6 +++--
3 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index a5a63b1c947eb..968559d625c40 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -62,7 +62,7 @@ arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
return cd;
}
- smmu_domain = container_of(cd, struct arm_smmu_domain, s1_cfg.cd);
+ smmu_domain = container_of(cd, struct arm_smmu_domain, cd);
smmu = smmu_domain->smmu;
ret = xa_alloc(&arm_smmu_asid_xa, &new_asid, cd,
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 9b0dc35056019..bb277ff86f65f 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1869,7 +1869,7 @@ static void arm_smmu_tlb_inv_context(void *cookie)
* careful, 007.
*/
if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
- arm_smmu_tlb_inv_asid(smmu, smmu_domain->s1_cfg.cd.asid);
+ arm_smmu_tlb_inv_asid(smmu, smmu_domain->cd.asid);
} else {
cmd.opcode = CMDQ_OP_TLBI_S12_VMALL;
cmd.tlbi.vmid = smmu_domain->s2_cfg.vmid;
@@ -1957,7 +1957,7 @@ static void arm_smmu_tlb_inv_range_domain(unsigned long iova, size_t size,
if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
cmd.opcode = smmu_domain->smmu->features & ARM_SMMU_FEAT_E2H ?
CMDQ_OP_TLBI_EL2_VA : CMDQ_OP_TLBI_NH_VA;
- cmd.tlbi.asid = smmu_domain->s1_cfg.cd.asid;
+ cmd.tlbi.asid = smmu_domain->cd.asid;
} else {
cmd.opcode = CMDQ_OP_TLBI_S2_IPA;
cmd.tlbi.vmid = smmu_domain->s2_cfg.vmid;
@@ -2088,7 +2088,7 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
mutex_lock(&arm_smmu_asid_lock);
if (cfg->cdcfg.cdtab)
arm_smmu_free_cd_tables(smmu_domain);
- arm_smmu_free_asid(&cfg->cd);
+ arm_smmu_free_asid(&smmu_domain->cd);
mutex_unlock(&arm_smmu_asid_lock);
} else {
struct arm_smmu_s2_cfg *cfg = &smmu_domain->s2_cfg;
@@ -2107,13 +2107,14 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
u32 asid;
struct arm_smmu_device *smmu = smmu_domain->smmu;
struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;
+ struct arm_smmu_ctx_desc *cd = &smmu_domain->cd;
typeof(&pgtbl_cfg->arm_lpae_s1_cfg.tcr) tcr = &pgtbl_cfg->arm_lpae_s1_cfg.tcr;
- refcount_set(&cfg->cd.refs, 1);
+ refcount_set(&cd->refs, 1);
/* Prevent SVA from modifying the ASID until it is written to the CD */
mutex_lock(&arm_smmu_asid_lock);
- ret = xa_alloc(&arm_smmu_asid_xa, &asid, &cfg->cd,
+ ret = xa_alloc(&arm_smmu_asid_xa, &asid, cd,
XA_LIMIT(1, (1 << smmu->asid_bits) - 1), GFP_KERNEL);
if (ret)
goto out_unlock;
@@ -2126,23 +2127,23 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
if (ret)
goto out_free_asid;
- cfg->cd.asid = (u16)asid;
- cfg->cd.ttbr = pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
- cfg->cd.tcr = FIELD_PREP(CTXDESC_CD_0_TCR_T0SZ, tcr->tsz) |
+ cd->asid = (u16)asid;
+ cd->ttbr = pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
+ cd->tcr = FIELD_PREP(CTXDESC_CD_0_TCR_T0SZ, tcr->tsz) |
FIELD_PREP(CTXDESC_CD_0_TCR_TG0, tcr->tg) |
FIELD_PREP(CTXDESC_CD_0_TCR_IRGN0, tcr->irgn) |
FIELD_PREP(CTXDESC_CD_0_TCR_ORGN0, tcr->orgn) |
FIELD_PREP(CTXDESC_CD_0_TCR_SH0, tcr->sh) |
FIELD_PREP(CTXDESC_CD_0_TCR_IPS, tcr->ips) |
CTXDESC_CD_0_TCR_EPD1 | CTXDESC_CD_0_AA64;
- cfg->cd.mair = pgtbl_cfg->arm_lpae_s1_cfg.mair;
+ cd->mair = pgtbl_cfg->arm_lpae_s1_cfg.mair;
/*
* Note that this will end up calling arm_smmu_sync_cd() before
* the master has been added to the devices list for this domain.
* This isn't an issue because the STE hasn't been installed yet.
*/
- ret = arm_smmu_write_ctx_desc(smmu_domain, 0, &cfg->cd);
+ ret = arm_smmu_write_ctx_desc(smmu_domain, 0, cd);
if (ret)
goto out_free_cd_tables;
@@ -2152,7 +2153,7 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
out_free_cd_tables:
arm_smmu_free_cd_tables(smmu_domain);
out_free_asid:
- arm_smmu_free_asid(&cfg->cd);
+ arm_smmu_free_asid(cd);
out_unlock:
mutex_unlock(&arm_smmu_asid_lock);
return ret;
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index dcab85698a4e2..f841383a55a35 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -599,7 +599,6 @@ struct arm_smmu_ctx_desc_cfg {
struct arm_smmu_s1_cfg {
struct arm_smmu_ctx_desc_cfg cdcfg;
- struct arm_smmu_ctx_desc cd;
u8 s1fmt;
u8 s1cdmax;
};
@@ -724,7 +723,10 @@ struct arm_smmu_domain {
enum arm_smmu_domain_stage stage;
union {
- struct arm_smmu_s1_cfg s1_cfg;
+ struct {
+ struct arm_smmu_ctx_desc cd;
+ struct arm_smmu_s1_cfg s1_cfg;
+ };
struct arm_smmu_s2_cfg s2_cfg;
};
--
2.41.0.640.ga95def55d0-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v5 2/9] iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg
2023-08-08 17:11 [PATCH v5 0/9] Refactor the SMMU's CD table ownership Michael Shavit
2023-08-08 17:11 ` [PATCH v5 1/9] iommu/arm-smmu-v3: Move ctx_desc out of s1_cfg Michael Shavit
@ 2023-08-08 17:11 ` Michael Shavit
2023-08-09 13:49 ` Will Deacon
2023-08-08 17:11 ` [PATCH v5 3/9] iommu/arm-smmu-v3: Encapsulate ctx_desc_cfg init in alloc_cd_tables Michael Shavit
` (6 subsequent siblings)
8 siblings, 1 reply; 45+ messages in thread
From: Michael Shavit @ 2023-08-08 17:11 UTC (permalink / raw)
To: iommu, linux-arm-kernel, linux-kernel
Cc: will, robin.murphy, nicolinc, jgg, jean-philippe, Michael Shavit
Remove struct arm_smmu_s1_cfg. This is really just a CD table with a
bit of extra information. Enhance the existing CD table structure,
struct arm_smmu_ctx_desc_cfg, with max_cds_bits and replace all usages
of arm_smmu_s1_cfg with arm_smmu_ctx_desc_cfg.
Compute the other values that were stored in s1cfg directly from
existing arm_smmu_ctx_desc_cfg.
For clarity, use the name "cd_table" for the variables pointing to
arm_smmu_ctx_desc_cfg in the new code instead of cdcfg. A later patch
will make this fully consistent.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Michael Shavit <mshavit@google.com>
---
(no changes since v3)
Changes in v3:
- Updated commit messages again
- Replace more usages of cdcfg with cdtable (lines that were already
touched by this commit anyways).
Changes in v2:
- Updated commit message
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 45 +++++++++++----------
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 10 ++---
2 files changed, 26 insertions(+), 29 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index bb277ff86f65f..ded613aedbb04 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1033,9 +1033,9 @@ static __le64 *arm_smmu_get_cd_ptr(struct arm_smmu_domain *smmu_domain,
unsigned int idx;
struct arm_smmu_l1_ctx_desc *l1_desc;
struct arm_smmu_device *smmu = smmu_domain->smmu;
- struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->s1_cfg.cdcfg;
+ struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->cd_table;
- if (smmu_domain->s1_cfg.s1fmt == STRTAB_STE_0_S1FMT_LINEAR)
+ if (!cdcfg->l1_desc)
return cdcfg->cdtab + ssid * CTXDESC_CD_DWORDS;
idx = ssid >> CTXDESC_SPLIT;
@@ -1071,7 +1071,7 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
bool cd_live;
__le64 *cdptr;
- if (WARN_ON(ssid >= (1 << smmu_domain->s1_cfg.s1cdmax)))
+ if (WARN_ON(ssid >= (1 << smmu_domain->cd_table.max_cds_bits)))
return -E2BIG;
cdptr = arm_smmu_get_cd_ptr(smmu_domain, ssid);
@@ -1138,19 +1138,16 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain)
size_t l1size;
size_t max_contexts;
struct arm_smmu_device *smmu = smmu_domain->smmu;
- struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;
- struct arm_smmu_ctx_desc_cfg *cdcfg = &cfg->cdcfg;
+ struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->cd_table;
- max_contexts = 1 << cfg->s1cdmax;
+ max_contexts = 1 << cdcfg->max_cds_bits;
if (!(smmu->features & ARM_SMMU_FEAT_2_LVL_CDTAB) ||
max_contexts <= CTXDESC_L2_ENTRIES) {
- cfg->s1fmt = STRTAB_STE_0_S1FMT_LINEAR;
cdcfg->num_l1_ents = max_contexts;
l1size = max_contexts * (CTXDESC_CD_DWORDS << 3);
} else {
- cfg->s1fmt = STRTAB_STE_0_S1FMT_64K_L2;
cdcfg->num_l1_ents = DIV_ROUND_UP(max_contexts,
CTXDESC_L2_ENTRIES);
@@ -1186,7 +1183,7 @@ static void arm_smmu_free_cd_tables(struct arm_smmu_domain *smmu_domain)
int i;
size_t size, l1size;
struct arm_smmu_device *smmu = smmu_domain->smmu;
- struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->s1_cfg.cdcfg;
+ struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->cd_table;
if (cdcfg->l1_desc) {
size = CTXDESC_L2_ENTRIES * (CTXDESC_CD_DWORDS << 3);
@@ -1276,7 +1273,7 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
u64 val = le64_to_cpu(dst[0]);
bool ste_live = false;
struct arm_smmu_device *smmu = NULL;
- struct arm_smmu_s1_cfg *s1_cfg = NULL;
+ struct arm_smmu_ctx_desc_cfg *cd_table = NULL;
struct arm_smmu_s2_cfg *s2_cfg = NULL;
struct arm_smmu_domain *smmu_domain = NULL;
struct arm_smmu_cmdq_ent prefetch_cmd = {
@@ -1294,7 +1291,7 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
if (smmu_domain) {
switch (smmu_domain->stage) {
case ARM_SMMU_DOMAIN_S1:
- s1_cfg = &smmu_domain->s1_cfg;
+ cd_table = &smmu_domain->cd_table;
break;
case ARM_SMMU_DOMAIN_S2:
case ARM_SMMU_DOMAIN_NESTED:
@@ -1325,7 +1322,7 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
val = STRTAB_STE_0_V;
/* Bypass/fault */
- if (!smmu_domain || !(s1_cfg || s2_cfg)) {
+ if (!smmu_domain || !(cd_table || s2_cfg)) {
if (!smmu_domain && disable_bypass)
val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_ABORT);
else
@@ -1344,7 +1341,7 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
return;
}
- if (s1_cfg) {
+ if (cd_table) {
u64 strw = smmu->features & ARM_SMMU_FEAT_E2H ?
STRTAB_STE_1_STRW_EL2 : STRTAB_STE_1_STRW_NSEL1;
@@ -1360,10 +1357,14 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
!master->stall_enabled)
dst[1] |= cpu_to_le64(STRTAB_STE_1_S1STALLD);
- val |= (s1_cfg->cdcfg.cdtab_dma & STRTAB_STE_0_S1CTXPTR_MASK) |
- FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS) |
- FIELD_PREP(STRTAB_STE_0_S1CDMAX, s1_cfg->s1cdmax) |
- FIELD_PREP(STRTAB_STE_0_S1FMT, s1_cfg->s1fmt);
+ val |= (cd_table->cdtab_dma & STRTAB_STE_0_S1CTXPTR_MASK) |
+ FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS) |
+ FIELD_PREP(STRTAB_STE_0_S1CDMAX,
+ cd_table->max_cds_bits) |
+ FIELD_PREP(STRTAB_STE_0_S1FMT,
+ cd_table->l1_desc ?
+ STRTAB_STE_0_S1FMT_64K_L2 :
+ STRTAB_STE_0_S1FMT_LINEAR);
}
if (s2_cfg) {
@@ -2082,11 +2083,11 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
/* Free the CD and ASID, if we allocated them */
if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
- struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;
+ struct arm_smmu_ctx_desc_cfg *cd_table = &smmu_domain->cd_table;
/* Prevent SVA from touching the CD while we're freeing it */
mutex_lock(&arm_smmu_asid_lock);
- if (cfg->cdcfg.cdtab)
+ if (cd_table->cdtab)
arm_smmu_free_cd_tables(smmu_domain);
arm_smmu_free_asid(&smmu_domain->cd);
mutex_unlock(&arm_smmu_asid_lock);
@@ -2106,7 +2107,7 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
int ret;
u32 asid;
struct arm_smmu_device *smmu = smmu_domain->smmu;
- struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;
+ struct arm_smmu_ctx_desc_cfg *cd_table = &smmu_domain->cd_table;
struct arm_smmu_ctx_desc *cd = &smmu_domain->cd;
typeof(&pgtbl_cfg->arm_lpae_s1_cfg.tcr) tcr = &pgtbl_cfg->arm_lpae_s1_cfg.tcr;
@@ -2119,7 +2120,7 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
if (ret)
goto out_unlock;
- cfg->s1cdmax = master->ssid_bits;
+ cd_table->max_cds_bits = master->ssid_bits;
smmu_domain->stall_enabled = master->stall_enabled;
@@ -2457,7 +2458,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
ret = -EINVAL;
goto out_unlock;
} else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 &&
- master->ssid_bits != smmu_domain->s1_cfg.s1cdmax) {
+ master->ssid_bits != smmu_domain->cd_table.max_cds_bits) {
ret = -EINVAL;
goto out_unlock;
} else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 &&
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index f841383a55a35..35a93e8858872 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -595,12 +595,8 @@ struct arm_smmu_ctx_desc_cfg {
dma_addr_t cdtab_dma;
struct arm_smmu_l1_ctx_desc *l1_desc;
unsigned int num_l1_ents;
-};
-
-struct arm_smmu_s1_cfg {
- struct arm_smmu_ctx_desc_cfg cdcfg;
- u8 s1fmt;
- u8 s1cdmax;
+ /* log2 of the maximum number of CDs supported by this table */
+ u8 max_cds_bits;
};
struct arm_smmu_s2_cfg {
@@ -725,7 +721,7 @@ struct arm_smmu_domain {
union {
struct {
struct arm_smmu_ctx_desc cd;
- struct arm_smmu_s1_cfg s1_cfg;
+ struct arm_smmu_ctx_desc_cfg cd_table;
};
struct arm_smmu_s2_cfg s2_cfg;
};
--
2.41.0.640.ga95def55d0-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v5 3/9] iommu/arm-smmu-v3: Encapsulate ctx_desc_cfg init in alloc_cd_tables
2023-08-08 17:11 [PATCH v5 0/9] Refactor the SMMU's CD table ownership Michael Shavit
2023-08-08 17:11 ` [PATCH v5 1/9] iommu/arm-smmu-v3: Move ctx_desc out of s1_cfg Michael Shavit
2023-08-08 17:11 ` [PATCH v5 2/9] iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg Michael Shavit
@ 2023-08-08 17:11 ` Michael Shavit
2023-08-08 17:12 ` [PATCH v5 4/9] iommu/arm-smmu-v3: move stall_enabled to the cd table Michael Shavit
` (5 subsequent siblings)
8 siblings, 0 replies; 45+ messages in thread
From: Michael Shavit @ 2023-08-08 17:11 UTC (permalink / raw)
To: iommu, linux-arm-kernel, linux-kernel
Cc: will, robin.murphy, nicolinc, jgg, jean-philippe, Michael Shavit
This is slighlty cleaner: arm_smmu_ctx_desc_cfg is initialized in a
single function instead of having pieces set ahead-of time by its caller.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Michael Shavit <mshavit@google.com>
---
(no changes since v1)
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index ded613aedbb04..fe4b19c3b8dee 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1132,7 +1132,8 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
return 0;
}
-static int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain)
+static int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain,
+ struct arm_smmu_master *master)
{
int ret;
size_t l1size;
@@ -1140,6 +1141,7 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain)
struct arm_smmu_device *smmu = smmu_domain->smmu;
struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->cd_table;
+ cdcfg->max_cds_bits = master->ssid_bits;
max_contexts = 1 << cdcfg->max_cds_bits;
if (!(smmu->features & ARM_SMMU_FEAT_2_LVL_CDTAB) ||
@@ -2107,7 +2109,6 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
int ret;
u32 asid;
struct arm_smmu_device *smmu = smmu_domain->smmu;
- struct arm_smmu_ctx_desc_cfg *cd_table = &smmu_domain->cd_table;
struct arm_smmu_ctx_desc *cd = &smmu_domain->cd;
typeof(&pgtbl_cfg->arm_lpae_s1_cfg.tcr) tcr = &pgtbl_cfg->arm_lpae_s1_cfg.tcr;
@@ -2120,11 +2121,9 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
if (ret)
goto out_unlock;
- cd_table->max_cds_bits = master->ssid_bits;
-
smmu_domain->stall_enabled = master->stall_enabled;
- ret = arm_smmu_alloc_cd_tables(smmu_domain);
+ ret = arm_smmu_alloc_cd_tables(smmu_domain, master);
if (ret)
goto out_free_asid;
--
2.41.0.640.ga95def55d0-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v5 4/9] iommu/arm-smmu-v3: move stall_enabled to the cd table
2023-08-08 17:11 [PATCH v5 0/9] Refactor the SMMU's CD table ownership Michael Shavit
` (2 preceding siblings ...)
2023-08-08 17:11 ` [PATCH v5 3/9] iommu/arm-smmu-v3: Encapsulate ctx_desc_cfg init in alloc_cd_tables Michael Shavit
@ 2023-08-08 17:12 ` Michael Shavit
2023-08-08 17:12 ` [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc Michael Shavit
` (4 subsequent siblings)
8 siblings, 0 replies; 45+ messages in thread
From: Michael Shavit @ 2023-08-08 17:12 UTC (permalink / raw)
To: iommu, linux-arm-kernel, linux-kernel
Cc: will, robin.murphy, nicolinc, jgg, jean-philippe, Michael Shavit
A domain can be attached to multiple masters with different
master->stall_enabled values. The stall bit of a CD entry should follow
master->stall_enabled and has an inverse relationship with the
STE.S1STALLD bit.
The stall_enabled bit does not depend on any property of the domain, so
move it out of the arm_smmu_domain struct. Move it to the CD table
struct so that it can fully describe how CD entries should be written to
it.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Michael Shavit <mshavit@google.com>
---
Changes in v5:
- Reword commit
Changes in v2:
- Use a bitfield instead of a bool for stall_enabled
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 8 ++++----
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 3 ++-
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index fe4b19c3b8dee..c01023404c26c 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1114,7 +1114,7 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
FIELD_PREP(CTXDESC_CD_0_ASID, cd->asid) |
CTXDESC_CD_0_V;
- if (smmu_domain->stall_enabled)
+ if (smmu_domain->cd_table.stall_enabled)
val |= CTXDESC_CD_0_S;
}
@@ -1141,6 +1141,7 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain,
struct arm_smmu_device *smmu = smmu_domain->smmu;
struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->cd_table;
+ cdcfg->stall_enabled = master->stall_enabled;
cdcfg->max_cds_bits = master->ssid_bits;
max_contexts = 1 << cdcfg->max_cds_bits;
@@ -2121,8 +2122,6 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
if (ret)
goto out_unlock;
- smmu_domain->stall_enabled = master->stall_enabled;
-
ret = arm_smmu_alloc_cd_tables(smmu_domain, master);
if (ret)
goto out_free_asid;
@@ -2461,7 +2460,8 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
ret = -EINVAL;
goto out_unlock;
} else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 &&
- smmu_domain->stall_enabled != master->stall_enabled) {
+ smmu_domain->cd_table.stall_enabled !=
+ master->stall_enabled) {
ret = -EINVAL;
goto out_unlock;
}
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 35a93e8858872..05b1f0ee60808 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -597,6 +597,8 @@ struct arm_smmu_ctx_desc_cfg {
unsigned int num_l1_ents;
/* log2 of the maximum number of CDs supported by this table */
u8 max_cds_bits;
+ /* Whether CD entries in this table have the stall bit set. */
+ u8 stall_enabled:1;
};
struct arm_smmu_s2_cfg {
@@ -714,7 +716,6 @@ struct arm_smmu_domain {
struct mutex init_mutex; /* Protects smmu pointer */
struct io_pgtable_ops *pgtbl_ops;
- bool stall_enabled;
atomic_t nr_ats_masters;
enum arm_smmu_domain_stage stage;
--
2.41.0.640.ga95def55d0-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc
2023-08-08 17:11 [PATCH v5 0/9] Refactor the SMMU's CD table ownership Michael Shavit
` (3 preceding siblings ...)
2023-08-08 17:12 ` [PATCH v5 4/9] iommu/arm-smmu-v3: move stall_enabled to the cd table Michael Shavit
@ 2023-08-08 17:12 ` Michael Shavit
2023-08-09 13:50 ` Will Deacon
2023-08-08 17:12 ` [PATCH v5 6/9] iommu/arm-smmu-v3: Move CD table to arm_smmu_master Michael Shavit
` (3 subsequent siblings)
8 siblings, 1 reply; 45+ messages in thread
From: Michael Shavit @ 2023-08-08 17:12 UTC (permalink / raw)
To: iommu, linux-arm-kernel, linux-kernel
Cc: will, robin.murphy, nicolinc, jgg, jean-philippe, Michael Shavit
Update arm_smmu_write_ctx_desc and downstream functions to operate on
a master instead of an smmu domain. We expect arm_smmu_write_ctx_desc()
to only be called to write a CD entry into a CD table owned by the
master. Under the hood, arm_smmu_write_ctx_desc still fetches the CD
table from the domain that is attached to the master, but a subsequent
commit will move that table's ownership to the master.
Note that this change isn't a nop refactor since SVA will call
arm_smmu_write_ctx_desc in a loop for every master the domain is
attached to despite the fact that they all share the same CD table. This
loop may look weird but becomes necessary when the CD table becomes
per-master in a subsequent commit.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Michael Shavit <mshavit@google.com>
---
(no changes since v3)
Changes in v3:
- Add a helper to write a CD to all masters that a domain is attached
to.
- Fixed an issue where an arm_smmu_write_ctx_desc error return wasn't
correctly handled by its caller.
Changes in v2:
- minor style fixes
Changes in v1:
- arm_smmu_write_ctx_desc now get's the CD table to write to from the
master parameter instead of a distinct parameter. This works well
because the CD table being written to should always be owned by the
master by the end of this series. This version no longer allows master
to be NULL.
.../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 31 +++++++++--
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 51 +++++++------------
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 2 +-
3 files changed, 46 insertions(+), 38 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index 968559d625c40..e3992a0c16377 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -37,6 +37,24 @@ struct arm_smmu_bond {
static DEFINE_MUTEX(sva_lock);
+static int arm_smmu_write_ctx_desc_devices(struct arm_smmu_domain *smmu_domain,
+ int ssid,
+ struct arm_smmu_ctx_desc *cd)
+{
+ struct arm_smmu_master *master;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&smmu_domain->devices_lock, flags);
+ list_for_each_entry(master, &smmu_domain->devices, domain_head) {
+ ret = arm_smmu_write_ctx_desc(master, ssid, cd);
+ if (ret)
+ break;
+ }
+ spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
+ return ret;
+}
+
/*
* Check if the CPU ASID is available on the SMMU side. If a private context
* descriptor is using it, try to replace it.
@@ -80,7 +98,7 @@ arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
* be some overlap between use of both ASIDs, until we invalidate the
* TLB.
*/
- arm_smmu_write_ctx_desc(smmu_domain, 0, cd);
+ arm_smmu_write_ctx_desc_devices(smmu_domain, 0, cd);
/* Invalidate TLB entries previously associated with that context */
arm_smmu_tlb_inv_asid(smmu, asid);
@@ -222,7 +240,7 @@ static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
* DMA may still be running. Keep the cd valid to avoid C_BAD_CD events,
* but disable translation.
*/
- arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, &quiet_cd);
+ arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, &quiet_cd);
arm_smmu_tlb_inv_asid(smmu_domain->smmu, smmu_mn->cd->asid);
arm_smmu_atc_inv_domain(smmu_domain, mm->pasid, 0, 0);
@@ -279,9 +297,11 @@ arm_smmu_mmu_notifier_get(struct arm_smmu_domain *smmu_domain,
goto err_free_cd;
}
- ret = arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, cd);
- if (ret)
+ ret = arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, cd);
+ if (ret) {
+ arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, NULL);
goto err_put_notifier;
+ }
list_add(&smmu_mn->list, &smmu_domain->mmu_notifiers);
return smmu_mn;
@@ -304,7 +324,8 @@ static void arm_smmu_mmu_notifier_put(struct arm_smmu_mmu_notifier *smmu_mn)
return;
list_del(&smmu_mn->list);
- arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, NULL);
+
+ arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, NULL);
/*
* If we went through clear(), we've already invalidated, and no
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index c01023404c26c..34bd7815aeb8e 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -971,14 +971,12 @@ void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid)
arm_smmu_cmdq_issue_cmd_with_sync(smmu, &cmd);
}
-static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain,
+static void arm_smmu_sync_cd(struct arm_smmu_master *master,
int ssid, bool leaf)
{
size_t i;
- unsigned long flags;
- struct arm_smmu_master *master;
struct arm_smmu_cmdq_batch cmds;
- struct arm_smmu_device *smmu = smmu_domain->smmu;
+ struct arm_smmu_device *smmu = master->smmu;
struct arm_smmu_cmdq_ent cmd = {
.opcode = CMDQ_OP_CFGI_CD,
.cfgi = {
@@ -988,15 +986,10 @@ static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain,
};
cmds.num = 0;
-
- spin_lock_irqsave(&smmu_domain->devices_lock, flags);
- list_for_each_entry(master, &smmu_domain->devices, domain_head) {
- for (i = 0; i < master->num_streams; i++) {
- cmd.cfgi.sid = master->streams[i].id;
- arm_smmu_cmdq_batch_add(smmu, &cmds, &cmd);
- }
+ for (i = 0; i < master->num_streams; i++) {
+ cmd.cfgi.sid = master->streams[i].id;
+ arm_smmu_cmdq_batch_add(smmu, &cmds, &cmd);
}
- spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
arm_smmu_cmdq_batch_submit(smmu, &cmds);
}
@@ -1026,14 +1019,13 @@ static void arm_smmu_write_cd_l1_desc(__le64 *dst,
WRITE_ONCE(*dst, cpu_to_le64(val));
}
-static __le64 *arm_smmu_get_cd_ptr(struct arm_smmu_domain *smmu_domain,
- u32 ssid)
+static __le64 *arm_smmu_get_cd_ptr(struct arm_smmu_master *master, u32 ssid)
{
__le64 *l1ptr;
unsigned int idx;
struct arm_smmu_l1_ctx_desc *l1_desc;
- struct arm_smmu_device *smmu = smmu_domain->smmu;
- struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->cd_table;
+ struct arm_smmu_device *smmu = master->smmu;
+ struct arm_smmu_ctx_desc_cfg *cdcfg = &master->domain->cd_table;
if (!cdcfg->l1_desc)
return cdcfg->cdtab + ssid * CTXDESC_CD_DWORDS;
@@ -1047,13 +1039,13 @@ static __le64 *arm_smmu_get_cd_ptr(struct arm_smmu_domain *smmu_domain,
l1ptr = cdcfg->cdtab + idx * CTXDESC_L1_DESC_DWORDS;
arm_smmu_write_cd_l1_desc(l1ptr, l1_desc);
/* An invalid L1CD can be cached */
- arm_smmu_sync_cd(smmu_domain, ssid, false);
+ arm_smmu_sync_cd(master, ssid, false);
}
idx = ssid & (CTXDESC_L2_ENTRIES - 1);
return l1_desc->l2ptr + idx * CTXDESC_CD_DWORDS;
}
-int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
+int arm_smmu_write_ctx_desc(struct arm_smmu_master *master, int ssid,
struct arm_smmu_ctx_desc *cd)
{
/*
@@ -1070,11 +1062,12 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
u64 val;
bool cd_live;
__le64 *cdptr;
+ struct arm_smmu_ctx_desc_cfg *cd_table = &master->domain->cd_table;
- if (WARN_ON(ssid >= (1 << smmu_domain->cd_table.max_cds_bits)))
+ if (WARN_ON(ssid >= (1 << cd_table->max_cds_bits)))
return -E2BIG;
- cdptr = arm_smmu_get_cd_ptr(smmu_domain, ssid);
+ cdptr = arm_smmu_get_cd_ptr(master, ssid);
if (!cdptr)
return -ENOMEM;
@@ -1102,7 +1095,7 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
* order. Ensure that it observes valid values before reading
* V=1.
*/
- arm_smmu_sync_cd(smmu_domain, ssid, true);
+ arm_smmu_sync_cd(master, ssid, true);
val = cd->tcr |
#ifdef __BIG_ENDIAN
@@ -1114,7 +1107,7 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
FIELD_PREP(CTXDESC_CD_0_ASID, cd->asid) |
CTXDESC_CD_0_V;
- if (smmu_domain->cd_table.stall_enabled)
+ if (cd_table->stall_enabled)
val |= CTXDESC_CD_0_S;
}
@@ -1128,7 +1121,7 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
* without first making the structure invalid.
*/
WRITE_ONCE(cdptr[0], cpu_to_le64(val));
- arm_smmu_sync_cd(smmu_domain, ssid, true);
+ arm_smmu_sync_cd(master, ssid, true);
return 0;
}
@@ -1138,7 +1131,7 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain,
int ret;
size_t l1size;
size_t max_contexts;
- struct arm_smmu_device *smmu = smmu_domain->smmu;
+ struct arm_smmu_device *smmu = master->smmu;
struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->cd_table;
cdcfg->stall_enabled = master->stall_enabled;
@@ -2137,12 +2130,7 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
CTXDESC_CD_0_TCR_EPD1 | CTXDESC_CD_0_AA64;
cd->mair = pgtbl_cfg->arm_lpae_s1_cfg.mair;
- /*
- * Note that this will end up calling arm_smmu_sync_cd() before
- * the master has been added to the devices list for this domain.
- * This isn't an issue because the STE hasn't been installed yet.
- */
- ret = arm_smmu_write_ctx_desc(smmu_domain, 0, cd);
+ ret = arm_smmu_write_ctx_desc(master, 0, cd);
if (ret)
goto out_free_cd_tables;
@@ -2460,8 +2448,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
ret = -EINVAL;
goto out_unlock;
} else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 &&
- smmu_domain->cd_table.stall_enabled !=
- master->stall_enabled) {
+ smmu_domain->cd_table.stall_enabled != master->stall_enabled) {
ret = -EINVAL;
goto out_unlock;
}
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 05b1f0ee60808..6066a09c01996 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -744,7 +744,7 @@ extern struct xarray arm_smmu_asid_xa;
extern struct mutex arm_smmu_asid_lock;
extern struct arm_smmu_ctx_desc quiet_cd;
-int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
+int arm_smmu_write_ctx_desc(struct arm_smmu_master *smmu_master, int ssid,
struct arm_smmu_ctx_desc *cd);
void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid);
void arm_smmu_tlb_inv_range_asid(unsigned long iova, size_t size, int asid,
--
2.41.0.640.ga95def55d0-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v5 6/9] iommu/arm-smmu-v3: Move CD table to arm_smmu_master
2023-08-08 17:11 [PATCH v5 0/9] Refactor the SMMU's CD table ownership Michael Shavit
` (4 preceding siblings ...)
2023-08-08 17:12 ` [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc Michael Shavit
@ 2023-08-08 17:12 ` Michael Shavit
2023-08-09 13:50 ` Will Deacon
2023-08-15 12:10 ` Michael Shavit
2023-08-08 17:12 ` [PATCH v5 7/9] iommu/arm-smmu-v3: Cleanup arm_smmu_domain_finalise Michael Shavit
` (2 subsequent siblings)
8 siblings, 2 replies; 45+ messages in thread
From: Michael Shavit @ 2023-08-08 17:12 UTC (permalink / raw)
To: iommu, linux-arm-kernel, linux-kernel
Cc: will, robin.murphy, nicolinc, jgg, jean-philippe, Michael Shavit
With this change, each master will now own its own CD table instead of
sharing one with other masters attached to the same domain. Attaching a
stage 1 domain installs CD entries into the master's CD table. SVA
writes its CD entries into each master's CD table if the domain is
shared across masters.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Michael Shavit <mshavit@google.com>
---
Changes in v5:
- Clear the 0th CD entry when the domain is detached. Not clearing it
caused a bug in arm_smmu_write_ctx_desc which doesn't expect the entry
to already be set.
Changes in v4:
- Added comment about the cd_table's dependency on the iommu core's
group mutex.
- Narrowed the range of code for which the domain's init_mutex is held
on attach since it now only protects the arm_smmu_domain_finalise
call.
Changes in v2:
- Allocate CD table when it's first needed instead of on probe.
Changes in v1:
- The master's CD table allocation was previously split to a different
commit. This change now atomically allocates the new CD table, uses
it, and removes the old one.
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 92 ++++++++++-----------
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 7 +-
2 files changed, 49 insertions(+), 50 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 34bd7815aeb8e..3f32f9a191a5f 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1025,7 +1025,7 @@ static __le64 *arm_smmu_get_cd_ptr(struct arm_smmu_master *master, u32 ssid)
unsigned int idx;
struct arm_smmu_l1_ctx_desc *l1_desc;
struct arm_smmu_device *smmu = master->smmu;
- struct arm_smmu_ctx_desc_cfg *cdcfg = &master->domain->cd_table;
+ struct arm_smmu_ctx_desc_cfg *cdcfg = &master->cd_table;
if (!cdcfg->l1_desc)
return cdcfg->cdtab + ssid * CTXDESC_CD_DWORDS;
@@ -1062,7 +1062,7 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_master *master, int ssid,
u64 val;
bool cd_live;
__le64 *cdptr;
- struct arm_smmu_ctx_desc_cfg *cd_table = &master->domain->cd_table;
+ struct arm_smmu_ctx_desc_cfg *cd_table = &master->cd_table;
if (WARN_ON(ssid >= (1 << cd_table->max_cds_bits)))
return -E2BIG;
@@ -1125,14 +1125,13 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_master *master, int ssid,
return 0;
}
-static int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain,
- struct arm_smmu_master *master)
+static int arm_smmu_alloc_cd_tables(struct arm_smmu_master *master)
{
int ret;
size_t l1size;
size_t max_contexts;
struct arm_smmu_device *smmu = master->smmu;
- struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->cd_table;
+ struct arm_smmu_ctx_desc_cfg *cdcfg = &master->cd_table;
cdcfg->stall_enabled = master->stall_enabled;
cdcfg->max_cds_bits = master->ssid_bits;
@@ -1174,12 +1173,12 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain,
return ret;
}
-static void arm_smmu_free_cd_tables(struct arm_smmu_domain *smmu_domain)
+static void arm_smmu_free_cd_tables(struct arm_smmu_master *master)
{
int i;
size_t size, l1size;
- struct arm_smmu_device *smmu = smmu_domain->smmu;
- struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->cd_table;
+ struct arm_smmu_device *smmu = master->smmu;
+ struct arm_smmu_ctx_desc_cfg *cdcfg = &master->cd_table;
if (cdcfg->l1_desc) {
size = CTXDESC_L2_ENTRIES * (CTXDESC_CD_DWORDS << 3);
@@ -1287,7 +1286,7 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
if (smmu_domain) {
switch (smmu_domain->stage) {
case ARM_SMMU_DOMAIN_S1:
- cd_table = &smmu_domain->cd_table;
+ cd_table = &master->cd_table;
break;
case ARM_SMMU_DOMAIN_S2:
case ARM_SMMU_DOMAIN_NESTED:
@@ -2077,14 +2076,10 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
free_io_pgtable_ops(smmu_domain->pgtbl_ops);
- /* Free the CD and ASID, if we allocated them */
+ /* Free the ASID or VMID */
if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
- struct arm_smmu_ctx_desc_cfg *cd_table = &smmu_domain->cd_table;
-
/* Prevent SVA from touching the CD while we're freeing it */
mutex_lock(&arm_smmu_asid_lock);
- if (cd_table->cdtab)
- arm_smmu_free_cd_tables(smmu_domain);
arm_smmu_free_asid(&smmu_domain->cd);
mutex_unlock(&arm_smmu_asid_lock);
} else {
@@ -2096,7 +2091,7 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
kfree(smmu_domain);
}
-static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
+static int arm_smmu_domain_finalise_cd(struct arm_smmu_domain *smmu_domain,
struct arm_smmu_master *master,
struct io_pgtable_cfg *pgtbl_cfg)
{
@@ -2115,10 +2110,6 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
if (ret)
goto out_unlock;
- ret = arm_smmu_alloc_cd_tables(smmu_domain, master);
- if (ret)
- goto out_free_asid;
-
cd->asid = (u16)asid;
cd->ttbr = pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
cd->tcr = FIELD_PREP(CTXDESC_CD_0_TCR_T0SZ, tcr->tsz) |
@@ -2130,17 +2121,9 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
CTXDESC_CD_0_TCR_EPD1 | CTXDESC_CD_0_AA64;
cd->mair = pgtbl_cfg->arm_lpae_s1_cfg.mair;
- ret = arm_smmu_write_ctx_desc(master, 0, cd);
- if (ret)
- goto out_free_cd_tables;
-
mutex_unlock(&arm_smmu_asid_lock);
return 0;
-out_free_cd_tables:
- arm_smmu_free_cd_tables(smmu_domain);
-out_free_asid:
- arm_smmu_free_asid(cd);
out_unlock:
mutex_unlock(&arm_smmu_asid_lock);
return ret;
@@ -2203,7 +2186,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain,
ias = min_t(unsigned long, ias, VA_BITS);
oas = smmu->ias;
fmt = ARM_64_LPAE_S1;
- finalise_stage_fn = arm_smmu_domain_finalise_s1;
+ finalise_stage_fn = arm_smmu_domain_finalise_cd;
break;
case ARM_SMMU_DOMAIN_NESTED:
case ARM_SMMU_DOMAIN_S2:
@@ -2402,6 +2385,16 @@ static void arm_smmu_detach_dev(struct arm_smmu_master *master)
master->domain = NULL;
master->ats_enabled = false;
arm_smmu_install_ste_for_dev(master);
+ /*
+ * The table is uninstalled before clearing the CD to prevent an
+ * unnecessary sync in arm_smmu_write_ctx_desc. Although clearing the
+ * CD entry isn't strictly required to detach the domain since the
+ * table is uninstalled anyway, it's more proper and helps avoid
+ * confusion in the call to arm_smmu_write_ctx_desc on the next attach
+ * (which expects the entry to be empty).
+ */
+ if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 && master->cd_table.cdtab)
+ arm_smmu_write_ctx_desc(master, 0, NULL);
}
static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
@@ -2436,22 +2429,14 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
if (!smmu_domain->smmu) {
smmu_domain->smmu = smmu;
ret = arm_smmu_domain_finalise(domain, master);
- if (ret) {
+ if (ret)
smmu_domain->smmu = NULL;
- goto out_unlock;
- }
- } else if (smmu_domain->smmu != smmu) {
- ret = -EINVAL;
- goto out_unlock;
- } else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 &&
- master->ssid_bits != smmu_domain->cd_table.max_cds_bits) {
+ } else if (smmu_domain->smmu != smmu)
ret = -EINVAL;
- goto out_unlock;
- } else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 &&
- smmu_domain->cd_table.stall_enabled != master->stall_enabled) {
- ret = -EINVAL;
- goto out_unlock;
- }
+
+ mutex_unlock(&smmu_domain->init_mutex);
+ if (ret)
+ return ret;
master->domain = smmu_domain;
@@ -2465,6 +2450,22 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
if (smmu_domain->stage != ARM_SMMU_DOMAIN_BYPASS)
master->ats_enabled = arm_smmu_ats_supported(master);
+ if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
+ if (!master->cd_table.cdtab) {
+ ret = arm_smmu_alloc_cd_tables(master);
+ if (ret) {
+ master->domain = NULL;
+ return ret;
+ }
+ }
+
+ ret = arm_smmu_write_ctx_desc(master, 0, &smmu_domain->cd);
+ if (ret) {
+ master->domain = NULL;
+ return ret;
+ }
+ }
+
arm_smmu_install_ste_for_dev(master);
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
@@ -2472,10 +2473,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
arm_smmu_enable_ats(master);
-
-out_unlock:
- mutex_unlock(&smmu_domain->init_mutex);
- return ret;
+ return 0;
}
static int arm_smmu_map_pages(struct iommu_domain *domain, unsigned long iova,
@@ -2719,6 +2717,8 @@ static void arm_smmu_release_device(struct device *dev)
arm_smmu_detach_dev(master);
arm_smmu_disable_pasid(master);
arm_smmu_remove_master(master);
+ if (master->cd_table.cdtab_dma)
+ arm_smmu_free_cd_tables(master);
kfree(master);
}
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 6066a09c01996..1f3b370257779 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -694,6 +694,8 @@ struct arm_smmu_master {
struct arm_smmu_domain *domain;
struct list_head domain_head;
struct arm_smmu_stream *streams;
+ /* Locked by the iommu core using the group mutex */
+ struct arm_smmu_ctx_desc_cfg cd_table;
unsigned int num_streams;
bool ats_enabled;
bool stall_enabled;
@@ -720,11 +722,8 @@ struct arm_smmu_domain {
enum arm_smmu_domain_stage stage;
union {
- struct {
struct arm_smmu_ctx_desc cd;
- struct arm_smmu_ctx_desc_cfg cd_table;
- };
- struct arm_smmu_s2_cfg s2_cfg;
+ struct arm_smmu_s2_cfg s2_cfg;
};
struct iommu_domain domain;
--
2.41.0.640.ga95def55d0-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v5 7/9] iommu/arm-smmu-v3: Cleanup arm_smmu_domain_finalise
2023-08-08 17:11 [PATCH v5 0/9] Refactor the SMMU's CD table ownership Michael Shavit
` (5 preceding siblings ...)
2023-08-08 17:12 ` [PATCH v5 6/9] iommu/arm-smmu-v3: Move CD table to arm_smmu_master Michael Shavit
@ 2023-08-08 17:12 ` Michael Shavit
2023-08-08 17:12 ` [PATCH v5 8/9] iommu/arm-smmu-v3: Skip cd sync if CD table isn't active Michael Shavit
2023-08-08 17:12 ` [PATCH v5 9/9] iommu/arm-smmu-v3: Rename cdcfg to cd_table Michael Shavit
8 siblings, 0 replies; 45+ messages in thread
From: Michael Shavit @ 2023-08-08 17:12 UTC (permalink / raw)
To: iommu, linux-arm-kernel, linux-kernel
Cc: will, robin.murphy, nicolinc, jgg, jean-philippe, Michael Shavit
Remove unused master parameter now that the CD table is allocated
elsewhere.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Michael Shavit <mshavit@google.com>
---
Changes in v5:
- New commit
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 3f32f9a191a5f..f5ad386cc8760 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2092,7 +2092,6 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
}
static int arm_smmu_domain_finalise_cd(struct arm_smmu_domain *smmu_domain,
- struct arm_smmu_master *master,
struct io_pgtable_cfg *pgtbl_cfg)
{
int ret;
@@ -2130,7 +2129,6 @@ static int arm_smmu_domain_finalise_cd(struct arm_smmu_domain *smmu_domain,
}
static int arm_smmu_domain_finalise_s2(struct arm_smmu_domain *smmu_domain,
- struct arm_smmu_master *master,
struct io_pgtable_cfg *pgtbl_cfg)
{
int vmid;
@@ -2155,8 +2153,7 @@ static int arm_smmu_domain_finalise_s2(struct arm_smmu_domain *smmu_domain,
return 0;
}
-static int arm_smmu_domain_finalise(struct iommu_domain *domain,
- struct arm_smmu_master *master)
+static int arm_smmu_domain_finalise(struct iommu_domain *domain)
{
int ret;
unsigned long ias, oas;
@@ -2164,7 +2161,6 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain,
struct io_pgtable_cfg pgtbl_cfg;
struct io_pgtable_ops *pgtbl_ops;
int (*finalise_stage_fn)(struct arm_smmu_domain *,
- struct arm_smmu_master *,
struct io_pgtable_cfg *);
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct arm_smmu_device *smmu = smmu_domain->smmu;
@@ -2216,7 +2212,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain,
domain->geometry.aperture_end = (1UL << pgtbl_cfg.ias) - 1;
domain->geometry.force_aperture = true;
- ret = finalise_stage_fn(smmu_domain, master, &pgtbl_cfg);
+ ret = finalise_stage_fn(smmu_domain, &pgtbl_cfg);
if (ret < 0) {
free_io_pgtable_ops(pgtbl_ops);
return ret;
@@ -2428,7 +2424,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
if (!smmu_domain->smmu) {
smmu_domain->smmu = smmu;
- ret = arm_smmu_domain_finalise(domain, master);
+ ret = arm_smmu_domain_finalise(domain);
if (ret)
smmu_domain->smmu = NULL;
} else if (smmu_domain->smmu != smmu)
--
2.41.0.640.ga95def55d0-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v5 8/9] iommu/arm-smmu-v3: Skip cd sync if CD table isn't active
2023-08-08 17:11 [PATCH v5 0/9] Refactor the SMMU's CD table ownership Michael Shavit
` (6 preceding siblings ...)
2023-08-08 17:12 ` [PATCH v5 7/9] iommu/arm-smmu-v3: Cleanup arm_smmu_domain_finalise Michael Shavit
@ 2023-08-08 17:12 ` Michael Shavit
2023-08-09 13:50 ` Will Deacon
2023-08-08 17:12 ` [PATCH v5 9/9] iommu/arm-smmu-v3: Rename cdcfg to cd_table Michael Shavit
8 siblings, 1 reply; 45+ messages in thread
From: Michael Shavit @ 2023-08-08 17:12 UTC (permalink / raw)
To: iommu, linux-arm-kernel, linux-kernel
Cc: will, robin.murphy, nicolinc, jgg, jean-philippe, Michael Shavit
This commit explicitly keeps track of whether a CD table is installed in
an STE so that arm_smmu_sync_cd can skip the sync when unnecessary. This
was previously achieved through the domain->devices list, but we are
moving to a model where arm_smmu_sync_cd directly operates on a master
and the master's CD table instead of a domain.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Michael Shavit <mshavit@google.com>
---
Changes in v5:
- Fix an issue where cd_table.installed wasn't correctly updated.
Changes in v3:
- Flip the cd_table.installed bit back off when table is detached
- re-order the commit later in the series since flipping the installed
bit to off isn't obvious when the cd_table is still shared by multiple
masters.
Changes in v2:
- Store field as a bit instead of a bool. Fix comment about STE being
live before the sync in write_ctx_desc().
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 9 ++++++++-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 2 ++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index f5ad386cc8760..488d12dd2d4aa 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -985,6 +985,9 @@ static void arm_smmu_sync_cd(struct arm_smmu_master *master,
},
};
+ if (!master->cd_table.installed)
+ return;
+
cmds.num = 0;
for (i = 0; i < master->num_streams; i++) {
cmd.cfgi.sid = master->streams[i].id;
@@ -1091,7 +1094,7 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_master *master, int ssid,
cdptr[3] = cpu_to_le64(cd->mair);
/*
- * STE is live, and the SMMU might read dwords of this CD in any
+ * STE may be live, and the SMMU might read dwords of this CD in any
* order. Ensure that it observes valid values before reading
* V=1.
*/
@@ -1333,6 +1336,7 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
*/
if (smmu)
arm_smmu_sync_ste_for_sid(smmu, sid);
+ master->cd_table.installed = false;
return;
}
@@ -1360,6 +1364,9 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
cd_table->l1_desc ?
STRTAB_STE_0_S1FMT_64K_L2 :
STRTAB_STE_0_S1FMT_LINEAR);
+ cd_table->installed = true;
+ } else {
+ master->cd_table.installed = false;
}
if (s2_cfg) {
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 1f3b370257779..e76452e735a04 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -599,6 +599,8 @@ struct arm_smmu_ctx_desc_cfg {
u8 max_cds_bits;
/* Whether CD entries in this table have the stall bit set. */
u8 stall_enabled:1;
+ /* Whether this CD table is installed in any STE */
+ u8 installed:1;
};
struct arm_smmu_s2_cfg {
--
2.41.0.640.ga95def55d0-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH v5 9/9] iommu/arm-smmu-v3: Rename cdcfg to cd_table
2023-08-08 17:11 [PATCH v5 0/9] Refactor the SMMU's CD table ownership Michael Shavit
` (7 preceding siblings ...)
2023-08-08 17:12 ` [PATCH v5 8/9] iommu/arm-smmu-v3: Skip cd sync if CD table isn't active Michael Shavit
@ 2023-08-08 17:12 ` Michael Shavit
8 siblings, 0 replies; 45+ messages in thread
From: Michael Shavit @ 2023-08-08 17:12 UTC (permalink / raw)
To: iommu, linux-arm-kernel, linux-kernel
Cc: will, robin.murphy, nicolinc, jgg, jean-philippe, Michael Shavit
cdcfg is a confusing name, especially given other variables with the cfg
suffix in this driver. cd_table more clearly describes what is being
operated on.
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Michael Shavit <mshavit@google.com>
---
(no changes since v3)
Changes in v3:
- Commit message update
Changes in v2:
- New commit
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 66 ++++++++++-----------
1 file changed, 33 insertions(+), 33 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 488d12dd2d4aa..e29e548776c1d 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1028,18 +1028,18 @@ static __le64 *arm_smmu_get_cd_ptr(struct arm_smmu_master *master, u32 ssid)
unsigned int idx;
struct arm_smmu_l1_ctx_desc *l1_desc;
struct arm_smmu_device *smmu = master->smmu;
- struct arm_smmu_ctx_desc_cfg *cdcfg = &master->cd_table;
+ struct arm_smmu_ctx_desc_cfg *cd_table = &master->cd_table;
- if (!cdcfg->l1_desc)
- return cdcfg->cdtab + ssid * CTXDESC_CD_DWORDS;
+ if (!cd_table->l1_desc)
+ return cd_table->cdtab + ssid * CTXDESC_CD_DWORDS;
idx = ssid >> CTXDESC_SPLIT;
- l1_desc = &cdcfg->l1_desc[idx];
+ l1_desc = &cd_table->l1_desc[idx];
if (!l1_desc->l2ptr) {
if (arm_smmu_alloc_cd_leaf_table(smmu, l1_desc))
return NULL;
- l1ptr = cdcfg->cdtab + idx * CTXDESC_L1_DESC_DWORDS;
+ l1ptr = cd_table->cdtab + idx * CTXDESC_L1_DESC_DWORDS;
arm_smmu_write_cd_l1_desc(l1ptr, l1_desc);
/* An invalid L1CD can be cached */
arm_smmu_sync_cd(master, ssid, false);
@@ -1134,33 +1134,33 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_master *master)
size_t l1size;
size_t max_contexts;
struct arm_smmu_device *smmu = master->smmu;
- struct arm_smmu_ctx_desc_cfg *cdcfg = &master->cd_table;
+ struct arm_smmu_ctx_desc_cfg *cd_table = &master->cd_table;
- cdcfg->stall_enabled = master->stall_enabled;
- cdcfg->max_cds_bits = master->ssid_bits;
- max_contexts = 1 << cdcfg->max_cds_bits;
+ cd_table->stall_enabled = master->stall_enabled;
+ cd_table->max_cds_bits = master->ssid_bits;
+ max_contexts = 1 << cd_table->max_cds_bits;
if (!(smmu->features & ARM_SMMU_FEAT_2_LVL_CDTAB) ||
max_contexts <= CTXDESC_L2_ENTRIES) {
- cdcfg->num_l1_ents = max_contexts;
+ cd_table->num_l1_ents = max_contexts;
l1size = max_contexts * (CTXDESC_CD_DWORDS << 3);
} else {
- cdcfg->num_l1_ents = DIV_ROUND_UP(max_contexts,
+ cd_table->num_l1_ents = DIV_ROUND_UP(max_contexts,
CTXDESC_L2_ENTRIES);
- cdcfg->l1_desc = devm_kcalloc(smmu->dev, cdcfg->num_l1_ents,
- sizeof(*cdcfg->l1_desc),
+ cd_table->l1_desc = devm_kcalloc(smmu->dev, cd_table->num_l1_ents,
+ sizeof(*cd_table->l1_desc),
GFP_KERNEL);
- if (!cdcfg->l1_desc)
+ if (!cd_table->l1_desc)
return -ENOMEM;
- l1size = cdcfg->num_l1_ents * (CTXDESC_L1_DESC_DWORDS << 3);
+ l1size = cd_table->num_l1_ents * (CTXDESC_L1_DESC_DWORDS << 3);
}
- cdcfg->cdtab = dmam_alloc_coherent(smmu->dev, l1size, &cdcfg->cdtab_dma,
+ cd_table->cdtab = dmam_alloc_coherent(smmu->dev, l1size, &cd_table->cdtab_dma,
GFP_KERNEL);
- if (!cdcfg->cdtab) {
+ if (!cd_table->cdtab) {
dev_warn(smmu->dev, "failed to allocate context descriptor\n");
ret = -ENOMEM;
goto err_free_l1;
@@ -1169,9 +1169,9 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_master *master)
return 0;
err_free_l1:
- if (cdcfg->l1_desc) {
- devm_kfree(smmu->dev, cdcfg->l1_desc);
- cdcfg->l1_desc = NULL;
+ if (cd_table->l1_desc) {
+ devm_kfree(smmu->dev, cd_table->l1_desc);
+ cd_table->l1_desc = NULL;
}
return ret;
}
@@ -1181,30 +1181,30 @@ static void arm_smmu_free_cd_tables(struct arm_smmu_master *master)
int i;
size_t size, l1size;
struct arm_smmu_device *smmu = master->smmu;
- struct arm_smmu_ctx_desc_cfg *cdcfg = &master->cd_table;
+ struct arm_smmu_ctx_desc_cfg *cd_table = &master->cd_table;
- if (cdcfg->l1_desc) {
+ if (cd_table->l1_desc) {
size = CTXDESC_L2_ENTRIES * (CTXDESC_CD_DWORDS << 3);
- for (i = 0; i < cdcfg->num_l1_ents; i++) {
- if (!cdcfg->l1_desc[i].l2ptr)
+ for (i = 0; i < cd_table->num_l1_ents; i++) {
+ if (!cd_table->l1_desc[i].l2ptr)
continue;
dmam_free_coherent(smmu->dev, size,
- cdcfg->l1_desc[i].l2ptr,
- cdcfg->l1_desc[i].l2ptr_dma);
+ cd_table->l1_desc[i].l2ptr,
+ cd_table->l1_desc[i].l2ptr_dma);
}
- devm_kfree(smmu->dev, cdcfg->l1_desc);
- cdcfg->l1_desc = NULL;
+ devm_kfree(smmu->dev, cd_table->l1_desc);
+ cd_table->l1_desc = NULL;
- l1size = cdcfg->num_l1_ents * (CTXDESC_L1_DESC_DWORDS << 3);
+ l1size = cd_table->num_l1_ents * (CTXDESC_L1_DESC_DWORDS << 3);
} else {
- l1size = cdcfg->num_l1_ents * (CTXDESC_CD_DWORDS << 3);
+ l1size = cd_table->num_l1_ents * (CTXDESC_CD_DWORDS << 3);
}
- dmam_free_coherent(smmu->dev, l1size, cdcfg->cdtab, cdcfg->cdtab_dma);
- cdcfg->cdtab_dma = 0;
- cdcfg->cdtab = NULL;
+ dmam_free_coherent(smmu->dev, l1size, cd_table->cdtab, cd_table->cdtab_dma);
+ cd_table->cdtab_dma = 0;
+ cd_table->cdtab = NULL;
}
bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd)
--
2.41.0.640.ga95def55d0-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 45+ messages in thread
* Re: [PATCH v5 2/9] iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg
2023-08-08 17:11 ` [PATCH v5 2/9] iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg Michael Shavit
@ 2023-08-09 13:49 ` Will Deacon
2023-08-09 13:59 ` Jason Gunthorpe
0 siblings, 1 reply; 45+ messages in thread
From: Will Deacon @ 2023-08-09 13:49 UTC (permalink / raw)
To: Michael Shavit
Cc: iommu, linux-arm-kernel, linux-kernel, robin.murphy, nicolinc,
jgg, jean-philippe
On Wed, Aug 09, 2023 at 01:11:58AM +0800, Michael Shavit wrote:
> Remove struct arm_smmu_s1_cfg. This is really just a CD table with a
> bit of extra information. Enhance the existing CD table structure,
> struct arm_smmu_ctx_desc_cfg, with max_cds_bits and replace all usages
> of arm_smmu_s1_cfg with arm_smmu_ctx_desc_cfg.
>
> Compute the other values that were stored in s1cfg directly from
> existing arm_smmu_ctx_desc_cfg.
>
> For clarity, use the name "cd_table" for the variables pointing to
> arm_smmu_ctx_desc_cfg in the new code instead of cdcfg. A later patch
> will make this fully consistent.
>
> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
> Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
> Signed-off-by: Michael Shavit <mshavit@google.com>
> ---
Sorry, but I'm having a hard time seeing some of the benefits of this
particular change. Most of the rest of the series looks good, but see
below:
> @@ -1071,7 +1071,7 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
> bool cd_live;
> __le64 *cdptr;
>
> - if (WARN_ON(ssid >= (1 << smmu_domain->s1_cfg.s1cdmax)))
> + if (WARN_ON(ssid >= (1 << smmu_domain->cd_table.max_cds_bits)))
> return -E2BIG;
S1CDMAX is architectural terminology -- it's the name given to bits 63:59
of the STE structure. Why is "max_cds_bits" better?
> cdptr = arm_smmu_get_cd_ptr(smmu_domain, ssid);
> @@ -1138,19 +1138,16 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain)
> size_t l1size;
> size_t max_contexts;
> struct arm_smmu_device *smmu = smmu_domain->smmu;
> - struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;
> - struct arm_smmu_ctx_desc_cfg *cdcfg = &cfg->cdcfg;
> + struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->cd_table;
>
> - max_contexts = 1 << cfg->s1cdmax;
> + max_contexts = 1 << cdcfg->max_cds_bits;
>
> if (!(smmu->features & ARM_SMMU_FEAT_2_LVL_CDTAB) ||
> max_contexts <= CTXDESC_L2_ENTRIES) {
> - cfg->s1fmt = STRTAB_STE_0_S1FMT_LINEAR;
> cdcfg->num_l1_ents = max_contexts;
>
> l1size = max_contexts * (CTXDESC_CD_DWORDS << 3);
> } else {
> - cfg->s1fmt = STRTAB_STE_0_S1FMT_64K_L2;
And here we're dropping the S1FMT setting from the code allocating the
CD tables (i.e. the only code which should be aware of it's configuration)
and now having the low-level STE writing logic here:
> @@ -1360,10 +1357,14 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
> !master->stall_enabled)
> dst[1] |= cpu_to_le64(STRTAB_STE_1_S1STALLD);
>
> - val |= (s1_cfg->cdcfg.cdtab_dma & STRTAB_STE_0_S1CTXPTR_MASK) |
> - FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS) |
> - FIELD_PREP(STRTAB_STE_0_S1CDMAX, s1_cfg->s1cdmax) |
> - FIELD_PREP(STRTAB_STE_0_S1FMT, s1_cfg->s1fmt);
> + val |= (cd_table->cdtab_dma & STRTAB_STE_0_S1CTXPTR_MASK) |
> + FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS) |
> + FIELD_PREP(STRTAB_STE_0_S1CDMAX,
> + cd_table->max_cds_bits) |
> + FIELD_PREP(STRTAB_STE_0_S1FMT,
> + cd_table->l1_desc ?
> + STRTAB_STE_0_S1FMT_64K_L2 :
> + STRTAB_STE_0_S1FMT_LINEAR);
magically know that we're using 64k tables.
Why is this an improvement to the driver?
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc
2023-08-08 17:12 ` [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc Michael Shavit
@ 2023-08-09 13:50 ` Will Deacon
2023-08-10 9:15 ` Michael Shavit
0 siblings, 1 reply; 45+ messages in thread
From: Will Deacon @ 2023-08-09 13:50 UTC (permalink / raw)
To: Michael Shavit
Cc: iommu, linux-arm-kernel, linux-kernel, robin.murphy, nicolinc,
jgg, jean-philippe
On Wed, Aug 09, 2023 at 01:12:01AM +0800, Michael Shavit wrote:
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
> index 968559d625c40..e3992a0c16377 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
> @@ -37,6 +37,24 @@ struct arm_smmu_bond {
>
> static DEFINE_MUTEX(sva_lock);
>
> +static int arm_smmu_write_ctx_desc_devices(struct arm_smmu_domain *smmu_domain,
> + int ssid,
> + struct arm_smmu_ctx_desc *cd)
> +{
> + struct arm_smmu_master *master;
> + unsigned long flags;
> + int ret;
> +
> + spin_lock_irqsave(&smmu_domain->devices_lock, flags);
> + list_for_each_entry(master, &smmu_domain->devices, domain_head) {
> + ret = arm_smmu_write_ctx_desc(master, ssid, cd);
> + if (ret)
> + break;
> + }
> + spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
> + return ret;
> +}
> +
> /*
> * Check if the CPU ASID is available on the SMMU side. If a private context
> * descriptor is using it, try to replace it.
> @@ -80,7 +98,7 @@ arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
> * be some overlap between use of both ASIDs, until we invalidate the
> * TLB.
> */
> - arm_smmu_write_ctx_desc(smmu_domain, 0, cd);
> + arm_smmu_write_ctx_desc_devices(smmu_domain, 0, cd);
>
> /* Invalidate TLB entries previously associated with that context */
> arm_smmu_tlb_inv_asid(smmu, asid);
> @@ -222,7 +240,7 @@ static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
> * DMA may still be running. Keep the cd valid to avoid C_BAD_CD events,
> * but disable translation.
> */
> - arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, &quiet_cd);
> + arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, &quiet_cd);
>
> arm_smmu_tlb_inv_asid(smmu_domain->smmu, smmu_mn->cd->asid);
> arm_smmu_atc_inv_domain(smmu_domain, mm->pasid, 0, 0);
> @@ -279,9 +297,11 @@ arm_smmu_mmu_notifier_get(struct arm_smmu_domain *smmu_domain,
> goto err_free_cd;
> }
>
> - ret = arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, cd);
> - if (ret)
> + ret = arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, cd);
> + if (ret) {
> + arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, NULL);
Why is it safe to drop the lock between these two calls?
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> index c01023404c26c..34bd7815aeb8e 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -971,14 +971,12 @@ void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid)
> arm_smmu_cmdq_issue_cmd_with_sync(smmu, &cmd);
> }
>
> -static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain,
> +static void arm_smmu_sync_cd(struct arm_smmu_master *master,
> int ssid, bool leaf)
> {
> size_t i;
> - unsigned long flags;
> - struct arm_smmu_master *master;
> struct arm_smmu_cmdq_batch cmds;
> - struct arm_smmu_device *smmu = smmu_domain->smmu;
> + struct arm_smmu_device *smmu = master->smmu;
> struct arm_smmu_cmdq_ent cmd = {
> .opcode = CMDQ_OP_CFGI_CD,
> .cfgi = {
> @@ -988,15 +986,10 @@ static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain,
> };
>
> cmds.num = 0;
> -
> - spin_lock_irqsave(&smmu_domain->devices_lock, flags);
Since you're dropping this and relying on the lock being taken higher up
callstack, can we add a lockdep assertion that we do actually hold the
devices_lock, please?
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 8/9] iommu/arm-smmu-v3: Skip cd sync if CD table isn't active
2023-08-08 17:12 ` [PATCH v5 8/9] iommu/arm-smmu-v3: Skip cd sync if CD table isn't active Michael Shavit
@ 2023-08-09 13:50 ` Will Deacon
2023-08-10 8:34 ` Michael Shavit
0 siblings, 1 reply; 45+ messages in thread
From: Will Deacon @ 2023-08-09 13:50 UTC (permalink / raw)
To: Michael Shavit
Cc: iommu, linux-arm-kernel, linux-kernel, robin.murphy, nicolinc,
jgg, jean-philippe
On Wed, Aug 09, 2023 at 01:12:04AM +0800, Michael Shavit wrote:
> This commit explicitly keeps track of whether a CD table is installed in
> an STE so that arm_smmu_sync_cd can skip the sync when unnecessary. This
> was previously achieved through the domain->devices list, but we are
> moving to a model where arm_smmu_sync_cd directly operates on a master
> and the master's CD table instead of a domain.
Why is this path worth optimising?
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> index f5ad386cc8760..488d12dd2d4aa 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -985,6 +985,9 @@ static void arm_smmu_sync_cd(struct arm_smmu_master *master,
> },
> };
>
> + if (!master->cd_table.installed)
> + return;
Doesn't this interact badly with the sync in arm_smmu_detach_dev(), which I
think happens after zapping the STE?
> cmds.num = 0;
> for (i = 0; i < master->num_streams; i++) {
> cmd.cfgi.sid = master->streams[i].id;
> @@ -1091,7 +1094,7 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_master *master, int ssid,
> cdptr[3] = cpu_to_le64(cd->mair);
>
> /*
> - * STE is live, and the SMMU might read dwords of this CD in any
> + * STE may be live, and the SMMU might read dwords of this CD in any
> * order. Ensure that it observes valid values before reading
> * V=1.
> */
Why does this patch need to update this comment?
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 6/9] iommu/arm-smmu-v3: Move CD table to arm_smmu_master
2023-08-08 17:12 ` [PATCH v5 6/9] iommu/arm-smmu-v3: Move CD table to arm_smmu_master Michael Shavit
@ 2023-08-09 13:50 ` Will Deacon
2023-08-10 9:23 ` Michael Shavit
2023-08-10 9:45 ` Michael Shavit
2023-08-15 12:10 ` Michael Shavit
1 sibling, 2 replies; 45+ messages in thread
From: Will Deacon @ 2023-08-09 13:50 UTC (permalink / raw)
To: Michael Shavit
Cc: iommu, linux-arm-kernel, linux-kernel, robin.murphy, nicolinc,
jgg, jean-philippe
On Wed, Aug 09, 2023 at 01:12:02AM +0800, Michael Shavit wrote:
> @@ -2203,7 +2186,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain,
> ias = min_t(unsigned long, ias, VA_BITS);
> oas = smmu->ias;
> fmt = ARM_64_LPAE_S1;
> - finalise_stage_fn = arm_smmu_domain_finalise_s1;
> + finalise_stage_fn = arm_smmu_domain_finalise_cd;
Why is this a better name? Now we have inconsistency with
arm_smmu_domain_finalise_s2().
> break;
> case ARM_SMMU_DOMAIN_NESTED:
> case ARM_SMMU_DOMAIN_S2:
> @@ -2402,6 +2385,16 @@ static void arm_smmu_detach_dev(struct arm_smmu_master *master)
> master->domain = NULL;
> master->ats_enabled = false;
> arm_smmu_install_ste_for_dev(master);
> + /*
> + * The table is uninstalled before clearing the CD to prevent an
> + * unnecessary sync in arm_smmu_write_ctx_desc. Although clearing the
> + * CD entry isn't strictly required to detach the domain since the
> + * table is uninstalled anyway, it's more proper and helps avoid
> + * confusion in the call to arm_smmu_write_ctx_desc on the next attach
You can remove the "it's more proper" part.
> + * (which expects the entry to be empty).
> + */
> + if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 && master->cd_table.cdtab)
> + arm_smmu_write_ctx_desc(master, 0, NULL);
> }
>
> static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> @@ -2436,22 +2429,14 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> if (!smmu_domain->smmu) {
> smmu_domain->smmu = smmu;
> ret = arm_smmu_domain_finalise(domain, master);
> - if (ret) {
> + if (ret)
> smmu_domain->smmu = NULL;
> - goto out_unlock;
> - }
> - } else if (smmu_domain->smmu != smmu) {
> - ret = -EINVAL;
> - goto out_unlock;
> - } else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 &&
> - master->ssid_bits != smmu_domain->cd_table.max_cds_bits) {
> + } else if (smmu_domain->smmu != smmu)
> ret = -EINVAL;
> - goto out_unlock;
> - } else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 &&
> - smmu_domain->cd_table.stall_enabled != master->stall_enabled) {
> - ret = -EINVAL;
> - goto out_unlock;
> - }
Removing these checks on the domain is pretty nice.
> @@ -2465,6 +2450,22 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> if (smmu_domain->stage != ARM_SMMU_DOMAIN_BYPASS)
> master->ats_enabled = arm_smmu_ats_supported(master);
>
> + if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
> + if (!master->cd_table.cdtab) {
> + ret = arm_smmu_alloc_cd_tables(master);
> + if (ret) {
> + master->domain = NULL;
> + return ret;
> + }
> + }
> +
> + ret = arm_smmu_write_ctx_desc(master, 0, &smmu_domain->cd);
> + if (ret) {
> + master->domain = NULL;
> + return ret;
Can you leak the cd tables here if you just allocated them?
> @@ -2472,10 +2473,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
>
> arm_smmu_enable_ats(master);
> -
> -out_unlock:
> - mutex_unlock(&smmu_domain->init_mutex);
> - return ret;
> + return 0;
> }
>
> static int arm_smmu_map_pages(struct iommu_domain *domain, unsigned long iova,
> @@ -2719,6 +2717,8 @@ static void arm_smmu_release_device(struct device *dev)
> arm_smmu_detach_dev(master);
> arm_smmu_disable_pasid(master);
> arm_smmu_remove_master(master);
> + if (master->cd_table.cdtab_dma)
Why are you checking 'cdtab_dma' here instead of just 'cdtab'?
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 2/9] iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg
2023-08-09 13:49 ` Will Deacon
@ 2023-08-09 13:59 ` Jason Gunthorpe
2023-08-09 14:55 ` Will Deacon
0 siblings, 1 reply; 45+ messages in thread
From: Jason Gunthorpe @ 2023-08-09 13:59 UTC (permalink / raw)
To: Will Deacon
Cc: Michael Shavit, iommu, linux-arm-kernel, linux-kernel,
robin.murphy, nicolinc, jean-philippe
On Wed, Aug 09, 2023 at 02:49:41PM +0100, Will Deacon wrote:
> > @@ -1360,10 +1357,14 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
> > !master->stall_enabled)
> > dst[1] |= cpu_to_le64(STRTAB_STE_1_S1STALLD);
> >
> > - val |= (s1_cfg->cdcfg.cdtab_dma & STRTAB_STE_0_S1CTXPTR_MASK) |
> > - FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS) |
> > - FIELD_PREP(STRTAB_STE_0_S1CDMAX, s1_cfg->s1cdmax) |
> > - FIELD_PREP(STRTAB_STE_0_S1FMT, s1_cfg->s1fmt);
> > + val |= (cd_table->cdtab_dma & STRTAB_STE_0_S1CTXPTR_MASK) |
> > + FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS) |
> > + FIELD_PREP(STRTAB_STE_0_S1CDMAX,
> > + cd_table->max_cds_bits) |
> > + FIELD_PREP(STRTAB_STE_0_S1FMT,
> > + cd_table->l1_desc ?
> > + STRTAB_STE_0_S1FMT_64K_L2 :
> > + STRTAB_STE_0_S1FMT_LINEAR);
>
> magically know that we're using 64k tables.
>
> Why is this an improvement to the driver?
Put the above in a function
arm_smmu_get_cd_ste(struct arm_smmu_ctx_desc_cfg *cdtab, void *ste)
And it makes more sense.
We don't need the driver to precompute the "s1_cfg" parameters and
store them in a redundant struct along side the ctx_desc_cfg when we
can compute those same values on the fly with no cost.
Jason
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 2/9] iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg
2023-08-09 13:59 ` Jason Gunthorpe
@ 2023-08-09 14:55 ` Will Deacon
2023-08-09 15:08 ` Jason Gunthorpe
0 siblings, 1 reply; 45+ messages in thread
From: Will Deacon @ 2023-08-09 14:55 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Michael Shavit, iommu, linux-arm-kernel, linux-kernel,
robin.murphy, nicolinc, jean-philippe
On Wed, Aug 09, 2023 at 10:59:33AM -0300, Jason Gunthorpe wrote:
> On Wed, Aug 09, 2023 at 02:49:41PM +0100, Will Deacon wrote:
>
> > > @@ -1360,10 +1357,14 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
> > > !master->stall_enabled)
> > > dst[1] |= cpu_to_le64(STRTAB_STE_1_S1STALLD);
> > >
> > > - val |= (s1_cfg->cdcfg.cdtab_dma & STRTAB_STE_0_S1CTXPTR_MASK) |
> > > - FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS) |
> > > - FIELD_PREP(STRTAB_STE_0_S1CDMAX, s1_cfg->s1cdmax) |
> > > - FIELD_PREP(STRTAB_STE_0_S1FMT, s1_cfg->s1fmt);
> > > + val |= (cd_table->cdtab_dma & STRTAB_STE_0_S1CTXPTR_MASK) |
> > > + FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS) |
> > > + FIELD_PREP(STRTAB_STE_0_S1CDMAX,
> > > + cd_table->max_cds_bits) |
> > > + FIELD_PREP(STRTAB_STE_0_S1FMT,
> > > + cd_table->l1_desc ?
> > > + STRTAB_STE_0_S1FMT_64K_L2 :
> > > + STRTAB_STE_0_S1FMT_LINEAR);
> >
> > magically know that we're using 64k tables.
> >
> > Why is this an improvement to the driver?
>
> Put the above in a function
>
> arm_smmu_get_cd_ste(struct arm_smmu_ctx_desc_cfg *cdtab, void *ste)
>
> And it makes more sense.
Sorry, but I'm not seeing it :/
> We don't need the driver to precompute the "s1_cfg" parameters and
> store them in a redundant struct along side the ctx_desc_cfg when we
> can compute those same values on the fly with no cost.
But the computation isn't happening -- the STRTAB_STE_0_S1FMT_64K_L2
constant is hardcoded here. If we want to use 4k leaf tables in some
cases, how would you add that? Such a change shouldn't need the low-level
strtab creation code to change.
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 2/9] iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg
2023-08-09 14:55 ` Will Deacon
@ 2023-08-09 15:08 ` Jason Gunthorpe
2023-08-09 16:22 ` Will Deacon
0 siblings, 1 reply; 45+ messages in thread
From: Jason Gunthorpe @ 2023-08-09 15:08 UTC (permalink / raw)
To: Will Deacon
Cc: Michael Shavit, iommu, linux-arm-kernel, linux-kernel,
robin.murphy, nicolinc, jean-philippe
On Wed, Aug 09, 2023 at 03:55:43PM +0100, Will Deacon wrote:
> On Wed, Aug 09, 2023 at 10:59:33AM -0300, Jason Gunthorpe wrote:
> > On Wed, Aug 09, 2023 at 02:49:41PM +0100, Will Deacon wrote:
> >
> > > > @@ -1360,10 +1357,14 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
> > > > !master->stall_enabled)
> > > > dst[1] |= cpu_to_le64(STRTAB_STE_1_S1STALLD);
> > > >
> > > > - val |= (s1_cfg->cdcfg.cdtab_dma & STRTAB_STE_0_S1CTXPTR_MASK) |
> > > > - FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS) |
> > > > - FIELD_PREP(STRTAB_STE_0_S1CDMAX, s1_cfg->s1cdmax) |
> > > > - FIELD_PREP(STRTAB_STE_0_S1FMT, s1_cfg->s1fmt);
> > > > + val |= (cd_table->cdtab_dma & STRTAB_STE_0_S1CTXPTR_MASK) |
> > > > + FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS) |
> > > > + FIELD_PREP(STRTAB_STE_0_S1CDMAX,
> > > > + cd_table->max_cds_bits) |
> > > > + FIELD_PREP(STRTAB_STE_0_S1FMT,
> > > > + cd_table->l1_desc ?
> > > > + STRTAB_STE_0_S1FMT_64K_L2 :
> > > > + STRTAB_STE_0_S1FMT_LINEAR);
> > >
> > > magically know that we're using 64k tables.
> > >
> > > Why is this an improvement to the driver?
> >
> > Put the above in a function
> >
> > arm_smmu_get_cd_ste(struct arm_smmu_ctx_desc_cfg *cdtab, void *ste)
> >
> > And it makes more sense.
>
> Sorry, but I'm not seeing it :/
>
> > We don't need the driver to precompute the "s1_cfg" parameters and
> > store them in a redundant struct along side the ctx_desc_cfg when we
> > can compute those same values on the fly with no cost.
>
> But the computation isn't happening -- the STRTAB_STE_0_S1FMT_64K_L2
> constant is hardcoded here.
So it would be hard coded in arm_smmu_get_cd_ste() because that
reflects the current state of CD table code.
> If we want to use 4k leaf tables in some cases, how would you add
> that? Such a change shouldn't need the low-level strtab creation
> code to change.
You would modify arm_smmu_ctx_desc_cfg to teach it about the different
format. It would gain some (enum?) member that specifies the CD table
layout and geometry. arm_smmu_get_cd_ste() will interpret that member
and generate the correct STE for the specifc cd table.
It is a standard OOP sort of practice that the object self-describes
and has accessors to export its internal definition. In this case the
STE bits are part of/derived from the internal definition of the CD
table.
Jason
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 2/9] iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg
2023-08-09 15:08 ` Jason Gunthorpe
@ 2023-08-09 16:22 ` Will Deacon
2023-08-09 16:26 ` Jason Gunthorpe
0 siblings, 1 reply; 45+ messages in thread
From: Will Deacon @ 2023-08-09 16:22 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Michael Shavit, iommu, linux-arm-kernel, linux-kernel,
robin.murphy, nicolinc, jean-philippe
On Wed, Aug 09, 2023 at 12:08:02PM -0300, Jason Gunthorpe wrote:
> On Wed, Aug 09, 2023 at 03:55:43PM +0100, Will Deacon wrote:
> > On Wed, Aug 09, 2023 at 10:59:33AM -0300, Jason Gunthorpe wrote:
> > > On Wed, Aug 09, 2023 at 02:49:41PM +0100, Will Deacon wrote:
> > >
> > > > > @@ -1360,10 +1357,14 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
> > > > > !master->stall_enabled)
> > > > > dst[1] |= cpu_to_le64(STRTAB_STE_1_S1STALLD);
> > > > >
> > > > > - val |= (s1_cfg->cdcfg.cdtab_dma & STRTAB_STE_0_S1CTXPTR_MASK) |
> > > > > - FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS) |
> > > > > - FIELD_PREP(STRTAB_STE_0_S1CDMAX, s1_cfg->s1cdmax) |
> > > > > - FIELD_PREP(STRTAB_STE_0_S1FMT, s1_cfg->s1fmt);
> > > > > + val |= (cd_table->cdtab_dma & STRTAB_STE_0_S1CTXPTR_MASK) |
> > > > > + FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS) |
> > > > > + FIELD_PREP(STRTAB_STE_0_S1CDMAX,
> > > > > + cd_table->max_cds_bits) |
> > > > > + FIELD_PREP(STRTAB_STE_0_S1FMT,
> > > > > + cd_table->l1_desc ?
> > > > > + STRTAB_STE_0_S1FMT_64K_L2 :
> > > > > + STRTAB_STE_0_S1FMT_LINEAR);
> > > >
> > > > magically know that we're using 64k tables.
> > > >
> > > > Why is this an improvement to the driver?
> > >
> > > Put the above in a function
> > >
> > > arm_smmu_get_cd_ste(struct arm_smmu_ctx_desc_cfg *cdtab, void *ste)
> > >
> > > And it makes more sense.
> >
> > Sorry, but I'm not seeing it :/
> >
> > > We don't need the driver to precompute the "s1_cfg" parameters and
> > > store them in a redundant struct along side the ctx_desc_cfg when we
> > > can compute those same values on the fly with no cost.
> >
> > But the computation isn't happening -- the STRTAB_STE_0_S1FMT_64K_L2
> > constant is hardcoded here.
>
> So it would be hard coded in arm_smmu_get_cd_ste() because that
> reflects the current state of CD table code.
>
> > If we want to use 4k leaf tables in some cases, how would you add
> > that? Such a change shouldn't need the low-level strtab creation
> > code to change.
>
> You would modify arm_smmu_ctx_desc_cfg to teach it about the different
> format. It would gain some (enum?) member that specifies the CD table
> layout and geometry. arm_smmu_get_cd_ste() will interpret that member
> and generate the correct STE for the specifc cd table.
Sounds a lot like the existing s1fmt field. Can we keep it?
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 2/9] iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg
2023-08-09 16:22 ` Will Deacon
@ 2023-08-09 16:26 ` Jason Gunthorpe
2023-08-09 16:27 ` Will Deacon
0 siblings, 1 reply; 45+ messages in thread
From: Jason Gunthorpe @ 2023-08-09 16:26 UTC (permalink / raw)
To: Will Deacon
Cc: Michael Shavit, iommu, linux-arm-kernel, linux-kernel,
robin.murphy, nicolinc, jean-philippe
On Wed, Aug 09, 2023 at 05:22:54PM +0100, Will Deacon wrote:
> > > If we want to use 4k leaf tables in some cases, how would you add
> > > that? Such a change shouldn't need the low-level strtab creation
> > > code to change.
> >
> > You would modify arm_smmu_ctx_desc_cfg to teach it about the different
> > format. It would gain some (enum?) member that specifies the CD table
> > layout and geometry. arm_smmu_get_cd_ste() will interpret that member
> > and generate the correct STE for the specifc cd table.
>
> Sounds a lot like the existing s1fmt field. Can we keep it?
If you are OK with the dead code, I don't object. But let's put it in
the struct arm_smmu_ctx_desc_cfg.
Jason
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 2/9] iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg
2023-08-09 16:26 ` Jason Gunthorpe
@ 2023-08-09 16:27 ` Will Deacon
2023-08-10 9:33 ` Michael Shavit
0 siblings, 1 reply; 45+ messages in thread
From: Will Deacon @ 2023-08-09 16:27 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Michael Shavit, iommu, linux-arm-kernel, linux-kernel,
robin.murphy, nicolinc, jean-philippe
On Wed, Aug 09, 2023 at 01:26:41PM -0300, Jason Gunthorpe wrote:
> On Wed, Aug 09, 2023 at 05:22:54PM +0100, Will Deacon wrote:
>
> > > > If we want to use 4k leaf tables in some cases, how would you add
> > > > that? Such a change shouldn't need the low-level strtab creation
> > > > code to change.
> > >
> > > You would modify arm_smmu_ctx_desc_cfg to teach it about the different
> > > format. It would gain some (enum?) member that specifies the CD table
> > > layout and geometry. arm_smmu_get_cd_ste() will interpret that member
> > > and generate the correct STE for the specifc cd table.
> >
> > Sounds a lot like the existing s1fmt field. Can we keep it?
>
> If you are OK with the dead code, I don't object. But let's put it in
> the struct arm_smmu_ctx_desc_cfg.
Ok, we have a deal!
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 8/9] iommu/arm-smmu-v3: Skip cd sync if CD table isn't active
2023-08-09 13:50 ` Will Deacon
@ 2023-08-10 8:34 ` Michael Shavit
2023-08-10 16:27 ` Will Deacon
0 siblings, 1 reply; 45+ messages in thread
From: Michael Shavit @ 2023-08-10 8:34 UTC (permalink / raw)
To: Will Deacon
Cc: iommu, linux-arm-kernel, linux-kernel, robin.murphy, nicolinc,
jgg, jean-philippe
On Wed, Aug 9, 2023 at 9:50 PM Will Deacon <will@kernel.org> wrote:
>
> On Wed, Aug 09, 2023 at 01:12:04AM +0800, Michael Shavit wrote:
> > This commit explicitly keeps track of whether a CD table is installed in
> > an STE so that arm_smmu_sync_cd can skip the sync when unnecessary. This
> > was previously achieved through the domain->devices list, but we are
> > moving to a model where arm_smmu_sync_cd directly operates on a master
> > and the master's CD table instead of a domain.
>
> Why is this path worth optimising?
I have no idea what the practical impact of this optimization is, but
the motivation here was to make the overall series as close to a nop
as possible. This optimization existed before but is "broken" by the
previous patch. This patch restores it.
> Doesn't this interact badly with the sync in arm_smmu_detach_dev(), which I
> think happens after zapping the STE?
The arm_smmu_write_ctx_desc call added in arm_smmu_detach_dev() was
inserted after zapping the STE precisely so that we could skip the
sync. Is there a concern that a stale CD could be used when the
CDtable is re-inserted into the STE?
> > /*
> > - * STE is live, and the SMMU might read dwords of this CD in any
> > + * STE may be live, and the SMMU might read dwords of this CD in any
> > * order. Ensure that it observes valid values before reading
> > * V=1.
> > */
>
> Why does this patch need to update this comment?
This is a drive-by to make this comment more accurate. Note how
(before this patch series) arm_smmu_domain_finalise_s1 explicitly
mentions that it calls arm_smmu_write_ctx_desc while the STE isn't
installed yet. Yet this comment asserts the STE *is* live.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc
2023-08-09 13:50 ` Will Deacon
@ 2023-08-10 9:15 ` Michael Shavit
2023-08-10 14:40 ` Will Deacon
2023-08-15 5:04 ` Michael Shavit
0 siblings, 2 replies; 45+ messages in thread
From: Michael Shavit @ 2023-08-10 9:15 UTC (permalink / raw)
To: Will Deacon
Cc: iommu, linux-arm-kernel, linux-kernel, robin.murphy, nicolinc,
jgg, jean-philippe
On Wed, Aug 9, 2023 at 9:50 PM Will Deacon <will@kernel.org> wrote:
>
> > - ret = arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, cd);
> > - if (ret)
> > + ret = arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, cd);
> > + if (ret) {
> > + arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, NULL);
>
> Why is it safe to drop the lock between these two calls?
Hmmm this is a tricky question.
Tracing through the SVA flow, it seems like there's a scenario where
multiple masters (with the same upstream SMMU device) can be attached
to the same primary/non-sva domain, in which case calling
iommu_attach_device_pasid on one device will write the CD entry for
both masters. This is still the case even with this patch series, and
changing this behavior will be the subject of a separate follow-up.
This is weird, especially since the second master need not even have
the sva_enabled bit set. This also means that the list of attached
masters can indeed change between these two calls if that second
master (not the one used on the iommu_attach_device_pasid call leading
to this code) is detached/attached at the same time. It's hard for me
to reason about whether this is safe or not, since this is already
weird behavior...
>
> Since you're dropping this and relying on the lock being taken higher up
> callstack, can we add a lockdep assertion that we do actually hold the
> devices_lock, please?
Will do!
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 6/9] iommu/arm-smmu-v3: Move CD table to arm_smmu_master
2023-08-09 13:50 ` Will Deacon
@ 2023-08-10 9:23 ` Michael Shavit
2023-08-10 14:38 ` Will Deacon
2023-08-10 9:45 ` Michael Shavit
1 sibling, 1 reply; 45+ messages in thread
From: Michael Shavit @ 2023-08-10 9:23 UTC (permalink / raw)
To: Will Deacon
Cc: iommu, linux-arm-kernel, linux-kernel, robin.murphy, nicolinc,
jgg, jean-philippe
>
> > @@ -2465,6 +2450,22 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> > if (smmu_domain->stage != ARM_SMMU_DOMAIN_BYPASS)
> > master->ats_enabled = arm_smmu_ats_supported(master);
> >
> > + if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
> > + if (!master->cd_table.cdtab) {
> > + ret = arm_smmu_alloc_cd_tables(master);
> > + if (ret) {
> > + master->domain = NULL;
> > + return ret;
> > + }
> > + }
> > +
> > + ret = arm_smmu_write_ctx_desc(master, 0, &smmu_domain->cd);
> > + if (ret) {
> > + master->domain = NULL;
> > + return ret;
>
> Can you leak the cd tables here if you just allocated them?
The CD table is only de-allocated when the SMMU device is released, so
this isn't "leaked" anymore than on a successful attachment. In a
previous version of this patch, this CD table was even pre-allocated
at probe time but is deferred to first attach following this
discussion: https://lore.kernel.org/lkml/ZMOzs1%2FxoEPX2+vA@nvidia.com/
.
> > @@ -2472,10 +2473,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> > spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
> >
> > arm_smmu_enable_ats(master);
> > -
> > -out_unlock:
> > - mutex_unlock(&smmu_domain->init_mutex);
> > - return ret;
> > + return 0;
> > }
> >
> > static int arm_smmu_map_pages(struct iommu_domain *domain, unsigned long iova,
> > @@ -2719,6 +2717,8 @@ static void arm_smmu_release_device(struct device *dev)
> > arm_smmu_detach_dev(master);
> > arm_smmu_disable_pasid(master);
> > arm_smmu_remove_master(master);
> > + if (master->cd_table.cdtab_dma)
>
> Why are you checking 'cdtab_dma' here instead of just 'cdtab'?
cd_table is statically allocated as part of the arm_smmu_master
struct. I suppose it could be allocated by arm_smmu_alloc_cd_tables()
instead?
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 2/9] iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg
2023-08-09 16:27 ` Will Deacon
@ 2023-08-10 9:33 ` Michael Shavit
2023-08-10 9:43 ` Will Deacon
0 siblings, 1 reply; 45+ messages in thread
From: Michael Shavit @ 2023-08-10 9:33 UTC (permalink / raw)
To: Will Deacon
Cc: Jason Gunthorpe, iommu, linux-arm-kernel, linux-kernel,
robin.murphy, nicolinc, jean-philippe
> > > Sounds a lot like the existing s1fmt field. Can we keep it?
> >
> > If you are OK with the dead code, I don't object. But let's put it in
> > the struct arm_smmu_ctx_desc_cfg.
>
> Ok, we have a deal!
What dead code? Is the deal here that we keep the field, but still
infer the value to write from (cd_table->l1_desc == null) in
arm_smmu_write_strtab_ent??
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 2/9] iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg
2023-08-10 9:33 ` Michael Shavit
@ 2023-08-10 9:43 ` Will Deacon
2023-08-10 12:04 ` Jason Gunthorpe
0 siblings, 1 reply; 45+ messages in thread
From: Will Deacon @ 2023-08-10 9:43 UTC (permalink / raw)
To: Michael Shavit
Cc: Jason Gunthorpe, iommu, linux-arm-kernel, linux-kernel,
robin.murphy, nicolinc, jean-philippe
On Thu, Aug 10, 2023 at 05:33:53PM +0800, Michael Shavit wrote:
> > > > Sounds a lot like the existing s1fmt field. Can we keep it?
> > >
> > > If you are OK with the dead code, I don't object. But let's put it in
> > > the struct arm_smmu_ctx_desc_cfg.
> >
> > Ok, we have a deal!
>
> What dead code? Is the deal here that we keep the field, but still
> infer the value to write from (cd_table->l1_desc == null) in
> arm_smmu_write_strtab_ent??
Keep the field and write it directly when populating the ste (i.e. don't
infer anything), but the field moves into 'struct arm_smmu_ctx_desc_cfg'.
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 6/9] iommu/arm-smmu-v3: Move CD table to arm_smmu_master
2023-08-09 13:50 ` Will Deacon
2023-08-10 9:23 ` Michael Shavit
@ 2023-08-10 9:45 ` Michael Shavit
2023-08-10 14:34 ` Will Deacon
1 sibling, 1 reply; 45+ messages in thread
From: Michael Shavit @ 2023-08-10 9:45 UTC (permalink / raw)
To: Will Deacon
Cc: iommu, linux-arm-kernel, linux-kernel, robin.murphy, nicolinc,
jgg, jean-philippe
On Wed, Aug 9, 2023 at 9:50 PM Will Deacon <will@kernel.org> wrote:
>
> On Wed, Aug 09, 2023 at 01:12:02AM +0800, Michael Shavit wrote:
> > @@ -2203,7 +2186,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain,
> > ias = min_t(unsigned long, ias, VA_BITS);
> > oas = smmu->ias;
> > fmt = ARM_64_LPAE_S1;
> > - finalise_stage_fn = arm_smmu_domain_finalise_s1;
> > + finalise_stage_fn = arm_smmu_domain_finalise_cd;
>
> Why is this a better name? Now we have inconsistency with
> arm_smmu_domain_finalise_s2().
There was a time where s1cfg represented the entire STE and carried
the entire cd table. We've gotten rid of s1cfg, and now only store
arm_smmu_ctx_desc in the arm_smmu_domain for stage 1 domains.
arm_smmu_domain_finalise_cd is IMO more clear, especially given the
historical baggage around `s1`.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 2/9] iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg
2023-08-10 9:43 ` Will Deacon
@ 2023-08-10 12:04 ` Jason Gunthorpe
2023-08-10 17:15 ` Michael Shavit
0 siblings, 1 reply; 45+ messages in thread
From: Jason Gunthorpe @ 2023-08-10 12:04 UTC (permalink / raw)
To: Will Deacon
Cc: Michael Shavit, iommu, linux-arm-kernel, linux-kernel,
robin.murphy, nicolinc, jean-philippe
On Thu, Aug 10, 2023 at 10:43:33AM +0100, Will Deacon wrote:
> On Thu, Aug 10, 2023 at 05:33:53PM +0800, Michael Shavit wrote:
> > > > > Sounds a lot like the existing s1fmt field. Can we keep it?
> > > >
> > > > If you are OK with the dead code, I don't object. But let's put it in
> > > > the struct arm_smmu_ctx_desc_cfg.
> > >
> > > Ok, we have a deal!
> >
> > What dead code? Is the deal here that we keep the field, but still
> > infer the value to write from (cd_table->l1_desc == null) in
> > arm_smmu_write_strtab_ent??
>
> Keep the field and write it directly when populating the ste (i.e. don't
> infer anything), but the field moves into 'struct arm_smmu_ctx_desc_cfg'.
Yes - the 'dead code' is that we introduce storage for a field that is
always a known constant (STRTAB_STE_0_S1FMT_64K_L2).
Jason
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 6/9] iommu/arm-smmu-v3: Move CD table to arm_smmu_master
2023-08-10 9:45 ` Michael Shavit
@ 2023-08-10 14:34 ` Will Deacon
2023-08-10 14:56 ` Jason Gunthorpe
0 siblings, 1 reply; 45+ messages in thread
From: Will Deacon @ 2023-08-10 14:34 UTC (permalink / raw)
To: Michael Shavit
Cc: iommu, linux-arm-kernel, linux-kernel, robin.murphy, nicolinc,
jgg, jean-philippe
On Thu, Aug 10, 2023 at 05:45:03PM +0800, Michael Shavit wrote:
> On Wed, Aug 9, 2023 at 9:50 PM Will Deacon <will@kernel.org> wrote:
> >
> > On Wed, Aug 09, 2023 at 01:12:02AM +0800, Michael Shavit wrote:
> > > @@ -2203,7 +2186,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain,
> > > ias = min_t(unsigned long, ias, VA_BITS);
> > > oas = smmu->ias;
> > > fmt = ARM_64_LPAE_S1;
> > > - finalise_stage_fn = arm_smmu_domain_finalise_s1;
> > > + finalise_stage_fn = arm_smmu_domain_finalise_cd;
> >
> > Why is this a better name? Now we have inconsistency with
> > arm_smmu_domain_finalise_s2().
>
> There was a time where s1cfg represented the entire STE and carried
> the entire cd table. We've gotten rid of s1cfg, and now only store
> arm_smmu_ctx_desc in the arm_smmu_domain for stage 1 domains.
> arm_smmu_domain_finalise_cd is IMO more clear, especially given the
> historical baggage around `s1`.
Ok, but it's the inconsistency I object to. I don't think it's clear at
all to have arm_smmu_domain_finalise_cd() and arm_smmu_domain_finalise_s2().
The easiest thing is to leave it as-is.
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 6/9] iommu/arm-smmu-v3: Move CD table to arm_smmu_master
2023-08-10 9:23 ` Michael Shavit
@ 2023-08-10 14:38 ` Will Deacon
0 siblings, 0 replies; 45+ messages in thread
From: Will Deacon @ 2023-08-10 14:38 UTC (permalink / raw)
To: Michael Shavit
Cc: iommu, linux-arm-kernel, linux-kernel, robin.murphy, nicolinc,
jgg, jean-philippe
On Thu, Aug 10, 2023 at 05:23:37PM +0800, Michael Shavit wrote:
> >
> > > @@ -2465,6 +2450,22 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> > > if (smmu_domain->stage != ARM_SMMU_DOMAIN_BYPASS)
> > > master->ats_enabled = arm_smmu_ats_supported(master);
> > >
> > > + if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
> > > + if (!master->cd_table.cdtab) {
> > > + ret = arm_smmu_alloc_cd_tables(master);
> > > + if (ret) {
> > > + master->domain = NULL;
> > > + return ret;
> > > + }
> > > + }
> > > +
> > > + ret = arm_smmu_write_ctx_desc(master, 0, &smmu_domain->cd);
> > > + if (ret) {
> > > + master->domain = NULL;
> > > + return ret;
> >
> > Can you leak the cd tables here if you just allocated them?
>
> The CD table is only de-allocated when the SMMU device is released, so
> this isn't "leaked" anymore than on a successful attachment. In a
> previous version of this patch, this CD table was even pre-allocated
> at probe time but is deferred to first attach following this
> discussion: https://lore.kernel.org/lkml/ZMOzs1%2FxoEPX2+vA@nvidia.com/
Thanks, that makes sense.
> > > @@ -2472,10 +2473,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> > > spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
> > >
> > > arm_smmu_enable_ats(master);
> > > -
> > > -out_unlock:
> > > - mutex_unlock(&smmu_domain->init_mutex);
> > > - return ret;
> > > + return 0;
> > > }
> > >
> > > static int arm_smmu_map_pages(struct iommu_domain *domain, unsigned long iova,
> > > @@ -2719,6 +2717,8 @@ static void arm_smmu_release_device(struct device *dev)
> > > arm_smmu_detach_dev(master);
> > > arm_smmu_disable_pasid(master);
> > > arm_smmu_remove_master(master);
> > > + if (master->cd_table.cdtab_dma)
> >
> > Why are you checking 'cdtab_dma' here instead of just 'cdtab'?
>
> cd_table is statically allocated as part of the arm_smmu_master
> struct. I suppose it could be allocated by arm_smmu_alloc_cd_tables()
> instead?
I just mean you could check 'master->cd_table.cdtab' like you do in other
places. The DMA pointer is supposed to be opaque.
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc
2023-08-10 9:15 ` Michael Shavit
@ 2023-08-10 14:40 ` Will Deacon
2023-08-10 15:39 ` Jason Gunthorpe
2023-08-15 5:04 ` Michael Shavit
1 sibling, 1 reply; 45+ messages in thread
From: Will Deacon @ 2023-08-10 14:40 UTC (permalink / raw)
To: Michael Shavit
Cc: iommu, linux-arm-kernel, linux-kernel, robin.murphy, nicolinc,
jgg, jean-philippe
On Thu, Aug 10, 2023 at 05:15:50PM +0800, Michael Shavit wrote:
> On Wed, Aug 9, 2023 at 9:50 PM Will Deacon <will@kernel.org> wrote:
> >
> > > - ret = arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, cd);
> > > - if (ret)
> > > + ret = arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, cd);
> > > + if (ret) {
> > > + arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, NULL);
> >
> > Why is it safe to drop the lock between these two calls?
>
> Hmmm this is a tricky question.
> Tracing through the SVA flow, it seems like there's a scenario where
> multiple masters (with the same upstream SMMU device) can be attached
> to the same primary/non-sva domain, in which case calling
> iommu_attach_device_pasid on one device will write the CD entry for
> both masters. This is still the case even with this patch series, and
> changing this behavior will be the subject of a separate follow-up.
> This is weird, especially since the second master need not even have
> the sva_enabled bit set. This also means that the list of attached
> masters can indeed change between these two calls if that second
> master (not the one used on the iommu_attach_device_pasid call leading
> to this code) is detached/attached at the same time. It's hard for me
> to reason about whether this is safe or not, since this is already
> weird behavior...
I really think the writing of the context descriptors should look atomic;
dropping the lock half way through a failed update and then coming back
to NULL them out definitely isn't correct. So I think you've probably pushed
the locking too far down the stack.
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 6/9] iommu/arm-smmu-v3: Move CD table to arm_smmu_master
2023-08-10 14:34 ` Will Deacon
@ 2023-08-10 14:56 ` Jason Gunthorpe
0 siblings, 0 replies; 45+ messages in thread
From: Jason Gunthorpe @ 2023-08-10 14:56 UTC (permalink / raw)
To: Will Deacon
Cc: Michael Shavit, iommu, linux-arm-kernel, linux-kernel,
robin.murphy, nicolinc, jean-philippe
On Thu, Aug 10, 2023 at 03:34:49PM +0100, Will Deacon wrote:
> On Thu, Aug 10, 2023 at 05:45:03PM +0800, Michael Shavit wrote:
> > On Wed, Aug 9, 2023 at 9:50 PM Will Deacon <will@kernel.org> wrote:
> > >
> > > On Wed, Aug 09, 2023 at 01:12:02AM +0800, Michael Shavit wrote:
> > > > @@ -2203,7 +2186,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain,
> > > > ias = min_t(unsigned long, ias, VA_BITS);
> > > > oas = smmu->ias;
> > > > fmt = ARM_64_LPAE_S1;
> > > > - finalise_stage_fn = arm_smmu_domain_finalise_s1;
> > > > + finalise_stage_fn = arm_smmu_domain_finalise_cd;
> > >
> > > Why is this a better name? Now we have inconsistency with
> > > arm_smmu_domain_finalise_s2().
> >
> > There was a time where s1cfg represented the entire STE and carried
> > the entire cd table. We've gotten rid of s1cfg, and now only store
> > arm_smmu_ctx_desc in the arm_smmu_domain for stage 1 domains.
> > arm_smmu_domain_finalise_cd is IMO more clear, especially given the
> > historical baggage around `s1`.
>
> Ok, but it's the inconsistency I object to. I don't think it's clear at
> all to have arm_smmu_domain_finalise_cd() and arm_smmu_domain_finalise_s2().
>
> The easiest thing is to leave it as-is.
Well the names have become wonky.
arm_smmu_domain_finalise_cd() is filling in the struct
arm_smmu_ctx_desc which is mostly the precomputed value for the CD
table entry, which is mostly redundant copies of the values of the
underlying pgtbl_cfg :\
But I agree keeping it named s1 is more consistent with the naming I
think we should use - domains are called S1 or S2 domains depending on
their IOPTE format.
But arm_smmu_domain_assign_asid/vmid is a generally clearer name for
both :\
Jason
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc
2023-08-10 14:40 ` Will Deacon
@ 2023-08-10 15:39 ` Jason Gunthorpe
2023-08-15 5:20 ` Michael Shavit
0 siblings, 1 reply; 45+ messages in thread
From: Jason Gunthorpe @ 2023-08-10 15:39 UTC (permalink / raw)
To: Will Deacon
Cc: Michael Shavit, iommu, linux-arm-kernel, linux-kernel,
robin.murphy, nicolinc, jean-philippe
On Thu, Aug 10, 2023 at 03:40:52PM +0100, Will Deacon wrote:
> On Thu, Aug 10, 2023 at 05:15:50PM +0800, Michael Shavit wrote:
> > On Wed, Aug 9, 2023 at 9:50 PM Will Deacon <will@kernel.org> wrote:
> > >
> > > > - ret = arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, cd);
> > > > - if (ret)
> > > > + ret = arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, cd);
> > > > + if (ret) {
> > > > + arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, NULL);
> > >
> > > Why is it safe to drop the lock between these two calls?
> >
> > Hmmm this is a tricky question.
> > Tracing through the SVA flow, it seems like there's a scenario where
> > multiple masters (with the same upstream SMMU device) can be attached
> > to the same primary/non-sva domain, in which case calling
> > iommu_attach_device_pasid on one device will write the CD entry for
> > both masters. This is still the case even with this patch series, and
> > changing this behavior will be the subject of a separate follow-up.
> > This is weird, especially since the second master need not even have
> > the sva_enabled bit set. This also means that the list of attached
> > masters can indeed change between these two calls if that second
> > master (not the one used on the iommu_attach_device_pasid call leading
> > to this code) is detached/attached at the same time. It's hard for me
> > to reason about whether this is safe or not, since this is already
> > weird behavior...
>
> I really think the writing of the context descriptors should look atomic;
> dropping the lock half way through a failed update and then coming back
> to NULL them out definitely isn't correct. So I think you've probably pushed
> the locking too far down the stack.
Urk, the issue is that progressive refactorings have left this kind of
wrong.
Basically we always have a singular master we are supposed to be
installing the SVA domain into a PASID for, we just need to load the
CD table entry into that master's existing CD table.
Actually, I don't think this even works as nothing on the PASID path
adds to the list that arm_smmu_write_ctx_desc_devices() iterates over ??
Then the remaining two calls:
arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
arm_smmu_write_ctx_desc_devices(smmu_domain, 0, cd);
This is OK only if the sketchy assumption that the CD
we extracted for a conflicting ASID is not asigned to a PASID.
static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, &quiet_cd);
This doesn't work because we didn't add the master to the list
during __arm_smmu_sva_bind and this path is expressly working
on the PASID binds, not the RID binds.
This is all far too complicated. We really need to get this series:
https://lore.kernel.org/linux-iommu/20230808074944.7825-1-tina.zhang@intel.com/
And rip out all this crazy code in the drivers trying to de-duplicate
the SVA domains. The core code will do it, the driver can assume it
has exactly one SVA domain per mm and do sane and simple things. :(
Maybe for now we just accept that quiet_cd doesn't work, it is a minor
issue and your next series fixes it, right?
Anyhow, something like this will fix what Will pointed to, probably as
an additional prep patch:
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index e3992a0c163779..8e751ba91e810a 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -297,12 +297,6 @@ arm_smmu_mmu_notifier_get(struct arm_smmu_domain *smmu_domain,
goto err_free_cd;
}
- ret = arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, cd);
- if (ret) {
- arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, NULL);
- goto err_put_notifier;
- }
-
list_add(&smmu_mn->list, &smmu_domain->mmu_notifiers);
return smmu_mn;
@@ -325,8 +319,6 @@ static void arm_smmu_mmu_notifier_put(struct arm_smmu_mmu_notifier *smmu_mn)
list_del(&smmu_mn->list);
- arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, NULL);
-
/*
* If we went through clear(), we've already invalidated, and no
* new TLB entry can have been formed.
@@ -342,7 +334,7 @@ static void arm_smmu_mmu_notifier_put(struct arm_smmu_mmu_notifier *smmu_mn)
}
static struct iommu_sva *
-__arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm)
+__arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm, ioasid_t ssid)
{
int ret;
struct arm_smmu_bond *bond;
@@ -375,9 +367,15 @@ __arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm)
goto err_free_bond;
}
+ ret = arm_smmu_write_ctx_desc(master, ssid, bond->smmu_mn->cd);
+ if (ret)
+ goto err_put_notifier;
+
list_add(&bond->list, &master->bonds);
return &bond->sva;
+err_put_notifier:
+ arm_smmu_mmu_notifier_put(bond->smmu_mn);
err_free_bond:
kfree(bond);
return ERR_PTR(ret);
@@ -548,6 +546,7 @@ void arm_smmu_sva_remove_dev_pasid(struct iommu_domain *domain,
if (!WARN_ON(!bond) && refcount_dec_and_test(&bond->refs)) {
list_del(&bond->list);
+ arm_smmu_write_ctx_desc(master, id, NULL);
arm_smmu_mmu_notifier_put(bond->smmu_mn);
kfree(bond);
}
@@ -562,7 +561,7 @@ static int arm_smmu_sva_set_dev_pasid(struct iommu_domain *domain,
struct mm_struct *mm = domain->mm;
mutex_lock(&sva_lock);
- handle = __arm_smmu_sva_bind(dev, mm);
+ handle = __arm_smmu_sva_bind(dev, mm, id);
if (IS_ERR(handle))
ret = PTR_ERR(handle);
mutex_unlock(&sva_lock);
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 45+ messages in thread
* Re: [PATCH v5 8/9] iommu/arm-smmu-v3: Skip cd sync if CD table isn't active
2023-08-10 8:34 ` Michael Shavit
@ 2023-08-10 16:27 ` Will Deacon
0 siblings, 0 replies; 45+ messages in thread
From: Will Deacon @ 2023-08-10 16:27 UTC (permalink / raw)
To: Michael Shavit
Cc: iommu, linux-arm-kernel, linux-kernel, robin.murphy, nicolinc,
jgg, jean-philippe
On Thu, Aug 10, 2023 at 04:34:39PM +0800, Michael Shavit wrote:
> On Wed, Aug 9, 2023 at 9:50 PM Will Deacon <will@kernel.org> wrote:
> >
> > On Wed, Aug 09, 2023 at 01:12:04AM +0800, Michael Shavit wrote:
> > > This commit explicitly keeps track of whether a CD table is installed in
> > > an STE so that arm_smmu_sync_cd can skip the sync when unnecessary. This
> > > was previously achieved through the domain->devices list, but we are
> > > moving to a model where arm_smmu_sync_cd directly operates on a master
> > > and the master's CD table instead of a domain.
> >
> > Why is this path worth optimising?
>
> I have no idea what the practical impact of this optimization is, but
> the motivation here was to make the overall series as close to a nop
> as possible. This optimization existed before but is "broken" by the
> previous patch. This patch restores it.
I'm not sure it's necessary, tbh. It's not like we're calling
arm_smmu_sync_cd() all over the place -- it's used when we're actually
working with the CD.
> > Doesn't this interact badly with the sync in arm_smmu_detach_dev(), which I
> > think happens after zapping the STE?
>
> The arm_smmu_write_ctx_desc call added in arm_smmu_detach_dev() was
> inserted after zapping the STE precisely so that we could skip the
> sync. Is there a concern that a stale CD could be used when the
> CDtable is re-inserted into the STE?
Ah, sorry, I went and looked at the architecture and it says for
CMD_CFGI_STE:
| This command invalidates all Context descriptors (including L1CD)
| that were cached using the given StreamID.
so as long as we make the CD unreachable in the STE before the STE
invalidation (which I think we do by setting the Config field to bypass or
abort), then I agree that we don't need the subsequent CD invalidation.
> > > /*
> > > - * STE is live, and the SMMU might read dwords of this CD in any
> > > + * STE may be live, and the SMMU might read dwords of this CD in any
> > > * order. Ensure that it observes valid values before reading
> > > * V=1.
> > > */
> >
> > Why does this patch need to update this comment?
>
> This is a drive-by to make this comment more accurate. Note how
> (before this patch series) arm_smmu_domain_finalise_s1 explicitly
> mentions that it calls arm_smmu_write_ctx_desc while the STE isn't
> installed yet. Yet this comment asserts the STE *is* live.
Can you do it as its own patch then, please?
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 2/9] iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg
2023-08-10 12:04 ` Jason Gunthorpe
@ 2023-08-10 17:15 ` Michael Shavit
2023-08-10 17:32 ` Jason Gunthorpe
0 siblings, 1 reply; 45+ messages in thread
From: Michael Shavit @ 2023-08-10 17:15 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Will Deacon, iommu, linux-arm-kernel, linux-kernel, robin.murphy,
nicolinc, jean-philippe
> > > What dead code? Is the deal here that we keep the field, but still
> > > infer the value to write from (cd_table->l1_desc == null) in
> > > arm_smmu_write_strtab_ent??
> >
> > Keep the field and write it directly when populating the ste (i.e. don't
> > infer anything), but the field moves into 'struct arm_smmu_ctx_desc_cfg'.
>
> Yes - the 'dead code' is that we introduce storage for a field that is
> always a known constant (STRTAB_STE_0_S1FMT_64K_L2).
I'm not sure we're on the same page here. s1fmt could contain either
`STRTAB_STE_0_S1FMT_64K_L2` or `STRTAB_STE_0_S1FMT_LINEAR`, and this
value will be directly copied in arm_smmu_write_strtab_ent.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 2/9] iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg
2023-08-10 17:15 ` Michael Shavit
@ 2023-08-10 17:32 ` Jason Gunthorpe
0 siblings, 0 replies; 45+ messages in thread
From: Jason Gunthorpe @ 2023-08-10 17:32 UTC (permalink / raw)
To: Michael Shavit
Cc: Will Deacon, iommu, linux-arm-kernel, linux-kernel, robin.murphy,
nicolinc, jean-philippe
On Fri, Aug 11, 2023 at 01:15:14AM +0800, Michael Shavit wrote:
> > > > What dead code? Is the deal here that we keep the field, but still
> > > > infer the value to write from (cd_table->l1_desc == null) in
> > > > arm_smmu_write_strtab_ent??
> > >
> > > Keep the field and write it directly when populating the ste (i.e. don't
> > > infer anything), but the field moves into 'struct arm_smmu_ctx_desc_cfg'.
> >
> > Yes - the 'dead code' is that we introduce storage for a field that is
> > always a known constant (STRTAB_STE_0_S1FMT_64K_L2).
>
> I'm not sure we're on the same page here. s1fmt could contain either
> `STRTAB_STE_0_S1FMT_64K_L2` or `STRTAB_STE_0_S1FMT_LINEAR`, and this
> value will be directly copied in arm_smmu_write_strtab_ent.
Ah, I did not check this closely, Will said:
> But the computation isn't happening -- the STRTAB_STE_0_S1FMT_64K_L2
> constant is hardcoded here.
So the nuanced answer is that computation is happening because today
the format of the CD table (linear vs 64k) is encoded in l1_desc:
+ cd_table->l1_desc ?
+ STRTAB_STE_0_S1FMT_64K_L2 :
+ STRTAB_STE_0_S1FMT_LINEAR);
So I would suggest that along with adding s1fmt to
arm_smmu_ctx_desc_cfg you also go and normalize the usage:
@@ -1030,7 +1030,7 @@ static __le64 *arm_smmu_get_cd_ptr(struct arm_smmu_master *master, u32 ssid)
struct arm_smmu_device *smmu = master->smmu;
struct arm_smmu_ctx_desc_cfg *cd_table = &master->cd_table;
- if (!cd_table->l1_desc)
+ if (cd_table->s1fmt == STRTAB_STE_0_S1FMT_LINEAR)
return cd_table->cdtab + ssid * CTXDESC_CD_DWORDS;
Jason
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc
2023-08-10 9:15 ` Michael Shavit
2023-08-10 14:40 ` Will Deacon
@ 2023-08-15 5:04 ` Michael Shavit
2023-08-15 10:19 ` Will Deacon
1 sibling, 1 reply; 45+ messages in thread
From: Michael Shavit @ 2023-08-15 5:04 UTC (permalink / raw)
To: Will Deacon
Cc: iommu, linux-arm-kernel, linux-kernel, robin.murphy, nicolinc,
jgg, jean-philippe
On Thu, Aug 10, 2023 at 5:15 PM Michael Shavit <mshavit@google.com> wrote:
> On Wed, Aug 9, 2023 at 9:50 PM Will Deacon <will@kernel.org> wrote:
> >
> > Since you're dropping this and relying on the lock being taken higher up
> > callstack, can we add a lockdep assertion that we do actually hold the
> > devices_lock, please?
>
> Will do!
I spoke too soon; the point of this change was to remove the
dependency on the arm_smmu_domain, piping the devices_lock would
defeat this. In fact, this section is really depending on the iommu
group lock not the devices_lock.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc
2023-08-10 15:39 ` Jason Gunthorpe
@ 2023-08-15 5:20 ` Michael Shavit
2023-08-15 11:22 ` Jason Gunthorpe
0 siblings, 1 reply; 45+ messages in thread
From: Michael Shavit @ 2023-08-15 5:20 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Will Deacon, iommu, linux-arm-kernel, linux-kernel, robin.murphy,
nicolinc, jean-philippe
On Thu, Aug 10, 2023 at 11:39 PM Jason Gunthorpe <jgg@nvidia.com> wrote:
>
> Actually, I don't think this even works as nothing on the PASID path
> adds to the list that arm_smmu_write_ctx_desc_devices() iterates over ??
>
> Then the remaining two calls:
>
> arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
> arm_smmu_write_ctx_desc_devices(smmu_domain, 0, cd);
>
> This is OK only if the sketchy assumption that the CD
> we extracted for a conflicting ASID is not asigned to a PASID.
>
> static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
> arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, &quiet_cd);
>
> This doesn't work because we didn't add the master to the list
> during __arm_smmu_sva_bind and this path is expressly working
> on the PASID binds, not the RID binds.
Actually it is working on the RID attached domain (as returned by
iommu_get_domain_for_dev() at sva_bind time) not the SVA domain
here... The arm SVA implementation completely dismisses the SVA handle
(I also have a patch to fix this ;) . Need to find the time to polish
and send out).
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc
2023-08-15 5:04 ` Michael Shavit
@ 2023-08-15 10:19 ` Will Deacon
2023-08-15 11:40 ` Michael Shavit
0 siblings, 1 reply; 45+ messages in thread
From: Will Deacon @ 2023-08-15 10:19 UTC (permalink / raw)
To: Michael Shavit
Cc: iommu, linux-arm-kernel, linux-kernel, robin.murphy, nicolinc,
jgg, jean-philippe
On Tue, Aug 15, 2023 at 01:04:43PM +0800, Michael Shavit wrote:
> On Thu, Aug 10, 2023 at 5:15 PM Michael Shavit <mshavit@google.com> wrote:
> > On Wed, Aug 9, 2023 at 9:50 PM Will Deacon <will@kernel.org> wrote:
> > >
> > > Since you're dropping this and relying on the lock being taken higher up
> > > callstack, can we add a lockdep assertion that we do actually hold the
> > > devices_lock, please?
> >
> > Will do!
>
> I spoke too soon; the point of this change was to remove the
> dependency on the arm_smmu_domain, piping the devices_lock would
> defeat this. In fact, this section is really depending on the iommu
> group lock not the devices_lock.
Sorry, but I'm not following you here. What is the devices_lock protecting
if we're depending on the group lock?
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc
2023-08-15 5:20 ` Michael Shavit
@ 2023-08-15 11:22 ` Jason Gunthorpe
2023-08-15 12:03 ` Michael Shavit
0 siblings, 1 reply; 45+ messages in thread
From: Jason Gunthorpe @ 2023-08-15 11:22 UTC (permalink / raw)
To: Michael Shavit
Cc: Will Deacon, iommu, linux-arm-kernel, linux-kernel, robin.murphy,
nicolinc, jean-philippe
On Tue, Aug 15, 2023 at 01:20:04PM +0800, Michael Shavit wrote:
> On Thu, Aug 10, 2023 at 11:39 PM Jason Gunthorpe <jgg@nvidia.com> wrote:
> >
> > Actually, I don't think this even works as nothing on the PASID path
> > adds to the list that arm_smmu_write_ctx_desc_devices() iterates over ??
> >
> > Then the remaining two calls:
> >
> > arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
> > arm_smmu_write_ctx_desc_devices(smmu_domain, 0, cd);
> >
> > This is OK only if the sketchy assumption that the CD
> > we extracted for a conflicting ASID is not asigned to a PASID.
> >
> > static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
> > arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, &quiet_cd);
> >
> > This doesn't work because we didn't add the master to the list
> > during __arm_smmu_sva_bind and this path is expressly working
> > on the PASID binds, not the RID binds.
>
> Actually it is working on the RID attached domain (as returned by
> iommu_get_domain_for_dev() at sva_bind time) not the SVA domain
> here...
That can't be right, the purpose of that call and arm_smmu_mm_release is to
disable the PASID that is about the UAF the mm's page table.
Jason
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc
2023-08-15 10:19 ` Will Deacon
@ 2023-08-15 11:40 ` Michael Shavit
0 siblings, 0 replies; 45+ messages in thread
From: Michael Shavit @ 2023-08-15 11:40 UTC (permalink / raw)
To: Will Deacon
Cc: iommu, linux-arm-kernel, linux-kernel, robin.murphy, nicolinc,
jgg, jean-philippe
On Tue, Aug 15, 2023 at 6:19 PM Will Deacon <will@kernel.org> wrote:
>
> On Tue, Aug 15, 2023 at 01:04:43PM +0800, Michael Shavit wrote:
> > On Thu, Aug 10, 2023 at 5:15 PM Michael Shavit <mshavit@google.com> wrote:
> > > On Wed, Aug 9, 2023 at 9:50 PM Will Deacon <will@kernel.org> wrote:
> > > >
> > > > Since you're dropping this and relying on the lock being taken higher up
> > > > callstack, can we add a lockdep assertion that we do actually hold the
> > > > devices_lock, please?
> > >
> > > Will do!
> >
> > I spoke too soon; the point of this change was to remove the
> > dependency on the arm_smmu_domain, piping the devices_lock would
> > defeat this. In fact, this section is really depending on the iommu
> > group lock not the devices_lock.
>
> Sorry, but I'm not following you here. What is the devices_lock protecting
> if we're depending on the group lock?
>
> Will
Ugh, yes sorry, we do need the devices_lock held *in the SVA* call
flow. The group lock is ineffective there because SVA performs
cross-master operations on iommu_domain callbacks. There, the
devices_lock is needed to ensure that the list of masters that a
domain is attached to doesn't mutate while we operate on that domain.
Nonetheless, it feels awkward to require the devices_lock to be held
outside SVA, since there we operate on a single master/CD table
rather. We don't care what other masters that domain is attached to.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc
2023-08-15 11:22 ` Jason Gunthorpe
@ 2023-08-15 12:03 ` Michael Shavit
2023-08-15 12:30 ` Jason Gunthorpe
0 siblings, 1 reply; 45+ messages in thread
From: Michael Shavit @ 2023-08-15 12:03 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Will Deacon, iommu, linux-arm-kernel, linux-kernel, robin.murphy,
nicolinc, jean-philippe
On Tue, Aug 15, 2023 at 7:38 PM Jason Gunthorpe <jgg@nvidia.com> wrote:
>
> On Tue, Aug 15, 2023 at 01:20:04PM +0800, Michael Shavit wrote:
> > On Thu, Aug 10, 2023 at 11:39 PM Jason Gunthorpe <jgg@nvidia.com> wrote:
> > >
> > > Actually, I don't think this even works as nothing on the PASID path
> > > adds to the list that arm_smmu_write_ctx_desc_devices() iterates over ??
> > >
> > > Then the remaining two calls:
> > >
> > > arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
> > > arm_smmu_write_ctx_desc_devices(smmu_domain, 0, cd);
> > >
> > > This is OK only if the sketchy assumption that the CD
> > > we extracted for a conflicting ASID is not asigned to a PASID.
> > >
> > > static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
> > > arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, &quiet_cd);
> > >
> > > This doesn't work because we didn't add the master to the list
> > > during __arm_smmu_sva_bind and this path is expressly working
> > > on the PASID binds, not the RID binds.
> >
> > Actually it is working on the RID attached domain (as returned by
> > iommu_get_domain_for_dev() at sva_bind time) not the SVA domain
> > here...
>
> That can't be right, the purpose of that call and arm_smmu_mm_release is to
> disable the PASID that is about the UAF the mm's page table.
>
> Jason
For the sake of this message, let's call "primary domain" whatever RID
domain was attached to a master at the time set_dev_pasid() was called
on that master. That RID domain is locked in while SVA is enabled and
cannot be detached.
The arm-smmu-v3-sva.c implementation creates a mapping between an SVA
domain and this primary domain (through the sva domain's mm). In
arm_smmu_mm_release, the primary domain is looked up and
arm_smmu_write_ctx_desc() is called on all masters that this domain is
attached to.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 6/9] iommu/arm-smmu-v3: Move CD table to arm_smmu_master
2023-08-08 17:12 ` [PATCH v5 6/9] iommu/arm-smmu-v3: Move CD table to arm_smmu_master Michael Shavit
2023-08-09 13:50 ` Will Deacon
@ 2023-08-15 12:10 ` Michael Shavit
1 sibling, 0 replies; 45+ messages in thread
From: Michael Shavit @ 2023-08-15 12:10 UTC (permalink / raw)
To: iommu, linux-arm-kernel, linux-kernel
Cc: will, robin.murphy, nicolinc, jgg, jean-philippe
On Wed, Aug 9, 2023 at 1:15 AM Michael Shavit <mshavit@google.com> wrote:
>
> -static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
> +static int arm_smmu_domain_finalise_cd(struct arm_smmu_domain *smmu_domain,
> struct arm_smmu_master *master,
> struct io_pgtable_cfg *pgtbl_cfg)
> {
> @@ -2115,10 +2110,6 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
> if (ret)
> goto out_unlock;
>
> - ret = arm_smmu_alloc_cd_tables(smmu_domain, master);
> - if (ret)
> - goto out_free_asid;
> -
> cd->asid = (u16)asid;
> cd->ttbr = pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
> cd->tcr = FIELD_PREP(CTXDESC_CD_0_TCR_T0SZ, tcr->tsz) |
> @@ -2130,17 +2121,9 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
> CTXDESC_CD_0_TCR_EPD1 | CTXDESC_CD_0_AA64;
> cd->mair = pgtbl_cfg->arm_lpae_s1_cfg.mair;
>
> - ret = arm_smmu_write_ctx_desc(master, 0, cd);
> - if (ret)
> - goto out_free_cd_tables;
> -
> mutex_unlock(&arm_smmu_asid_lock);
> return 0;
>
> -out_free_cd_tables:
> - arm_smmu_free_cd_tables(smmu_domain);
> -out_free_asid:
> - arm_smmu_free_asid(cd);
> out_unlock:
> mutex_unlock(&arm_smmu_asid_lock);
> return ret;
...
> @@ -2465,6 +2450,22 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> if (smmu_domain->stage != ARM_SMMU_DOMAIN_BYPASS)
> master->ats_enabled = arm_smmu_ats_supported(master);
>
> + if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
> + if (!master->cd_table.cdtab) {
> + ret = arm_smmu_alloc_cd_tables(master);
> + if (ret) {
> + master->domain = NULL;
> + return ret;
> + }
> + }
> +
> + ret = arm_smmu_write_ctx_desc(master, 0, &smmu_domain->cd);
> + if (ret) {
> + master->domain = NULL;
> + return ret;
> + }
> + }
> +
> arm_smmu_install_ste_for_dev(master);
>
> spin_lock_irqsave(&smmu_domain->devices_lock, flags);
> @@ -2472,10 +2473,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
>
> arm_smmu_enable_ats(master);
All this talk of locking on the other thread made me realize there's
an issue here. We are no longer holding the arm_smmu_asid_lock while
arm_smmu_write_ctx_desc is called due to its move out of
arm_smmu_domain_finalise_s1. This can race with arm_smmu_share_asid
which may modify the asid after we've written it, but before we've
updated the CD's smmu_domain->devices list.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc
2023-08-15 12:03 ` Michael Shavit
@ 2023-08-15 12:30 ` Jason Gunthorpe
2023-08-15 12:36 ` Michael Shavit
0 siblings, 1 reply; 45+ messages in thread
From: Jason Gunthorpe @ 2023-08-15 12:30 UTC (permalink / raw)
To: Michael Shavit
Cc: Will Deacon, iommu, linux-arm-kernel, linux-kernel, robin.murphy,
nicolinc, jean-philippe
On Tue, Aug 15, 2023 at 08:03:40PM +0800, Michael Shavit wrote:
> On Tue, Aug 15, 2023 at 7:38 PM Jason Gunthorpe <jgg@nvidia.com> wrote:
> >
> > On Tue, Aug 15, 2023 at 01:20:04PM +0800, Michael Shavit wrote:
> > > On Thu, Aug 10, 2023 at 11:39 PM Jason Gunthorpe <jgg@nvidia.com> wrote:
> > > >
> > > > Actually, I don't think this even works as nothing on the PASID path
> > > > adds to the list that arm_smmu_write_ctx_desc_devices() iterates over ??
> > > >
> > > > Then the remaining two calls:
> > > >
> > > > arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
> > > > arm_smmu_write_ctx_desc_devices(smmu_domain, 0, cd);
> > > >
> > > > This is OK only if the sketchy assumption that the CD
> > > > we extracted for a conflicting ASID is not asigned to a PASID.
> > > >
> > > > static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
> > > > arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, &quiet_cd);
> > > >
> > > > This doesn't work because we didn't add the master to the list
> > > > during __arm_smmu_sva_bind and this path is expressly working
> > > > on the PASID binds, not the RID binds.
> > >
> > > Actually it is working on the RID attached domain (as returned by
> > > iommu_get_domain_for_dev() at sva_bind time) not the SVA domain
> > > here...
> >
> > That can't be right, the purpose of that call and arm_smmu_mm_release is to
> > disable the PASID that is about the UAF the mm's page table.
> >
> > Jason
>
> For the sake of this message, let's call "primary domain" whatever RID
> domain was attached to a master at the time set_dev_pasid() was called
> on that master. That RID domain is locked in while SVA is enabled and
> cannot be detached.
>
> The arm-smmu-v3-sva.c implementation creates a mapping between an SVA
> domain and this primary domain (through the sva domain's mm). In
> arm_smmu_mm_release, the primary domain is looked up and
> arm_smmu_write_ctx_desc() is called on all masters that this domain is
> attached to.
My question is still the same - how does arm_smmu_mm_release update the
Contex descriptor table entry for the *PASID*
The RID on PASID 0 hasn't change and doesn't need updating.
Jason
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc
2023-08-15 12:30 ` Jason Gunthorpe
@ 2023-08-15 12:36 ` Michael Shavit
2023-08-15 12:56 ` Jason Gunthorpe
0 siblings, 1 reply; 45+ messages in thread
From: Michael Shavit @ 2023-08-15 12:36 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Will Deacon, iommu, linux-arm-kernel, linux-kernel, robin.murphy,
nicolinc, jean-philippe
On Tue, Aug 15, 2023 at 8:30 PM Jason Gunthorpe <jgg@nvidia.com> wrote:
>
> On Tue, Aug 15, 2023 at 08:03:40PM +0800, Michael Shavit wrote:
> > On Tue, Aug 15, 2023 at 7:38 PM Jason Gunthorpe <jgg@nvidia.com> wrote:
> > >
> > > On Tue, Aug 15, 2023 at 01:20:04PM +0800, Michael Shavit wrote:
> > > > On Thu, Aug 10, 2023 at 11:39 PM Jason Gunthorpe <jgg@nvidia.com> wrote:
> > > > >
> > > > > Actually, I don't think this even works as nothing on the PASID path
> > > > > adds to the list that arm_smmu_write_ctx_desc_devices() iterates over ??
> > > > >
> > > > > Then the remaining two calls:
> > > > >
> > > > > arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
> > > > > arm_smmu_write_ctx_desc_devices(smmu_domain, 0, cd);
> > > > >
> > > > > This is OK only if the sketchy assumption that the CD
> > > > > we extracted for a conflicting ASID is not asigned to a PASID.
> > > > >
> > > > > static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
> > > > > arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, &quiet_cd);
> > > > >
> > > > > This doesn't work because we didn't add the master to the list
> > > > > during __arm_smmu_sva_bind and this path is expressly working
> > > > > on the PASID binds, not the RID binds.
> > > >
> > > > Actually it is working on the RID attached domain (as returned by
> > > > iommu_get_domain_for_dev() at sva_bind time) not the SVA domain
> > > > here...
> > >
> > > That can't be right, the purpose of that call and arm_smmu_mm_release is to
> > > disable the PASID that is about the UAF the mm's page table.
> > >
> > > Jason
> >
> > For the sake of this message, let's call "primary domain" whatever RID
> > domain was attached to a master at the time set_dev_pasid() was called
> > on that master. That RID domain is locked in while SVA is enabled and
> > cannot be detached.
> >
> > The arm-smmu-v3-sva.c implementation creates a mapping between an SVA
> > domain and this primary domain (through the sva domain's mm). In
> > arm_smmu_mm_release, the primary domain is looked up and
> > arm_smmu_write_ctx_desc() is called on all masters that this domain is
> > attached to.
>
> My question is still the same - how does arm_smmu_mm_release update the
> Contex descriptor table entry for the *PASID*
>
> The RID on PASID 0 hasn't change and doesn't need updating.
>
> Jason
arm_smmu_mm_release looks-up the CD table(s) to write using the
primary domain's device list, and finds the index into those CD
table(s) to write to using mm->pasid.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc
2023-08-15 12:36 ` Michael Shavit
@ 2023-08-15 12:56 ` Jason Gunthorpe
0 siblings, 0 replies; 45+ messages in thread
From: Jason Gunthorpe @ 2023-08-15 12:56 UTC (permalink / raw)
To: Michael Shavit
Cc: Will Deacon, iommu, linux-arm-kernel, linux-kernel, robin.murphy,
nicolinc, jean-philippe
On Tue, Aug 15, 2023 at 08:36:55PM +0800, Michael Shavit wrote:
> On Tue, Aug 15, 2023 at 8:30 PM Jason Gunthorpe <jgg@nvidia.com> wrote:
> >
> > On Tue, Aug 15, 2023 at 08:03:40PM +0800, Michael Shavit wrote:
> > > On Tue, Aug 15, 2023 at 7:38 PM Jason Gunthorpe <jgg@nvidia.com> wrote:
> > > >
> > > > On Tue, Aug 15, 2023 at 01:20:04PM +0800, Michael Shavit wrote:
> > > > > On Thu, Aug 10, 2023 at 11:39 PM Jason Gunthorpe <jgg@nvidia.com> wrote:
> > > > > >
> > > > > > Actually, I don't think this even works as nothing on the PASID path
> > > > > > adds to the list that arm_smmu_write_ctx_desc_devices() iterates over ??
> > > > > >
> > > > > > Then the remaining two calls:
> > > > > >
> > > > > > arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
> > > > > > arm_smmu_write_ctx_desc_devices(smmu_domain, 0, cd);
> > > > > >
> > > > > > This is OK only if the sketchy assumption that the CD
> > > > > > we extracted for a conflicting ASID is not asigned to a PASID.
> > > > > >
> > > > > > static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
> > > > > > arm_smmu_write_ctx_desc_devices(smmu_domain, mm->pasid, &quiet_cd);
> > > > > >
> > > > > > This doesn't work because we didn't add the master to the list
> > > > > > during __arm_smmu_sva_bind and this path is expressly working
> > > > > > on the PASID binds, not the RID binds.
> > > > >
> > > > > Actually it is working on the RID attached domain (as returned by
> > > > > iommu_get_domain_for_dev() at sva_bind time) not the SVA domain
> > > > > here...
> > > >
> > > > That can't be right, the purpose of that call and arm_smmu_mm_release is to
> > > > disable the PASID that is about the UAF the mm's page table.
> > > >
> > > > Jason
> > >
> > > For the sake of this message, let's call "primary domain" whatever RID
> > > domain was attached to a master at the time set_dev_pasid() was called
> > > on that master. That RID domain is locked in while SVA is enabled and
> > > cannot be detached.
> > >
> > > The arm-smmu-v3-sva.c implementation creates a mapping between an SVA
> > > domain and this primary domain (through the sva domain's mm). In
> > > arm_smmu_mm_release, the primary domain is looked up and
> > > arm_smmu_write_ctx_desc() is called on all masters that this domain is
> > > attached to.
> >
> > My question is still the same - how does arm_smmu_mm_release update the
> > Contex descriptor table entry for the *PASID*
> >
> > The RID on PASID 0 hasn't change and doesn't need updating.
> >
> > Jason
>
> arm_smmu_mm_release looks-up the CD table(s) to write using the
> primary domain's device list, and finds the index into those CD
> table(s) to write to using mm->pasid.
Oh.. I don't think I caught that detail that at this point the
arm_smmu_write_ctx_desc_devices() argument must always be the rid
domain. Maybe add a comment to describe that? And lets try to undo
that later :(
Thanks,
Jason
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 45+ messages in thread
end of thread, other threads:[~2023-08-15 12:57 UTC | newest]
Thread overview: 45+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-08 17:11 [PATCH v5 0/9] Refactor the SMMU's CD table ownership Michael Shavit
2023-08-08 17:11 ` [PATCH v5 1/9] iommu/arm-smmu-v3: Move ctx_desc out of s1_cfg Michael Shavit
2023-08-08 17:11 ` [PATCH v5 2/9] iommu/arm-smmu-v3: Replace s1_cfg with cdtab_cfg Michael Shavit
2023-08-09 13:49 ` Will Deacon
2023-08-09 13:59 ` Jason Gunthorpe
2023-08-09 14:55 ` Will Deacon
2023-08-09 15:08 ` Jason Gunthorpe
2023-08-09 16:22 ` Will Deacon
2023-08-09 16:26 ` Jason Gunthorpe
2023-08-09 16:27 ` Will Deacon
2023-08-10 9:33 ` Michael Shavit
2023-08-10 9:43 ` Will Deacon
2023-08-10 12:04 ` Jason Gunthorpe
2023-08-10 17:15 ` Michael Shavit
2023-08-10 17:32 ` Jason Gunthorpe
2023-08-08 17:11 ` [PATCH v5 3/9] iommu/arm-smmu-v3: Encapsulate ctx_desc_cfg init in alloc_cd_tables Michael Shavit
2023-08-08 17:12 ` [PATCH v5 4/9] iommu/arm-smmu-v3: move stall_enabled to the cd table Michael Shavit
2023-08-08 17:12 ` [PATCH v5 5/9] iommu/arm-smmu-v3: Refactor write_ctx_desc Michael Shavit
2023-08-09 13:50 ` Will Deacon
2023-08-10 9:15 ` Michael Shavit
2023-08-10 14:40 ` Will Deacon
2023-08-10 15:39 ` Jason Gunthorpe
2023-08-15 5:20 ` Michael Shavit
2023-08-15 11:22 ` Jason Gunthorpe
2023-08-15 12:03 ` Michael Shavit
2023-08-15 12:30 ` Jason Gunthorpe
2023-08-15 12:36 ` Michael Shavit
2023-08-15 12:56 ` Jason Gunthorpe
2023-08-15 5:04 ` Michael Shavit
2023-08-15 10:19 ` Will Deacon
2023-08-15 11:40 ` Michael Shavit
2023-08-08 17:12 ` [PATCH v5 6/9] iommu/arm-smmu-v3: Move CD table to arm_smmu_master Michael Shavit
2023-08-09 13:50 ` Will Deacon
2023-08-10 9:23 ` Michael Shavit
2023-08-10 14:38 ` Will Deacon
2023-08-10 9:45 ` Michael Shavit
2023-08-10 14:34 ` Will Deacon
2023-08-10 14:56 ` Jason Gunthorpe
2023-08-15 12:10 ` Michael Shavit
2023-08-08 17:12 ` [PATCH v5 7/9] iommu/arm-smmu-v3: Cleanup arm_smmu_domain_finalise Michael Shavit
2023-08-08 17:12 ` [PATCH v5 8/9] iommu/arm-smmu-v3: Skip cd sync if CD table isn't active Michael Shavit
2023-08-09 13:50 ` Will Deacon
2023-08-10 8:34 ` Michael Shavit
2023-08-10 16:27 ` Will Deacon
2023-08-08 17:12 ` [PATCH v5 9/9] iommu/arm-smmu-v3: Rename cdcfg to cd_table Michael Shavit
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).