iommu/io-pgtable: Cleanup and prep for split tables
Subsystems (6)
Robin Murphy
reviewercover iommu/io-pgtable: Cleanup and prep for split tables
Hi all,
Although the io-pgtable-arm formats started out with the notion of being able to provide a complete ready-to-use context for VMSA-compliant users to consume, the reality is that users inevitably still have to make their own adjustments to that context anyway. Worse, though, is that some of that cruft starts actively getting in the way of future work like supporting split tables using both TTBRs.
These patches clean things up by stripping io-pgatble's context back to just the parts directly relevant to what it abstracts, and formalising the expectation that this only forms a basis from which users can construct their own complete context.
Series based on v2 of "Arm SMMU refactoring" here:
https://patchwork.kernel.org/patch/11096263/
Robin.
Robin Murphy (4):
iommu/io-pgtable-arm: Rationalise MAIR handling iommu/io-pgtable-arm: Rationalise TTBRn handling iommu/io-pgtable-arm: Rationalise TCR handling iommu/io-pgtable-arm: Prepare for TTBR1 usage
drivers/iommu/arm-smmu-v3.c | 11 +++-------- drivers/iommu/arm-smmu.c | 14 +++++++------- drivers/iommu/arm-smmu.h | 2 ++ drivers/iommu/io-pgtable-arm-v7s.c | 22 +++++++++------------- drivers/iommu/io-pgtable-arm.c | 23 +++++++++-------------- drivers/iommu/ipmmu-vmsa.c | 4 ++-- drivers/iommu/msm_iommu.c | 4 ++-- drivers/iommu/mtk_iommu.c | 4 ++-- drivers/iommu/qcom_iommu.c | 9 ++++----- include/linux/io-pgtable.h | 6 +++--- 10 files changed, 43 insertions(+), 56 deletions(-)
Signature · 6 lines
2.21.0.dirty _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
reviewerPATCH 1/4 iommu/io-pgtable-arm: Rationalise MAIR handling
Between VMSAv8-64 and the various 32-bit formats, there is either one 64-bit MAIR or a pair of 32-bit MAIR0/MAIR1 or NMRR/PMRR registers. As such, keeping two 64-bit values in io_pgtable_cfg has always been overkill.
--- drivers/iommu/arm-smmu-v3.c | 2 +- drivers/iommu/arm-smmu.c | 4 ++-- drivers/iommu/io-pgtable-arm.c | 5 ++--- drivers/iommu/ipmmu-vmsa.c | 2 +- drivers/iommu/qcom_iommu.c | 4 ++-- include/linux/io-pgtable.h | 2 +- 6 files changed, 9 insertions(+), 10 deletions(-)
drivers/iommu/arm-smmu-v3.c +1 -1
@@ -1724,7 +1724,7 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain, cfg->cd.asid = (u16 )asid; cfg->cd.ttbr = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0 ]; cfg->cd.tcr = pgtbl_cfg->arm_lpae_s1_cfg.tcr; - cfg->cd.mair = pgtbl_cfg->arm_lpae_s1_cfg.mair[0 ]; + cfg->cd.mair = pgtbl_cfg->arm_lpae_s1_cfg.mair;return 0 ; out_free_asid:
drivers/iommu/arm-smmu.c +2 -2
@@ -491,8 +491,8 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain, cb->mair[0 ] = pgtbl_cfg->arm_v7s_cfg.prrr; cb->mair[1 ] = pgtbl_cfg->arm_v7s_cfg.nmrr; }else { - cb->mair[0 ] = pgtbl_cfg->arm_lpae_s1_cfg.mair[0 ]; - cb->mair[1 ] = pgtbl_cfg->arm_lpae_s1_cfg.mair[1 ]; + cb->mair[0 ] = pgtbl_cfg->arm_lpae_s1_cfg.mair; + cb->mair[1 ] = pgtbl_cfg->arm_lpae_s1_cfg.mair >>32 ; } } }
drivers/iommu/io-pgtable-arm.c +2 -3
@@ -859,8 +859,7 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie) (ARM_LPAE_MAIR_ATTR_INC_OWBRWA <<ARM_LPAE_MAIR_ATTR_SHIFT (ARM_LPAE_MAIR_ATTR_IDX_INC_OCACHE )); - cfg->arm_lpae_s1_cfg.mair[0 ] = reg; - cfg->arm_lpae_s1_cfg.mair[1 ] =0 ; + cfg->arm_lpae_s1_cfg.mair = reg;/* Looking good; allocate a pgd */ data->pgd =__arm_lpae_alloc_pages (data->pgd_size,GFP_KERNEL , cfg);
@@ -1024,7 +1023,7 @@ arm_mali_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)u64 mair, ttbr;/* Copy values as union fields overlap */ - mair = cfg->arm_lpae_s1_cfg.mair[0 ]; + mair = cfg->arm_lpae_s1_cfg.mair; ttbr = cfg->arm_lpae_s1_cfg.ttbr[0 ]; cfg->arm_mali_lpae_cfg.memattr = mair;
drivers/iommu/ipmmu-vmsa.c +1 -1
@@ -436,7 +436,7 @@ static void ipmmu_domain_setup_context(struct ipmmu_vmsa_domain *domain)/* MAIR0 */ ipmmu_ctx_write_root (domain,IMMAIR0 , - domain->cfg.arm_lpae_s1_cfg.mair[0 ]); + domain->cfg.arm_lpae_s1_cfg.mair);/* IMBUSCR */ if (domain->mmu->features->setup_imbuscr)
drivers/iommu/qcom_iommu.c +2 -2
@@ -262,9 +262,9 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,/* MAIRs (stage-1 only) */ iommu_writel (ctx,ARM_SMMU_CB_S1_MAIR0 , - pgtbl_cfg.arm_lpae_s1_cfg.mair[0 ]); + pgtbl_cfg.arm_lpae_s1_cfg.mair);iommu_writel (ctx,ARM_SMMU_CB_S1_MAIR1 , - pgtbl_cfg.arm_lpae_s1_cfg.mair[1 ]); + pgtbl_cfg.arm_lpae_s1_cfg.mair >>32 );/* SCTLR */ reg = SCTLR_CFIE | SCTLR_CFRE | SCTLR_AFE | SCTLR_TRE |
include/linux/io-pgtable.h +1 -1
@@ -92,7 +92,7 @@ struct io_pgtable_cfg {struct {u64 ttbr[2 ];u64 tcr; -u64 mair[2 ]; +u64 mair; } arm_lpae_s1_cfg;struct {
Signature · 7 lines
2.21.0.dirty _______________________________________________ linux-arm-kernel mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Robin Murphy
reviewerPATCH 2/4 iommu/io-pgtable-arm: Rationalise TTBRn handling
In reply to Robin MurphyTTBR1 values have so far been redundant since no users implement any support for split address spaces. Crucially, though, one of the main reasons for wanting to do so is to be able to manage each half entirely independently, e.g. context-switching one set of mappings without disturbing the other. Thus it seems unlikely that tying two tables together in a single io_pgtable_cfg would ever be particularly desirable or useful.
Streamline the configs to just a single conceptual TTBR value representing the allocated table. This paves the way for future users to support split address spaces by simply allocating a table and dealing with the detailed TTBRn logistics themselves.
--- drivers/iommu/arm-smmu-v3.c | 2 +- drivers/iommu/arm-smmu.c | 9 ++++----- drivers/iommu/io-pgtable-arm-v7s.c | 16 +++++++--------- drivers/iommu/io-pgtable-arm.c | 7 +++---- drivers/iommu/ipmmu-vmsa.c | 2 +- drivers/iommu/msm_iommu.c | 4 ++-- drivers/iommu/mtk_iommu.c | 4 ++-- drivers/iommu/qcom_iommu.c | 3 +-- include/linux/io-pgtable.h | 4 ++-- 9 files changed, 23 insertions(+), 28 deletions(-)
drivers/iommu/arm-smmu-v3.c +1 -1
@@ -1722,7 +1722,7 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain, } cfg->cd.asid = (u16 )asid; - cfg->cd.ttbr = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0 ]; + cfg->cd.ttbr = pgtbl_cfg->arm_lpae_s1_cfg.ttbr; cfg->cd.tcr = pgtbl_cfg->arm_lpae_s1_cfg.tcr; cfg->cd.mair = pgtbl_cfg->arm_lpae_s1_cfg.mair;return 0 ;
drivers/iommu/arm-smmu.c +4 -5
@@ -473,13 +473,12 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,/* TTBRs */ if (stage1) {if (cfg->fmt ==ARM_SMMU_CTX_FMT_AARCH32_S ) { - cb->ttbr[0 ] = pgtbl_cfg->arm_v7s_cfg.ttbr[0 ]; - cb->ttbr[1 ] = pgtbl_cfg->arm_v7s_cfg.ttbr[1 ]; + cb->ttbr[0 ] = pgtbl_cfg->arm_v7s_cfg.ttbr; + cb->ttbr[1 ] =0 ; }else { - cb->ttbr[0 ] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0 ]; + cb->ttbr[0 ] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr; cb->ttbr[0 ] |=FIELD_PREP (TTBRn_ASID, cfg->asid); - cb->ttbr[1 ] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[1 ]; - cb->ttbr[1 ] |=FIELD_PREP (TTBRn_ASID, cfg->asid); + cb->ttbr[1 ] =FIELD_PREP (TTBRn_ASID, cfg->asid); } }else { cb->ttbr[0 ] = pgtbl_cfg->arm_lpae_s2_cfg.vttbr;
drivers/iommu/io-pgtable-arm-v7s.c +7 -9
@@ -775,15 +775,13 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,/* Ensure the empty pgd is visible before any actual TTBR write */ wmb (); -/* TTBRs */ - cfg->arm_v7s_cfg.ttbr[0 ] =virt_to_phys (data->pgd) | -ARM_V7S_TTBR_S |ARM_V7S_TTBR_NOS | - (cfg->coherent_walk ? - (ARM_V7S_TTBR_IRGN_ATTR (ARM_V7S_RGN_WBWA ) | -ARM_V7S_TTBR_ORGN_ATTR (ARM_V7S_RGN_WBWA )) : - (ARM_V7S_TTBR_IRGN_ATTR (ARM_V7S_RGN_NC ) | -ARM_V7S_TTBR_ORGN_ATTR (ARM_V7S_RGN_NC ))); - cfg->arm_v7s_cfg.ttbr[1 ] =0 ; +/* TTBR */ + cfg->arm_v7s_cfg.ttbr =virt_to_phys (data->pgd) |ARM_V7S_TTBR_S | + (cfg->coherent_walk ? (ARM_V7S_TTBR_NOS | +ARM_V7S_TTBR_IRGN_ATTR (ARM_V7S_RGN_WBWA ) | +ARM_V7S_TTBR_ORGN_ATTR (ARM_V7S_RGN_WBWA )) : + (ARM_V7S_TTBR_IRGN_ATTR (ARM_V7S_RGN_NC ) | +ARM_V7S_TTBR_ORGN_ATTR (ARM_V7S_RGN_NC )));return &data->iop; out_free_data:
drivers/iommu/io-pgtable-arm.c +3 -4
@@ -869,9 +869,8 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)/* Ensure the empty pgd is visible before any actual TTBR write */ wmb (); -/* TTBRs */ - cfg->arm_lpae_s1_cfg.ttbr[0 ] =virt_to_phys (data->pgd); - cfg->arm_lpae_s1_cfg.ttbr[1 ] =0 ; +/* TTBR */ + cfg->arm_lpae_s1_cfg.ttbr =virt_to_phys (data->pgd);return &data->iop; out_free_data:
@@ -1024,7 +1023,7 @@ arm_mali_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)/* Copy values as union fields overlap */ mair = cfg->arm_lpae_s1_cfg.mair; - ttbr = cfg->arm_lpae_s1_cfg.ttbr[0 ]; + ttbr = cfg->arm_lpae_s1_cfg.ttbr; cfg->arm_mali_lpae_cfg.memattr = mair; cfg->arm_mali_lpae_cfg.transtab = ttbr |
drivers/iommu/ipmmu-vmsa.c +1 -1
@@ -416,7 +416,7 @@ static void ipmmu_domain_setup_context(struct ipmmu_vmsa_domain *domain)u32 tmp;/* TTBR0 */ - ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr[0 ]; + ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr;ipmmu_ctx_write_root (domain,IMTTLBR0 , ttbr);ipmmu_ctx_write_root (domain,IMTTUBR0 , ttbr >>32 );
drivers/iommu/msm_iommu.c +2 -2
@@ -270,8 +270,8 @@ static void __program_context(void __iomem *base, int ctx,SET_V2PCFG (base, ctx,0x3 );SET_TTBCR (base, ctx, priv->cfg.arm_v7s_cfg.tcr); -SET_TTBR0 (base, ctx, priv->cfg.arm_v7s_cfg.ttbr[0 ]); -SET_TTBR1 (base, ctx, priv->cfg.arm_v7s_cfg.ttbr[1 ]); +SET_TTBR0 (base, ctx, priv->cfg.arm_v7s_cfg.ttbr); +SET_TTBR1 (base, ctx,0 );/* Set prrr and nmrr */ SET_PRRR (base, ctx, priv->cfg.arm_v7s_cfg.prrr);
drivers/iommu/mtk_iommu.c +2 -2
@@ -336,7 +336,7 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,/* Update the pgtable base address register of the M4U HW */ if (!data->m4u_dom) { data->m4u_dom = dom; -writel (dom->cfg.arm_v7s_cfg.ttbr[0 ], +writel (dom->cfg.arm_v7s_cfg.ttbr, data->base +REG_MMU_PT_BASE_ADDR ); }
@@ -723,7 +723,7 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)writel_relaxed (reg->int_main_control, base +REG_MMU_INT_MAIN_CONTROL );writel_relaxed (reg->ivrp_paddr, base +REG_MMU_IVRP_PADDR );if (data->m4u_dom) -writel (data->m4u_dom->cfg.arm_v7s_cfg.ttbr[0 ], +writel (data->m4u_dom->cfg.arm_v7s_cfg.ttbr, base +REG_MMU_PT_BASE_ADDR );return 0 ; }
drivers/iommu/qcom_iommu.c +1 -2
@@ -247,10 +247,9 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,/* TTBRs */ iommu_writeq (ctx,ARM_SMMU_CB_TTBR0 , - pgtbl_cfg.arm_lpae_s1_cfg.ttbr[0 ] | + pgtbl_cfg.arm_lpae_s1_cfg.ttbr |FIELD_PREP (TTBRn_ASID, ctx->asid));iommu_writeq (ctx,ARM_SMMU_CB_TTBR1 , - pgtbl_cfg.arm_lpae_s1_cfg.ttbr[1 ] |FIELD_PREP (TTBRn_ASID, ctx->asid));/* TCR */
include/linux/io-pgtable.h +2 -2
@@ -90,7 +90,7 @@ struct io_pgtable_cfg {/* Low-level data specific to the table format */ union {struct { -u64 ttbr[2 ]; +u64 ttbr;u64 tcr;u64 mair; } arm_lpae_s1_cfg;
@@ -101,7 +101,7 @@ struct io_pgtable_cfg { } arm_lpae_s2_cfg;struct { -u32 ttbr[2 ]; +u32 ttbr;u32 tcr;u32 nmrr;u32 prrr;
Signature · 6 lines
2.21.0.dirty _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Will Deacon
maintainerRe: [PATCH 2/4] iommu/io-pgtable-arm: Rationalise TTBRn handling
Quoted 48 lines · Robin Murphy
TTBR1 values have so far been redundant since no users implement any support for split address spaces. Crucially, though, one of the main reasons for wanting to do so is to be able to manage each half entirely independently, e.g. context-switching one set of mappings without disturbing the other. Thus it seems unlikely that tying two tables together in a single
io_pgtable_cfgwould ever be particularly desirable or useful.Streamline the configs to just a single conceptual TTBR value representing the allocated table. This paves the way for future users to support split address spaces by simply allocating a table and dealing with the detailed TTBRn logistics themselves.
Signed-off-by Robin Murphy <[email protected]>--- drivers/iommu/arm-smmu-v3.c | 2 +- drivers/iommu/arm-smmu.c | 9 ++++----- drivers/iommu/io-pgtable-arm-v7s.c | 16 +++++++--------- drivers/iommu/io-pgtable-arm.c | 7 +++---- drivers/iommu/ipmmu-vmsa.c | 2 +- drivers/iommu/msm_iommu.c | 4 ++-- drivers/iommu/mtk_iommu.c | 4 ++-- drivers/iommu/qcom_iommu.c | 3 +-- include/linux/io-pgtable.h | 4 ++-- 9 files changed, 23 insertions(+), 28 deletions(-)drivers/iommu/arm-smmu-v3.c +1
-1@@ -1722,7 +1722,7 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain, } cfg->cd.asid = (u16 )asid; - cfg->cd.ttbr = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0 ]; + cfg->cd.ttbr = pgtbl_cfg->arm_lpae_s1_cfg.ttbr; cfg->cd.tcr = pgtbl_cfg->arm_lpae_s1_cfg.tcr; cfg->cd.mair = pgtbl_cfg->arm_lpae_s1_cfg.mair;return 0 ;drivers/iommu/arm-smmu.c +0
-1@@ -473,13 +473,12 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,/* TTBRs */ if (stage1) {if (cfg->fmt ==ARM_SMMU_CTX_FMT_AARCH32_S ) { - cb->ttbr[0 ] = pgtbl_cfg->arm_v7s_cfg.ttbr[0 ];
drivers/iommu/arm-smmu.c static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain, · line 481
Quoted 10 lines
drivers/iommu/arm-smmu.c +4
-4- cb->ttbr[1 ] = pgtbl_cfg->arm_v7s_cfg.ttbr[1 ]; + cb->ttbr[0 ] = pgtbl_cfg->arm_v7s_cfg.ttbr; + cb->ttbr[1 ] =0 ; }else { - cb->ttbr[0 ] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0 ]; + cb->ttbr[0 ] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr; cb->ttbr[0 ] |=FIELD_PREP (TTBRn_ASID, cfg->asid); - cb->ttbr[1 ] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[1 ]; - cb->ttbr[1 ] |=FIELD_PREP (TTBRn_ASID, cfg->asid); + cb->ttbr[1 ] =FIELD_PREP (TTBRn_ASID, cfg->asid);
Why do you continue to put the ASID in here?
Quoted 5 lines
drivers/iommu/qcom_iommu.c +0
-0
drivers/iommu/qcom_iommu.c static int qcom_iommu_init_domain(struct iommu_domain *domain, · line 253
Quoted 9 lines
drivers/iommu/qcom_iommu.c +1
-2@@ -247,10 +247,9 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,/* TTBRs */ iommu_writeq (ctx,ARM_SMMU_CB_TTBR0 , - pgtbl_cfg.arm_lpae_s1_cfg.ttbr[0 ] | + pgtbl_cfg.arm_lpae_s1_cfg.ttbr |FIELD_PREP (TTBRn_ASID, ctx->asid));iommu_writeq (ctx,ARM_SMMU_CB_TTBR1 , - pgtbl_cfg.arm_lpae_s1_cfg.ttbr[1 ] |FIELD_PREP (TTBRn_ASID, ctx->asid));
Same here.
Quoted 14 lines
include/linux/io-pgtable.h +1
-1@@ -90,7 +90,7 @@ struct io_pgtable_cfg {/* Low-level data specific to the table format */ union {struct { -u64 ttbr[2 ]; +u64 ttbr;u64 tcr;u64 mair; } arm_lpae_s1_cfg;
include/linux/io-pgtable.h struct io_pgtable_cfg { · line 104
Quoted 5 lines
include/linux/io-pgtable.h +1
-1@@ -101,7 +101,7 @@ struct io_pgtable_cfg { } arm_lpae_s2_cfg;struct { -u32 ttbr[2 ]; +u32 ttbr;
We could probably do with a comment for these 'ttbr' field now saying that they refer to ttbr0 (since the tcr will have EPD1 set).
Will
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
reviewerRe: [PATCH 2/4] iommu/io-pgtable-arm: Rationalise TTBRn handling
Quoted 53 lines · Will Deacon
Quoted 52 lines · Robin Murphy
TTBR1 values have so far been redundant since no users implement any support for split address spaces. Crucially, though, one of the main reasons for wanting to do so is to be able to manage each half entirely independently, e.g. context-switching one set of mappings without disturbing the other. Thus it seems unlikely that tying two tables together in a single
io_pgtable_cfgwould ever be particularly desirable or useful.Streamline the configs to just a single conceptual TTBR value representing the allocated table. This paves the way for future users to support split address spaces by simply allocating a table and dealing with the detailed TTBRn logistics themselves.
Signed-off-by Robin Murphy <[email protected]>--- drivers/iommu/arm-smmu-v3.c | 2 +- drivers/iommu/arm-smmu.c | 9 ++++----- drivers/iommu/io-pgtable-arm-v7s.c | 16 +++++++--------- drivers/iommu/io-pgtable-arm.c | 7 +++---- drivers/iommu/ipmmu-vmsa.c | 2 +- drivers/iommu/msm_iommu.c | 4 ++-- drivers/iommu/mtk_iommu.c | 4 ++-- drivers/iommu/qcom_iommu.c | 3 +-- include/linux/io-pgtable.h | 4 ++-- 9 files changed, 23 insertions(+), 28 deletions(-)drivers/iommu/arm-smmu-v3.c +1
-1@@ -1722,7 +1722,7 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain, } cfg->cd.asid = (u16 )asid; - cfg->cd.ttbr = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0 ]; + cfg->cd.ttbr = pgtbl_cfg->arm_lpae_s1_cfg.ttbr; cfg->cd.tcr = pgtbl_cfg->arm_lpae_s1_cfg.tcr; cfg->cd.mair = pgtbl_cfg->arm_lpae_s1_cfg.mair;return 0 ;drivers/iommu/arm-smmu.c +2
-2@@ -473,13 +473,12 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,/* TTBRs */ if (stage1) {if (cfg->fmt ==ARM_SMMU_CTX_FMT_AARCH32_S ) { - cb->ttbr[0 ] = pgtbl_cfg->arm_v7s_cfg.ttbr[0 ]; - cb->ttbr[1 ] = pgtbl_cfg->arm_v7s_cfg.ttbr[1 ]; + cb->ttbr[0 ] = pgtbl_cfg->arm_v7s_cfg.ttbr; + cb->ttbr[1 ] =0 ; }else {
Quoted 8 lines
drivers/iommu/arm-smmu.c static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain, · line 481
Quoted 6 lines
drivers/iommu/arm-smmu.c +2
-3- cb->ttbr[0 ] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0 ]; + cb->ttbr[0 ] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr; cb->ttbr[0 ] |=FIELD_PREP (TTBRn_ASID, cfg->asid); - cb->ttbr[1 ] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[1 ]; - cb->ttbr[1 ] |=FIELD_PREP (TTBRn_ASID, cfg->asid); + cb->ttbr[1 ] =FIELD_PREP (TTBRn_ASID, cfg->asid);Why do you continue to put the ASID in here?
For the same reason we put it there before ;)
Although I guess if TCR.A1 were ever to get flipped accidentally then we're still cool.
Quoted 33 lines
Quoted 5 lines
drivers/iommu/qcom_iommu.c +0
-0drivers/iommu/qcom_iommu.c static int qcom_iommu_init_domain(struct iommu_domain *domain, · line 253
Quoted 9 lines
drivers/iommu/qcom_iommu.c +1
-2@@ -247,10 +247,9 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,/* TTBRs */ iommu_writeq (ctx,ARM_SMMU_CB_TTBR0 , - pgtbl_cfg.arm_lpae_s1_cfg.ttbr[0 ] | + pgtbl_cfg.arm_lpae_s1_cfg.ttbr |FIELD_PREP (TTBRn_ASID, ctx->asid));iommu_writeq (ctx,ARM_SMMU_CB_TTBR1 , - pgtbl_cfg.arm_lpae_s1_cfg.ttbr[1 ] |FIELD_PREP (TTBRn_ASID, ctx->asid));Same here.
Quoted 16 lines
include/linux/io-pgtable.h +1
-1@@ -90,7 +90,7 @@ struct io_pgtable_cfg {/* Low-level data specific to the table format */ union {struct { -u64 ttbr[2 ]; +u64 ttbr;u64 tcr;u64 mair; } arm_lpae_s1_cfg;@@ -101,7 +101,7 @@ struct io_pgtable_cfg { } arm_lpae_s2_cfg;
Quoted 6 lines
include/linux/io-pgtable.h struct io_pgtable_cfg { · line 104
Quoted 3 lines
include/linux/io-pgtable.h +1
-1struct { -u32 ttbr[2 ]; +u32 ttbr;We could probably do with a comment for these 'ttbr' field now saying that they refer to ttbr0 (since the tcr will have EPD1 set).
Yeah, I did wonder whether this might want elaboration, or whether the commit messages plus the code consuming it made the idea sufficiently clear - I guess that's my answer...
Robin.
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Will Deacon
maintainerRe: [PATCH 2/4] iommu/io-pgtable-arm: Rationalise TTBRn handling
Quoted 62 lines · Robin Murphy
Quoted 52 lines · Will Deacon
Quoted 51 lines · Robin Murphy
TTBR1 values have so far been redundant since no users implement any support for split address spaces. Crucially, though, one of the main reasons for wanting to do so is to be able to manage each half entirely independently, e.g. context-switching one set of mappings without disturbing the other. Thus it seems unlikely that tying two tables together in a single
io_pgtable_cfgwould ever be particularly desirable or useful.Streamline the configs to just a single conceptual TTBR value representing the allocated table. This paves the way for future users to support split address spaces by simply allocating a table and dealing with the detailed TTBRn logistics themselves.
Signed-off-by Robin Murphy <[email protected]>--- drivers/iommu/arm-smmu-v3.c | 2 +- drivers/iommu/arm-smmu.c | 9 ++++----- drivers/iommu/io-pgtable-arm-v7s.c | 16 +++++++--------- drivers/iommu/io-pgtable-arm.c | 7 +++---- drivers/iommu/ipmmu-vmsa.c | 2 +- drivers/iommu/msm_iommu.c | 4 ++-- drivers/iommu/mtk_iommu.c | 4 ++-- drivers/iommu/qcom_iommu.c | 3 +-- include/linux/io-pgtable.h | 4 ++-- 9 files changed, 23 insertions(+), 28 deletions(-)drivers/iommu/arm-smmu-v3.c +1
-1@@ -1722,7 +1722,7 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain, } cfg->cd.asid = (u16 )asid; - cfg->cd.ttbr = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0 ]; + cfg->cd.ttbr = pgtbl_cfg->arm_lpae_s1_cfg.ttbr; cfg->cd.tcr = pgtbl_cfg->arm_lpae_s1_cfg.tcr; cfg->cd.mair = pgtbl_cfg->arm_lpae_s1_cfg.mair;return 0 ;drivers/iommu/arm-smmu.c +2
-2@@ -473,13 +473,12 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,/* TTBRs */ if (stage1) {if (cfg->fmt ==ARM_SMMU_CTX_FMT_AARCH32_S ) { - cb->ttbr[0 ] = pgtbl_cfg->arm_v7s_cfg.ttbr[0 ]; - cb->ttbr[1 ] = pgtbl_cfg->arm_v7s_cfg.ttbr[1 ]; + cb->ttbr[0 ] = pgtbl_cfg->arm_v7s_cfg.ttbr; + cb->ttbr[1 ] =0 ; }else {Quoted 8 lines
drivers/iommu/arm-smmu.c static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain, · line 481
Quoted 6 lines
drivers/iommu/arm-smmu.c +2
-3- cb->ttbr[0 ] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0 ]; + cb->ttbr[0 ] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr; cb->ttbr[0 ] |=FIELD_PREP (TTBRn_ASID, cfg->asid); - cb->ttbr[1 ] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[1 ]; - cb->ttbr[1 ] |=FIELD_PREP (TTBRn_ASID, cfg->asid); + cb->ttbr[1 ] =FIELD_PREP (TTBRn_ASID, cfg->asid);Why do you continue to put the ASID in here?
Quoted 4 lines
For the same reason we put it there before ;)
Although I guess if TCR.A1 were ever to get flipped accidentally then we're still cool.
Hmm, but we don't do this for other drivers, so I'd be inclined to zap it with 0 for consistency.
Will
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
reviewerPATCH 3/4 iommu/io-pgtable-arm: Rationalise TCR handling
In reply to Robin MurphyAlthough it's conceptually nice for the io_pgtable_cfg to provide a standard VMSA TCR value, the reality is that no VMSA-compliant IOMMU looks exactly like an Arm CPU, and they all have various other TCR controls which io-pgtable can't be expected to understand. Thus since there is an expectation that drivers will have to add to the given TCR value anyway, let's strip it down to just the essentials that are directly relevant to io-pgatble's inner workings - namely the address sizes, walk attributes, and where appropriate, format selection.
--- drivers/iommu/arm-smmu-v3.c | 7 +------ drivers/iommu/arm-smmu.c | 1 + drivers/iommu/arm-smmu.h | 2 ++ drivers/iommu/io-pgtable-arm-v7s.c | 6 ++---- drivers/iommu/io-pgtable-arm.c | 4 ---- drivers/iommu/qcom_iommu.c | 2 +- 6 files changed, 7 insertions(+), 15 deletions(-)
drivers/iommu/arm-smmu-v3.c +1 -6
@@ -270,9 +270,7 @@#define CTXDESC_CD_0_TCR_SH0 GENMASK_ULL(13, 12)#define ARM64_TCR_SH0 GENMASK_ULL(13, 12)#define CTXDESC_CD_0_TCR_EPD0 (1ULL << 14) -#define ARM64_TCR_EPD0 (1ULL << 7)#define CTXDESC_CD_0_TCR_EPD1 (1ULL << 30) -#define ARM64_TCR_EPD1 (1ULL << 23)#define CTXDESC_CD_0_ENDI (1UL << 15)#define CTXDESC_CD_0_V (1UL << 31)
@@ -280,7 +278,6 @@#define CTXDESC_CD_0_TCR_IPS GENMASK_ULL(34, 32)#define ARM64_TCR_IPS GENMASK_ULL(34, 32)#define CTXDESC_CD_0_TCR_TBI0 (1ULL << 38) -#define ARM64_TCR_TBI0 (1ULL << 37)#define CTXDESC_CD_0_AA64 (1UL << 41)#define CTXDESC_CD_0_S (1UL << 44)
@@ -1064,8 +1061,6 @@ static u64 arm_smmu_cpu_tcr_to_cd(u64 tcr) val |=ARM_SMMU_TCR2CD (tcr,IRGN0 ); val |=ARM_SMMU_TCR2CD (tcr,ORGN0 ); val |=ARM_SMMU_TCR2CD (tcr,SH0 ); - val |=ARM_SMMU_TCR2CD (tcr,EPD0 ); - val |=ARM_SMMU_TCR2CD (tcr,EPD1 ); val |=ARM_SMMU_TCR2CD (tcr,IPS );return val;
@@ -1086,7 +1081,7 @@ static void arm_smmu_write_ctx_desc(struct arm_smmu_device *smmu,#endif CTXDESC_CD_0_R |CTXDESC_CD_0_A |CTXDESC_CD_0_ASET |CTXDESC_CD_0_AA64 |FIELD_PREP (CTXDESC_CD_0_ASID , cfg->cd.asid) | -CTXDESC_CD_0_V ; +CTXDESC_CD_0_V |CTXDESC_CD_0_TCR_EPD1 ;/* STALL_MODEL==0b10 && CD.S==0 is ILLEGAL */ if (smmu->features &ARM_SMMU_FEAT_STALL_FORCE )
drivers/iommu/arm-smmu.c +1 -0
@@ -461,6 +461,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain, cb->tcr[0 ] = pgtbl_cfg->arm_v7s_cfg.tcr; }else { cb->tcr[0 ] = pgtbl_cfg->arm_lpae_s1_cfg.tcr; + cb->tcr[0 ] |=TCR_EPD1 ; cb->tcr[1 ] = pgtbl_cfg->arm_lpae_s1_cfg.tcr >>32 ; cb->tcr[1 ] |=FIELD_PREP (TCR2_SEP ,TCR2_SEP_UPSTREAM );if (cfg->fmt ==ARM_SMMU_CTX_FMT_AARCH64 )
drivers/iommu/arm-smmu.h +2 -0
@@ -162,6 +162,8 @@ enum arm_smmu_cbar_type {#define TTBRn_ASID GENMASK_ULL(63, 48)#define ARM_SMMU_CB_TCR 0x30 +#define TCR_EPD1 BIT(23) +#define ARM_SMMU_CB_CONTEXTIDR 0x34#define ARM_SMMU_CB_S1_MAIR0 0x38#define ARM_SMMU_CB_S1_MAIR1 0x3c
drivers/iommu/io-pgtable-arm-v7s.c +2 -4
@@ -147,8 +147,6 @@#define ARM_V7S_TTBR_IRGN_ATTR (attr) \ ((((attr) & 0x1) << 6) | (((attr) & 0x2) >> 1)) -#define ARM_V7S_TCR_PD1 BIT(5) -#ifdef CONFIG_ZONE_DMA32 #define ARM_V7S_TABLE_GFP_DMA GFP_DMA32#define ARM_V7S_TABLE_SLAB_FLAGS SLAB_CACHE_DMA32
@@ -751,8 +749,8 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,*/ cfg->pgsize_bitmap &=SZ_4K |SZ_64K |SZ_1M |SZ_16M ; -/* TCR: T0SZ=0, disable TTBR1 */ - cfg->arm_v7s_cfg.tcr =ARM_V7S_TCR_PD1 ; +/* TCR: T0SZ=0, EAE=0 (if applicable) */ + cfg->arm_v7s_cfg.tcr =0 ;/* * TEX remap: the indices used map to the closest equivalent types
drivers/iommu/io-pgtable-arm.c +0 -4
@@ -112,8 +112,6 @@#define ARM_32_LPAE_TCR_EAE (1 << 31)#define ARM_64_LPAE_S2_TCR_RES1 (1 << 31) -#define ARM_LPAE_TCR_EPD1 (1 << 23) -#define ARM_LPAE_TCR_TG0_4K (0 << 14)#define ARM_LPAE_TCR_TG0_64K (1 << 14)#define ARM_LPAE_TCR_TG0_16K (2 << 14)
@@ -845,8 +843,6 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie) reg |= (64ULL - cfg->ias) <<ARM_LPAE_TCR_T0SZ_SHIFT ; -/* Disable speculative walks through TTBR1 */ - reg |=ARM_LPAE_TCR_EPD1 ; cfg->arm_lpae_s1_cfg.tcr = reg;/* MAIRs */
drivers/iommu/qcom_iommu.c +1 -1
@@ -257,7 +257,7 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, (pgtbl_cfg.arm_lpae_s1_cfg.tcr >>32 ) | FIELD_PREP(TCR2_SEP, TCR2_SEP_UPSTREAM));iommu_writel (ctx,ARM_SMMU_CB_TCR , - pgtbl_cfg.arm_lpae_s1_cfg.tcr); + pgtbl_cfg.arm_lpae_s1_cfg.tcr |TCR_EPD1 );/* MAIRs (stage-1 only) */ iommu_writel(ctx, ARM_SMMU_CB_S1_MAIR0,
Signature · 6 lines
2.21.0.dirty _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Will Deacon
maintainerRe: [PATCH 3/4] iommu/io-pgtable-arm: Rationalise TCR handling
Quoted 10 lines · Robin Murphy
Although it's conceptually nice for the
io_pgtable_cfgto provide a standard VMSA TCR value, the reality is that no VMSA-compliant IOMMU looks exactly like an Arm CPU, and they all have various other TCR controls which io-pgtable can't be expected to understand. Thus since there is an expectation that drivers will have to add to the given TCR value anyway, let's strip it down to just the essentials that are directly relevant to io-pgatble's inner workings - namely the address sizes, walk attributes, and where appropriate, format selection.Signed-off-by Robin Murphy <[email protected]>
Quoted 8 lines
--- drivers/iommu/arm-smmu-v3.c | 7 +------ drivers/iommu/arm-smmu.c | 1 + drivers/iommu/arm-smmu.h | 2 ++ drivers/iommu/io-pgtable-arm-v7s.c | 6 ++---- drivers/iommu/io-pgtable-arm.c | 4 ---- drivers/iommu/qcom_iommu.c | 2 +- 6 files changed, 7 insertions(+), 15 deletions(-)
Hmm, so I'm a bit nervous about this one since I think we really should be providing a TCR with EPD1 set if we're only giving you TTBR0. Relying on the driver to do this worries me. See my comments on the next patch.
Will
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
reviewerRe: [PATCH 3/4] iommu/io-pgtable-arm: Rationalise TCR handling
Quoted 20 lines · Will Deacon
Quoted 10 lines · Robin Murphy
Although it's conceptually nice for the
io_pgtable_cfgto provide a standard VMSA TCR value, the reality is that no VMSA-compliant IOMMU looks exactly like an Arm CPU, and they all have various other TCR controls which io-pgtable can't be expected to understand. Thus since there is an expectation that drivers will have to add to the given TCR value anyway, let's strip it down to just the essentials that are directly relevant to io-pgatble's inner workings - namely the address sizes, walk attributes, and where appropriate, format selection.Signed-off-by Robin Murphy <[email protected]>Quoted 8 lines
--- drivers/iommu/arm-smmu-v3.c | 7 +------ drivers/iommu/arm-smmu.c | 1 + drivers/iommu/arm-smmu.h | 2 ++ drivers/iommu/io-pgtable-arm-v7s.c | 6 ++---- drivers/iommu/io-pgtable-arm.c | 4 ---- drivers/iommu/qcom_iommu.c | 2 +- 6 files changed, 7 insertions(+), 15 deletions(-)
Quoted 3 lines
Hmm, so I'm a bit nervous about this one since I think we really should be providing a TCR with EPD1 set if we're only giving you TTBR0. Relying on the driver to do this worries me. See my comments on the next patch.
The whole idea is that we already know we can't provide a *complete* TCR value (not least because anything above bit 31 is the wild west), thus there's really no point in io-pgtable trying to provide anything other than the parts it definitely controls. It makes sense to provide this partial TCR value "as if" for TTBR0, since that's the most common case, but ultimately io-pgatble doesn't know (or need to) which TTBR the caller intends to actually use for this table. Even if the caller *is* allocating it for TTBR0, io-pgtable doesn't know that they haven't got something live in TTBR1 already, so it still wouldn't be in a position to make the EPD1 call either way.
Ultimately, it's the IOMMU drivers who decide what they put in which TTBR, so it's the IOMMU drivers which have to take responsibility for EPD*. Sure you can worry about it, but you can equally worry about them them misprogramming the ASID or anything else...
Robin.
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Will Deacon
maintainerRe: [PATCH 3/4] iommu/io-pgtable-arm: Rationalise TCR handling
Quoted 25 lines · Robin Murphy
Quoted 20 lines · Will Deacon
Quoted 10 lines · Robin Murphy
Although it's conceptually nice for the
io_pgtable_cfgto provide a standard VMSA TCR value, the reality is that no VMSA-compliant IOMMU looks exactly like an Arm CPU, and they all have various other TCR controls which io-pgtable can't be expected to understand. Thus since there is an expectation that drivers will have to add to the given TCR value anyway, let's strip it down to just the essentials that are directly relevant to io-pgatble's inner workings - namely the address sizes, walk attributes, and where appropriate, format selection.Signed-off-by Robin Murphy <[email protected]>Quoted 8 lines
--- drivers/iommu/arm-smmu-v3.c | 7 +------ drivers/iommu/arm-smmu.c | 1 + drivers/iommu/arm-smmu.h | 2 ++ drivers/iommu/io-pgtable-arm-v7s.c | 6 ++---- drivers/iommu/io-pgtable-arm.c | 4 ---- drivers/iommu/qcom_iommu.c | 2 +- 6 files changed, 7 insertions(+), 15 deletions(-)Quoted 3 lines
Hmm, so I'm a bit nervous about this one since I think we really should be providing a TCR with EPD1 set if we're only giving you TTBR0. Relying on the driver to do this worries me. See my comments on the next patch.
Quoted 10 lines
The whole idea is that we already know we can't provide a *complete* TCR value (not least because anything above bit 31 is the wild west), thus there's really no point in io-pgtable trying to provide anything other than the parts it definitely controls. It makes sense to provide this partial TCR value "as if" for TTBR0, since that's the most common case, but ultimately io-pgatble doesn't know (or need to) which TTBR the caller intends to actually use for this table. Even if the caller *is* allocating it for TTBR0, io-pgtable doesn't know that they haven't got something live in TTBR1 already, so it still wouldn't be in a position to make the EPD1 call either way.
Ok, but the driver can happily rewrite/ignore what it gets back. I suppose an alternative would be scrapped the 'u64 tcr' and instead having a bunch of named bitfields for the stuff we're actually providing, although I'd still like EPDx to be in there.
Quoted 4 lines
Ultimately, it's the IOMMU drivers who decide what they put in which TTBR, so it's the IOMMU drivers which have to take responsibility for EPD*. Sure you can worry about it, but you can equally worry about them them misprogramming the ASID or anything else...
I find the EPDx bits particularly dangerous because:
- They're easily overlooked
- Clobbering TTBR1 with 0x0 doesn't disable walks via TTBR1 as you might reasonably expect
- If you do the above without EPD, the breakage will be subtle
and given that I don't see any real downsides to us providing a default TCR value with EPD set appropriately, then I think we should do that. I'd be happy to revisit the decision later on if it's getting the way of a real use-case, but it feels like we're throwing the baby out with the bathwater at the moment and I'd rather do this incrementally based on actual need.
Will
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
reviewerRe: [PATCH 3/4] iommu/io-pgtable-arm: Rationalise TCR handling
Quoted 37 lines · Will Deacon
Quoted 25 lines · Robin Murphy
Quoted 20 lines · Will Deacon
Quoted 10 lines · Robin Murphy
Although it's conceptually nice for the
io_pgtable_cfgto provide a standard VMSA TCR value, the reality is that no VMSA-compliant IOMMU looks exactly like an Arm CPU, and they all have various other TCR controls which io-pgtable can't be expected to understand. Thus since there is an expectation that drivers will have to add to the given TCR value anyway, let's strip it down to just the essentials that are directly relevant to io-pgatble's inner workings - namely the address sizes, walk attributes, and where appropriate, format selection.Signed-off-by Robin Murphy <[email protected]>Quoted 8 lines
--- drivers/iommu/arm-smmu-v3.c | 7 +------ drivers/iommu/arm-smmu.c | 1 + drivers/iommu/arm-smmu.h | 2 ++ drivers/iommu/io-pgtable-arm-v7s.c | 6 ++---- drivers/iommu/io-pgtable-arm.c | 4 ---- drivers/iommu/qcom_iommu.c | 2 +- 6 files changed, 7 insertions(+), 15 deletions(-)Quoted 3 lines
Hmm, so I'm a bit nervous about this one since I think we really should be providing a TCR with EPD1 set if we're only giving you TTBR0. Relying on the driver to do this worries me. See my comments on the next patch.
Quoted 10 lines
The whole idea is that we already know we can't provide a *complete* TCR value (not least because anything above bit 31 is the wild west), thus there's really no point in io-pgtable trying to provide anything other than the parts it definitely controls. It makes sense to provide this partial TCR value "as if" for TTBR0, since that's the most common case, but ultimately io-pgatble doesn't know (or need to) which TTBR the caller intends to actually use for this table. Even if the caller *is* allocating it for TTBR0, io-pgtable doesn't know that they haven't got something live in TTBR1 already, so it still wouldn't be in a position to make the EPD1 call either way.
Quoted 4 lines
Ok, but the driver can happily rewrite/ignore what it gets back. I suppose an alternative would be scrapped the 'u64 tcr' and instead having a bunch of named bitfields for the stuff we're actually providing, although I'd still like EPDx to be in there.
I like the bitfield idea; it would certainly emphasise the "you have to do something more with this" angle that I'm pushing towards here, but still leave things framed in TCR terms without having to go to some more general abstraction. It really doesn't play into your EPD argument though - such a config would be providing TxSZ/TGx/IRGNx/ORGNx/SHx, but EPDy, for y = !x. For a driver to understand that and do the right thing with it is even more involved than for the driver to just set EPD1 by itself anyway.
Quoted 10 lines
Quoted 4 lines
Ultimately, it's the IOMMU drivers who decide what they put in which TTBR, so it's the IOMMU drivers which have to take responsibility for EPD*. Sure you can worry about it, but you can equally worry about them them misprogramming the ASID or anything else...
I find the EPDx bits particularly dangerous because:
- They're easily overlooked
- Clobbering TTBR1 with0x0doesn't disable walks via TTBR1 as you might reasonably expect
(FWIW I'm not sure that that is a reasonable expectation, at least for anyone savvy enough to be programming an MMU in the first place. There are plenty of systems with RAM at 0x0)
Quoted 7 lines
- If you do the above without EPD, the breakage will be subtle
and given that I don't see any real downsides to us providing a default TCR value with EPD set appropriately, then I think we should do that. I'd be happy to revisit the decision later on if it's getting the way of a real use-case, but it feels like we're throwing the baby out with the bathwater at the moment and I'd rather do this incrementally based on actual need.
The downside is maintaining extra complexity for the sake of a theoretical concern which hasn't been borne out in practice, with a promise of yet more complexity down the line. Moving the 3 babies which anyone acknowledges into their own private baths takes a whole -8 lines of code to implement. That said, if we don't go down the bitfield route, then I *can* leave the default TCR having EPD1 set if that makes you feel warm and safe, but it will still be resoundingly ignored.
If only LPAE had created these bits as enables rather than disables then things would be logical and we could all be happy, but here we are...
Robin.
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Will Deacon
maintainerRe: [PATCH 3/4] iommu/io-pgtable-arm: Rationalise TCR handling
Quoted 43 lines · Robin Murphy
Quoted 37 lines · Will Deacon
Quoted 25 lines · Robin Murphy
Quoted 20 lines · Will Deacon
Quoted 10 lines · Robin Murphy
Although it's conceptually nice for the
io_pgtable_cfgto provide a standard VMSA TCR value, the reality is that no VMSA-compliant IOMMU looks exactly like an Arm CPU, and they all have various other TCR controls which io-pgtable can't be expected to understand. Thus since there is an expectation that drivers will have to add to the given TCR value anyway, let's strip it down to just the essentials that are directly relevant to io-pgatble's inner workings - namely the address sizes, walk attributes, and where appropriate, format selection.Signed-off-by Robin Murphy <[email protected]>Quoted 8 lines
--- drivers/iommu/arm-smmu-v3.c | 7 +------ drivers/iommu/arm-smmu.c | 1 + drivers/iommu/arm-smmu.h | 2 ++ drivers/iommu/io-pgtable-arm-v7s.c | 6 ++---- drivers/iommu/io-pgtable-arm.c | 4 ---- drivers/iommu/qcom_iommu.c | 2 +- 6 files changed, 7 insertions(+), 15 deletions(-)Quoted 3 lines
Hmm, so I'm a bit nervous about this one since I think we really should be providing a TCR with EPD1 set if we're only giving you TTBR0. Relying on the driver to do this worries me. See my comments on the next patch.
Quoted 10 lines
The whole idea is that we already know we can't provide a *complete* TCR value (not least because anything above bit 31 is the wild west), thus there's really no point in io-pgtable trying to provide anything other than the parts it definitely controls. It makes sense to provide this partial TCR value "as if" for TTBR0, since that's the most common case, but ultimately io-pgatble doesn't know (or need to) which TTBR the caller intends to actually use for this table. Even if the caller *is* allocating it for TTBR0, io-pgtable doesn't know that they haven't got something live in TTBR1 already, so it still wouldn't be in a position to make the EPD1 call either way.
Quoted 4 lines
Ok, but the driver can happily rewrite/ignore what it gets back. I suppose an alternative would be scrapped the 'u64 tcr' and instead having a bunch of named bitfields for the stuff we're actually providing, although I'd still like EPDx to be in there.
Quoted 7 lines
I like the bitfield idea; it would certainly emphasise the "you have to do something more with this" angle that I'm pushing towards here, but still leave things framed in TCR terms without having to go to some more general abstraction. It really doesn't play into your EPD argument though - such a config would be providing TxSZ/TGx/IRGNx/ORGNx/SHx, but EPDy, for y = !x. For a driver to understand that and do the right thing with it is even more involved than for the driver to just set EPD1 by itself anyway.
Having considered the bitfield idea some more, I'm less attached to EPDx because we simply wouldn't be making a statement about them, rather than a (dangerous) zero value and expecting it to be ignored. So I think we're in agreement on that.
The only part I'm still stuck to is that I think io-pgtable should know whether it's targetting TTBR0 or TTBR1 so that it can sanitise input addresses correctly. Doing this in the driver code is possible, but I'd rather not start from that position, particularly as it would require things like sign-extension in the TLBI callbacks.
Quoted 2 lines
If only LPAE had created these bits as enables rather than disables then things would be logical and we could all be happy, but here we are...
I'm happy! :D:D:D
Will
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
reviewerRe: [PATCH 3/4] iommu/io-pgtable-arm: Rationalise TCR handling
Quoted 52 lines · Will Deacon
Quoted 43 lines · Robin Murphy
Quoted 37 lines · Will Deacon
Quoted 25 lines · Robin Murphy
Quoted 20 lines · Will Deacon
Quoted 10 lines · Robin Murphy
Although it's conceptually nice for the
io_pgtable_cfgto provide a standard VMSA TCR value, the reality is that no VMSA-compliant IOMMU looks exactly like an Arm CPU, and they all have various other TCR controls which io-pgtable can't be expected to understand. Thus since there is an expectation that drivers will have to add to the given TCR value anyway, let's strip it down to just the essentials that are directly relevant to io-pgatble's inner workings - namely the address sizes, walk attributes, and where appropriate, format selection.Signed-off-by Robin Murphy <[email protected]>Quoted 8 lines
--- drivers/iommu/arm-smmu-v3.c | 7 +------ drivers/iommu/arm-smmu.c | 1 + drivers/iommu/arm-smmu.h | 2 ++ drivers/iommu/io-pgtable-arm-v7s.c | 6 ++---- drivers/iommu/io-pgtable-arm.c | 4 ---- drivers/iommu/qcom_iommu.c | 2 +- 6 files changed, 7 insertions(+), 15 deletions(-)Quoted 3 lines
Hmm, so I'm a bit nervous about this one since I think we really should be providing a TCR with EPD1 set if we're only giving you TTBR0. Relying on the driver to do this worries me. See my comments on the next patch.
Quoted 10 lines
The whole idea is that we already know we can't provide a *complete* TCR value (not least because anything above bit 31 is the wild west), thus there's really no point in io-pgtable trying to provide anything other than the parts it definitely controls. It makes sense to provide this partial TCR value "as if" for TTBR0, since that's the most common case, but ultimately io-pgatble doesn't know (or need to) which TTBR the caller intends to actually use for this table. Even if the caller *is* allocating it for TTBR0, io-pgtable doesn't know that they haven't got something live in TTBR1 already, so it still wouldn't be in a position to make the EPD1 call either way.
Quoted 4 lines
Ok, but the driver can happily rewrite/ignore what it gets back. I suppose an alternative would be scrapped the 'u64 tcr' and instead having a bunch of named bitfields for the stuff we're actually providing, although I'd still like EPDx to be in there.
Quoted 7 lines
I like the bitfield idea; it would certainly emphasise the "you have to do something more with this" angle that I'm pushing towards here, but still leave things framed in TCR terms without having to go to some more general abstraction. It really doesn't play into your EPD argument though - such a config would be providing TxSZ/TGx/IRGNx/ORGNx/SHx, but EPDy, for y = !x. For a driver to understand that and do the right thing with it is even more involved than for the driver to just set EPD1 by itself anyway.
Quoted 4 lines
Having considered the bitfield idea some more, I'm less attached to EPDx because we simply wouldn't be making a statement about them, rather than a (dangerous) zero value and expecting it to be ignored. So I think we're in agreement on that.
Cool, I'll give bitfields a go for v2.
Quoted 5 lines
The only part I'm still stuck to is that I think io-pgtable should know whether it's targetting TTBR0 or TTBR1 so that it can sanitise input addresses correctly. Doing this in the driver code is possible, but I'd rather not start from that position, particularly as it would require things like sign-extension in the TLBI callbacks.
Good point, and thanks for the prod that the way I end up propagating masked-off IOVAs through to the TLBI calls here is busted either way. I'm OK with introducing an explicit TTBR1 quirk to begin with, as it should make things a little easier to reason about, and we can always revisit later if and when we do find a need for more flexibility.
Quoted 4 lines
Quoted 2 lines
If only LPAE had created these bits as enables rather than disables then things would be logical and we could all be happy, but here we are...
I'm happy! :D:D:D
Yeah, but I refuse to believe it's ever because of pagetables ;)
Robin.
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 3/4] iommu/io-pgtable-arm: Rationalise TCR handling
Quoted 53 lines · Robin Murphy
Quoted 52 lines · Will Deacon
Quoted 50 lines · Robin Murphy
Quoted 37 lines · Will Deacon
Quoted 25 lines · Robin Murphy
Quoted 20 lines · Will Deacon
Quoted 10 lines · Robin Murphy
Although it's conceptually nice for the
io_pgtable_cfgto provide a standard VMSA TCR value, the reality is that no VMSA-compliant IOMMU looks exactly like an Arm CPU, and they all have various other TCR controls which io-pgtable can't be expected to understand. Thus since there is an expectation that drivers will have to add to the given TCR value anyway, let's strip it down to just the essentials that are directly relevant to io-pgatble's inner workings - namely the address sizes, walk attributes, and where appropriate, format selection.Signed-off-by Robin Murphy <[email protected]>Quoted 8 lines
--- drivers/iommu/arm-smmu-v3.c | 7 +------ drivers/iommu/arm-smmu.c | 1 + drivers/iommu/arm-smmu.h | 2 ++ drivers/iommu/io-pgtable-arm-v7s.c | 6 ++---- drivers/iommu/io-pgtable-arm.c | 4 ---- drivers/iommu/qcom_iommu.c | 2 +- 6 files changed, 7 insertions(+), 15 deletions(-)Quoted 3 lines
Hmm, so I'm a bit nervous about this one since I think we really should be providing a TCR with EPD1 set if we're only giving you TTBR0. Relying on the driver to do this worries me. See my comments on the next patch.
Quoted 10 lines
The whole idea is that we already know we can't provide a *complete* TCR value (not least because anything above bit 31 is the wild west), thus there's really no point in io-pgtable trying to provide anything other than the parts it definitely controls. It makes sense to provide this partial TCR value "as if" for TTBR0, since that's the most common case, but ultimately io-pgatble doesn't know (or need to) which TTBR the caller intends to actually use for this table. Even if the caller *is* allocating it for TTBR0, io-pgtable doesn't know that they haven't got something live in TTBR1 already, so it still wouldn't be in a position to make the EPD1 call either way.
Quoted 4 lines
Ok, but the driver can happily rewrite/ignore what it gets back. I suppose an alternative would be scrapped the 'u64 tcr' and instead having a bunch of named bitfields for the stuff we're actually providing, although I'd still like EPDx to be in there.
I like the bitfield idea; it would certainly emphasise the "you have to do something more with this" angle that I'm pushing towards here, but still leave things framed in TCR terms without having to go to some more general abstraction. It really doesn't play into your EPD argument though - such a config would be providing TxSZ/TGx/IRGNx/ORGNx/SHx, but EPDy, for y = !x. For a driver to understand that and do the right thing with it is even more involved than for the driver to just set EPD1 by itself anyway.
Quoted 12 lines
Quoted 4 lines
Having considered the bitfield idea some more, I'm less attached to EPDx because we simply wouldn't be making a statement about them, rather than a (dangerous) zero value and expecting it to be ignored. So I think we're in agreement on that.
Cool, I'll give bitfields a go for v2.
Quoted 5 lines
The only part I'm still stuck to is that I think io-pgtable should know whether it's targetting TTBR0 or TTBR1 so that it can sanitise input addresses correctly. Doing this in the driver code is possible, but I'd rather not start from that position, particularly as it would require things like sign-extension in the TLBI callbacks.
Bumping this as is our tradition in the -rc1 time frame before we get all distracted with other stuff. It sounds like the last agreement was for a TTBR1 hint for the EDP and the sign extension in the functions.
Let me know if you need any help. I've got a little time and more than a little motivation to keep slogging ahead toward a glorious arm-smmu-v2 per-context pagetable future.
Jordan
Signature · 6 lines
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Will Deacon
maintainerRe: [PATCH 3/4] iommu/io-pgtable-arm: Rationalise TCR handling
Quoted 67 lines · Jordan Crouse
Quoted 53 lines · Robin Murphy
Quoted 52 lines · Will Deacon
Quoted 50 lines · Robin Murphy
Quoted 37 lines · Will Deacon
Quoted 25 lines · Robin Murphy
Quoted 20 lines · Will Deacon
Quoted 10 lines · Robin Murphy
Although it's conceptually nice for the
io_pgtable_cfgto provide a standard VMSA TCR value, the reality is that no VMSA-compliant IOMMU looks exactly like an Arm CPU, and they all have various other TCR controls which io-pgtable can't be expected to understand. Thus since there is an expectation that drivers will have to add to the given TCR value anyway, let's strip it down to just the essentials that are directly relevant to io-pgatble's inner workings - namely the address sizes, walk attributes, and where appropriate, format selection.Signed-off-by Robin Murphy <[email protected]>Quoted 8 lines
--- drivers/iommu/arm-smmu-v3.c | 7 +------ drivers/iommu/arm-smmu.c | 1 + drivers/iommu/arm-smmu.h | 2 ++ drivers/iommu/io-pgtable-arm-v7s.c | 6 ++---- drivers/iommu/io-pgtable-arm.c | 4 ---- drivers/iommu/qcom_iommu.c | 2 +- 6 files changed, 7 insertions(+), 15 deletions(-)Quoted 3 lines
Hmm, so I'm a bit nervous about this one since I think we really should be providing a TCR with EPD1 set if we're only giving you TTBR0. Relying on the driver to do this worries me. See my comments on the next patch.
Quoted 10 lines
The whole idea is that we already know we can't provide a *complete* TCR value (not least because anything above bit 31 is the wild west), thus there's really no point in io-pgtable trying to provide anything other than the parts it definitely controls. It makes sense to provide this partial TCR value "as if" for TTBR0, since that's the most common case, but ultimately io-pgatble doesn't know (or need to) which TTBR the caller intends to actually use for this table. Even if the caller *is* allocating it for TTBR0, io-pgtable doesn't know that they haven't got something live in TTBR1 already, so it still wouldn't be in a position to make the EPD1 call either way.
Quoted 4 lines
Ok, but the driver can happily rewrite/ignore what it gets back. I suppose an alternative would be scrapped the 'u64 tcr' and instead having a bunch of named bitfields for the stuff we're actually providing, although I'd still like EPDx to be in there.
I like the bitfield idea; it would certainly emphasise the "you have to do something more with this" angle that I'm pushing towards here, but still leave things framed in TCR terms without having to go to some more general abstraction. It really doesn't play into your EPD argument though - such a config would be providing TxSZ/TGx/IRGNx/ORGNx/SHx, but EPDy, for y = !x. For a driver to understand that and do the right thing with it is even more involved than for the driver to just set EPD1 by itself anyway.
Quoted 12 lines
Quoted 4 lines
Having considered the bitfield idea some more, I'm less attached to EPDx because we simply wouldn't be making a statement about them, rather than a (dangerous) zero value and expecting it to be ignored. So I think we're in agreement on that.
Cool, I'll give bitfields a go for v2.
Quoted 5 lines
The only part I'm still stuck to is that I think io-pgtable should know whether it's targetting TTBR0 or TTBR1 so that it can sanitise input addresses correctly. Doing this in the driver code is possible, but I'd rather not start from that position, particularly as it would require things like sign-extension in the TLBI callbacks.
Quoted 3 lines
Bumping this as is our tradition in the -rc1 time frame before we get all distracted with other stuff. It sounds like the last agreement was for a TTBR1 hint for the EDP and the sign extension in the functions.
If somebody respins this using bitfields and an explicit TTBR1 quirk then I'll merge it.
Will
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
reviewerRe: [PATCH 3/4] iommu/io-pgtable-arm: Rationalise TCR handling
Quoted 68 lines · Will Deacon
Quoted 67 lines · Jordan Crouse
Quoted 65 lines · Robin Murphy
Quoted 52 lines · Will Deacon
Quoted 43 lines · Robin Murphy
Quoted 37 lines · Will Deacon
Quoted 25 lines · Robin Murphy
Quoted 20 lines · Will Deacon
Quoted 10 lines · Robin Murphy
Although it's conceptually nice for the
io_pgtable_cfgto provide a standard VMSA TCR value, the reality is that no VMSA-compliant IOMMU looks exactly like an Arm CPU, and they all have various other TCR controls which io-pgtable can't be expected to understand. Thus since there is an expectation that drivers will have to add to the given TCR value anyway, let's strip it down to just the essentials that are directly relevant to io-pgatble's inner workings - namely the address sizes, walk attributes, and where appropriate, format selection.Signed-off-by Robin Murphy <[email protected]>Quoted 8 lines
--- drivers/iommu/arm-smmu-v3.c | 7 +------ drivers/iommu/arm-smmu.c | 1 + drivers/iommu/arm-smmu.h | 2 ++ drivers/iommu/io-pgtable-arm-v7s.c | 6 ++---- drivers/iommu/io-pgtable-arm.c | 4 ---- drivers/iommu/qcom_iommu.c | 2 +- 6 files changed, 7 insertions(+), 15 deletions(-)Quoted 3 lines
Hmm, so I'm a bit nervous about this one since I think we really should be providing a TCR with EPD1 set if we're only giving you TTBR0. Relying on the driver to do this worries me. See my comments on the next patch.
Quoted 10 lines
The whole idea is that we already know we can't provide a *complete* TCR value (not least because anything above bit 31 is the wild west), thus there's really no point in io-pgtable trying to provide anything other than the parts it definitely controls. It makes sense to provide this partial TCR value "as if" for TTBR0, since that's the most common case, but ultimately io-pgatble doesn't know (or need to) which TTBR the caller intends to actually use for this table. Even if the caller *is* allocating it for TTBR0, io-pgtable doesn't know that they haven't got something live in TTBR1 already, so it still wouldn't be in a position to make the EPD1 call either way.
Quoted 4 lines
Ok, but the driver can happily rewrite/ignore what it gets back. I suppose an alternative would be scrapped the 'u64 tcr' and instead having a bunch of named bitfields for the stuff we're actually providing, although I'd still like EPDx to be in there.
Quoted 7 lines
I like the bitfield idea; it would certainly emphasise the "you have to do something more with this" angle that I'm pushing towards here, but still leave things framed in TCR terms without having to go to some more general abstraction. It really doesn't play into your EPD argument though - such a config would be providing TxSZ/TGx/IRGNx/ORGNx/SHx, but EPDy, for y = !x. For a driver to understand that and do the right thing with it is even more involved than for the driver to just set EPD1 by itself anyway.
Quoted 4 lines
Having considered the bitfield idea some more, I'm less attached to EPDx because we simply wouldn't be making a statement about them, rather than a (dangerous) zero value and expecting it to be ignored. So I think we're in agreement on that.
Cool, I'll give bitfields a go for v2.
Quoted 5 lines
The only part I'm still stuck to is that I think io-pgtable should know whether it's targetting TTBR0 or TTBR1 so that it can sanitise input addresses correctly. Doing this in the driver code is possible, but I'd rather not start from that position, particularly as it would require things like sign-extension in the TLBI callbacks.
Quoted 6 lines
Quoted 3 lines
Bumping this as is our tradition in the -rc1 time frame before we get all distracted with other stuff. It sounds like the last agreement was for a TTBR1 hint for the EDP and the sign extension in the functions.
If somebody respins this using bitfields and an explicit TTBR1 quirk then I'll merge it.
Oops, the ping did register, I just didn't react outwardly ;)
I have been working on v2, and plan to have something ready next week - the holdup was that I started refactoring all the argument passing since the number of things we have to carry through from one end of map/unmap to the other is getting a bit silly, but I think I can still finish the TTBR1 quirk without that, so if I don't get it cracked imminently then I'll put it aside to revisit later.
Robin.
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Will Deacon
maintainerRe: [PATCH 3/4] iommu/io-pgtable-arm: Rationalise TCR handling
Quoted 76 lines · Robin Murphy
Quoted 68 lines · Will Deacon
Quoted 67 lines · Jordan Crouse
Quoted 65 lines · Robin Murphy
Quoted 52 lines · Will Deacon
Quoted 43 lines · Robin Murphy
Quoted 37 lines · Will Deacon
Quoted 25 lines · Robin Murphy
Quoted 20 lines · Will Deacon
Quoted 10 lines · Robin Murphy
Although it's conceptually nice for the
io_pgtable_cfgto provide a standard VMSA TCR value, the reality is that no VMSA-compliant IOMMU looks exactly like an Arm CPU, and they all have various other TCR controls which io-pgtable can't be expected to understand. Thus since there is an expectation that drivers will have to add to the given TCR value anyway, let's strip it down to just the essentials that are directly relevant to io-pgatble's inner workings - namely the address sizes, walk attributes, and where appropriate, format selection.Signed-off-by Robin Murphy <[email protected]>Quoted 8 lines
--- drivers/iommu/arm-smmu-v3.c | 7 +------ drivers/iommu/arm-smmu.c | 1 + drivers/iommu/arm-smmu.h | 2 ++ drivers/iommu/io-pgtable-arm-v7s.c | 6 ++---- drivers/iommu/io-pgtable-arm.c | 4 ---- drivers/iommu/qcom_iommu.c | 2 +- 6 files changed, 7 insertions(+), 15 deletions(-)Quoted 3 lines
Hmm, so I'm a bit nervous about this one since I think we really should be providing a TCR with EPD1 set if we're only giving you TTBR0. Relying on the driver to do this worries me. See my comments on the next patch.
Quoted 10 lines
The whole idea is that we already know we can't provide a *complete* TCR value (not least because anything above bit 31 is the wild west), thus there's really no point in io-pgtable trying to provide anything other than the parts it definitely controls. It makes sense to provide this partial TCR value "as if" for TTBR0, since that's the most common case, but ultimately io-pgatble doesn't know (or need to) which TTBR the caller intends to actually use for this table. Even if the caller *is* allocating it for TTBR0, io-pgtable doesn't know that they haven't got something live in TTBR1 already, so it still wouldn't be in a position to make the EPD1 call either way.
Quoted 4 lines
Ok, but the driver can happily rewrite/ignore what it gets back. I suppose an alternative would be scrapped the 'u64 tcr' and instead having a bunch of named bitfields for the stuff we're actually providing, although I'd still like EPDx to be in there.
Quoted 7 lines
I like the bitfield idea; it would certainly emphasise the "you have to do something more with this" angle that I'm pushing towards here, but still leave things framed in TCR terms without having to go to some more general abstraction. It really doesn't play into your EPD argument though - such a config would be providing TxSZ/TGx/IRGNx/ORGNx/SHx, but EPDy, for y = !x. For a driver to understand that and do the right thing with it is even more involved than for the driver to just set EPD1 by itself anyway.
Quoted 4 lines
Having considered the bitfield idea some more, I'm less attached to EPDx because we simply wouldn't be making a statement about them, rather than a (dangerous) zero value and expecting it to be ignored. So I think we're in agreement on that.
Cool, I'll give bitfields a go for v2.
Quoted 5 lines
The only part I'm still stuck to is that I think io-pgtable should know whether it's targetting TTBR0 or TTBR1 so that it can sanitise input addresses correctly. Doing this in the driver code is possible, but I'd rather not start from that position, particularly as it would require things like sign-extension in the TLBI callbacks.
Quoted 6 lines
Quoted 3 lines
Bumping this as is our tradition in the -rc1 time frame before we get all distracted with other stuff. It sounds like the last agreement was for a TTBR1 hint for the EDP and the sign extension in the functions.
If somebody respins this using bitfields and an explicit TTBR1 quirk then I'll merge it.
Quoted 8 lines
Oops, the ping did register, I just didn't react outwardly ;)
I have been working on v2, and plan to have something ready next week - the holdup was that I started refactoring all the argument passing since the number of things we have to carry through from one end of map/unmap to the other is getting a bit silly, but I think I can still finish the TTBR1 quirk without that, so if I don't get it cracked imminently then I'll put it aside to revisit later.
Cheers, Robin! I'll keep an eye out for it.
Will
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 3/4] iommu/io-pgtable-arm: Rationalise TCR handling
In reply to Robin MurphyQuoted 36 lines · Robin Murphy
Quoted 20 lines · Will Deacon
Quoted 10 lines · Robin Murphy
Although it's conceptually nice for the
io_pgtable_cfgto provide a standard VMSA TCR value, the reality is that no VMSA-compliant IOMMU looks exactly like an Arm CPU, and they all have various other TCR controls which io-pgtable can't be expected to understand. Thus since there is an expectation that drivers will have to add to the given TCR value anyway, let's strip it down to just the essentials that are directly relevant to io-pgatble's inner workings - namely the address sizes, walk attributes, and where appropriate, format selection.Signed-off-by Robin Murphy <[email protected]>Quoted 8 lines
--- drivers/iommu/arm-smmu-v3.c | 7 +------ drivers/iommu/arm-smmu.c | 1 + drivers/iommu/arm-smmu.h | 2 ++ drivers/iommu/io-pgtable-arm-v7s.c | 6 ++---- drivers/iommu/io-pgtable-arm.c | 4 ---- drivers/iommu/qcom_iommu.c | 2 +- 6 files changed, 7 insertions(+), 15 deletions(-)Quoted 3 lines
Hmm, so I'm a bit nervous about this one since I think we really should be providing a TCR with EPD1 set if we're only giving you TTBR0. Relying on the driver to do this worries me. See my comments on the next patch.
The whole idea is that we already know we can't provide a *complete* TCR value (not least because anything above bit 31 is the wild west), thus there's really no point in io-pgtable trying to provide anything other than the parts it definitely controls. It makes sense to provide this partial TCR value "as if" for TTBR0, since that's the most common case, but ultimately io-pgatble doesn't know (or need to) which TTBR the caller intends to actually use for this table. Even if the caller *is* allocating it for TTBR0, io-pgtable doesn't know that they haven't got something live in TTBR1 already, so it still wouldn't be in a position to make the EPD1 call either way.
Quoted 4 lines
Ultimately, it's the IOMMU drivers who decide what they put in which TTBR, so it's the IOMMU drivers which have to take responsibility for EPD*. Sure you can worry about it, but you can equally worry about them them misprogramming the ASID or anything else...
I agree. If the driver *does* want to use TTBR1 then it gets a bit uglier to realize that the io-pgtable set the bit and mask it off. To me it is a lot clearer if this is done explicitly in the driver especially if the driver is where we are making the choice to use either ttbr0 or ttbr1.
It would probably be easier to see in actual code, and I'll have a patch shortly on top of this series.
Jordan
Signature · 6 lines
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
reviewerPATCH 4/4 iommu/io-pgtable-arm: Prepare for TTBR1 usage
In reply to Robin MurphyNow that callers are free to use a given table for TTBR1 if they wish (all they need do is shift the provided attributes when constructing their final TCR value), the only remaining impediment is the address validation on map/unmap. The fact that the LPAE address space split is symmetric makes this easy to accommodate - by simplifying the current range checks into explicit tests that address bits above IAS are all zero, it then follows straightforwardly to add the inverse test to allow the all-ones case as well.
--- drivers/iommu/io-pgtable-arm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/iommu/io-pgtable-arm.c +4 -3
@@ -475,13 +475,13 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,arm_lpae_iopte *ptep = data->pgd;int ret, lvl =ARM_LPAE_START_LVL (data);arm_lpae_iopte prot; +long iaext = (long )iova >> data->iop.cfg.ias;/* If no access, then nothing to do */ if (!(iommu_prot & (IOMMU_READ |IOMMU_WRITE )))return 0 ; -if (WARN_ON (iova >= (1ULL << data->iop.cfg.ias) || - paddr >= (1ULL << data->iop.cfg.oas))) +if (WARN_ON ((iaext && ~iaext) || paddr >> data->iop.cfg.oas))return -ERANGE ; prot =arm_lpae_prot_to_pte (data, iommu_prot);
@@ -647,8 +647,9 @@ static size_t arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova,struct arm_lpae_io_pgtable *data =io_pgtable_ops_to_data (ops);arm_lpae_iopte *ptep = data->pgd;int lvl =ARM_LPAE_START_LVL (data); +long iaext = (long )iova >> data->iop.cfg.ias; -if (WARN_ON (iova >= (1ULL << data->iop.cfg.ias))) +if (WARN_ON (iaext && ~iaext))return 0 ;return __arm_lpae_unmap (data, iova, size, lvl, ptep);
Signature · 6 lines
2.21.0.dirty _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 4/4] iommu/io-pgtable-arm: Prepare for TTBR1 usage
Quoted 24 lines · Robin Murphy
Now that callers are free to use a given table for TTBR1 if they wish (all they need do is shift the provided attributes when constructing their final TCR value), the only remaining impediment is the address validation on map/unmap. The fact that the LPAE address space split is symmetric makes this easy to accommodate - by simplifying the current range checks into explicit tests that address bits above IAS are all zero, it then follows straightforwardly to add the inverse test to allow the all-ones case as well.
Signed-off-by Robin Murphy <[email protected]>--- drivers/iommu/io-pgtable-arm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)drivers/iommu/io-pgtable-arm.c +1
-0@@ -475,13 +475,13 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,arm_lpae_iopte *ptep = data->pgd;int ret, lvl =ARM_LPAE_START_LVL (data);arm_lpae_iopte prot; +long iaext = (long )iova >> data->iop.cfg.ias;
drivers/iommu/io-pgtable-arm.c static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova, · line 487
Quoted 10 lines
drivers/iommu/io-pgtable-arm.c +1
-2/* If no access, then nothing to do */ if (!(iommu_prot & (IOMMU_READ |IOMMU_WRITE )))return 0 ; -if (WARN_ON (iova >= (1ULL << data->iop.cfg.ias) || - paddr >= (1ULL << data->iop.cfg.oas))) +if (WARN_ON ((iaext && ~iaext) || paddr >> data->iop.cfg.oas))return -ERANGE ; prot =arm_lpae_prot_to_pte (data, iommu_prot);
We'll want to cast away the sign extended bits before mapping the iova, this might be a good patch for that too as long as we are calculating the iaext.
drivers/iommu/io-pgtable-arm.c static size_t arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova, · line 655
Quoted 11 lines
drivers/iommu/io-pgtable-arm.c +2
-1@@ -647,8 +647,9 @@ static size_t arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova,struct arm_lpae_io_pgtable *data =io_pgtable_ops_to_data (ops);arm_lpae_iopte *ptep = data->pgd;int lvl =ARM_LPAE_START_LVL (data); +long iaext = (long )iova >> data->iop.cfg.ias; -if (WARN_ON (iova >= (1ULL << data->iop.cfg.ias))) +if (WARN_ON (iaext && ~iaext))return 0 ;return __arm_lpae_unmap (data, iova, size, lvl, ptep);
And here too.
Jordan
Signature · 6 lines
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ iommu mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
reviewerRe: [PATCH 4/4] iommu/io-pgtable-arm: Prepare for TTBR1 usage
Quoted 34 lines · Jordan Crouse
Quoted 33 lines · Robin Murphy
Now that callers are free to use a given table for TTBR1 if they wish (all they need do is shift the provided attributes when constructing their final TCR value), the only remaining impediment is the address validation on map/unmap. The fact that the LPAE address space split is symmetric makes this easy to accommodate - by simplifying the current range checks into explicit tests that address bits above IAS are all zero, it then follows straightforwardly to add the inverse test to allow the all-ones case as well.
Signed-off-by Robin Murphy <[email protected]>--- drivers/iommu/io-pgtable-arm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)drivers/iommu/io-pgtable-arm.c +2
-2@@ -475,13 +475,13 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,arm_lpae_iopte *ptep = data->pgd;int ret, lvl =ARM_LPAE_START_LVL (data);arm_lpae_iopte prot; +long iaext = (long )iova >> data->iop.cfg.ias;/* If no access, then nothing to do */ if (!(iommu_prot & (IOMMU_READ |IOMMU_WRITE )))return 0 ; -if (WARN_ON (iova >= (1ULL << data->iop.cfg.ias) || - paddr >= (1ULL << data->iop.cfg.oas))) +if (WARN_ON ((iaext && ~iaext) || paddr >> data->iop.cfg.oas))return -ERANGE ;
Quoted 4 lines
drivers/iommu/io-pgtable-arm.c static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova, · line 487
Quoted 1 line
drivers/iommu/io-pgtable-arm.c +0
-0prot =arm_lpae_prot_to_pte (data, iommu_prot);We'll want to cast away the sign extended bits before mapping the iova, this might be a good patch for that too as long as we are calculating the iaext.
Ah good point, I'd forgotten that ARM_LPAE_LVL_IDX() doesn't actually cap to IAS if the top level is smaller than bits_per_level (I suppose we *could* make it do so for purity, but that's bound to hurt efficiency far more than just zeroing out the offending bits here).
Thanks,
Robin.
Quoted 11 lines
Quoted 11 lines
drivers/iommu/io-pgtable-arm.c +2
-1@@ -647,8 +647,9 @@ static size_t arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova,struct arm_lpae_io_pgtable *data =io_pgtable_ops_to_data (ops);arm_lpae_iopte *ptep = data->pgd;int lvl =ARM_LPAE_START_LVL (data); +long iaext = (long )iova >> data->iop.cfg.ias; -if (WARN_ON (iova >= (1ULL << data->iop.cfg.ias))) +if (WARN_ON (iaext && ~iaext))return 0 ;
Quoted 6 lines
drivers/iommu/io-pgtable-arm.c static size_t arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova, · line 655
Quoted 1 line
drivers/iommu/io-pgtable-arm.c +0
-0return __arm_lpae_unmap (data, iova, size, lvl, ptep);And here too.
Jordan
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Will Deacon
maintainerRe: [PATCH 4/4] iommu/io-pgtable-arm: Prepare for TTBR1 usage
In reply to Robin MurphyQuoted 21 lines · Robin Murphy
Now that callers are free to use a given table for TTBR1 if they wish (all they need do is shift the provided attributes when constructing their final TCR value), the only remaining impediment is the address validation on map/unmap. The fact that the LPAE address space split is symmetric makes this easy to accommodate - by simplifying the current range checks into explicit tests that address bits above IAS are all zero, it then follows straightforwardly to add the inverse test to allow the all-ones case as well.
Signed-off-by Robin Murphy <[email protected]>--- drivers/iommu/io-pgtable-arm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)drivers/iommu/io-pgtable-arm.c +0
-0@@ -475,13 +475,13 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,arm_lpae_iopte *ptep = data->pgd;int ret, lvl =ARM_LPAE_START_LVL (data);
drivers/iommu/io-pgtable-arm.c static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova, · line 484
Quoted 10 lines
drivers/iommu/io-pgtable-arm.c +2
-2arm_lpae_iopte prot; +long iaext = (long )iova >> data->iop.cfg.ias;/* If no access, then nothing to do */ if (!(iommu_prot & (IOMMU_READ |IOMMU_WRITE )))return 0 ; -if (WARN_ON (iova >= (1ULL << data->iop.cfg.ias) || - paddr >= (1ULL << data->iop.cfg.oas))) +if (WARN_ON ((iaext && ~iaext) || paddr >> data->iop.cfg.oas))
I had to read that '&&' twice, but I see what you're doing now :)
drivers/iommu/io-pgtable-arm.c static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova, · line 485
Quoted 1 line
drivers/iommu/io-pgtable-arm.c +0
-0return -ERANGE ;
This doesn't seem sufficient to prevent a mixture of TTBR1 and TTBR0 addresses from being mapped in the same TTBR. Perhaps we need a quirk for TTBR1, which could then take care of setting EPDx appropriately?
Will
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Robin Murphy
reviewerRe: [PATCH 4/4] iommu/io-pgtable-arm: Prepare for TTBR1 usage
Quoted 35 lines · Will Deacon
Quoted 21 lines · Robin Murphy
Now that callers are free to use a given table for TTBR1 if they wish (all they need do is shift the provided attributes when constructing their final TCR value), the only remaining impediment is the address validation on map/unmap. The fact that the LPAE address space split is symmetric makes this easy to accommodate - by simplifying the current range checks into explicit tests that address bits above IAS are all zero, it then follows straightforwardly to add the inverse test to allow the all-ones case as well.
Signed-off-by Robin Murphy <[email protected]>--- drivers/iommu/io-pgtable-arm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)drivers/iommu/io-pgtable-arm.c +0
-0@@ -475,13 +475,13 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,arm_lpae_iopte *ptep = data->pgd;int ret, lvl =ARM_LPAE_START_LVL (data);drivers/iommu/io-pgtable-arm.c static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova, · line 484
Quoted 10 lines
drivers/iommu/io-pgtable-arm.c +2
-2arm_lpae_iopte prot; +long iaext = (long )iova >> data->iop.cfg.ias;/* If no access, then nothing to do */ if (!(iommu_prot & (IOMMU_READ |IOMMU_WRITE )))return 0 ; -if (WARN_ON (iova >= (1ULL << data->iop.cfg.ias) || - paddr >= (1ULL << data->iop.cfg.oas))) +if (WARN_ON ((iaext && ~iaext) || paddr >> data->iop.cfg.oas))I had to read that '&&' twice, but I see what you're doing now :)
Quoted 5 lines
drivers/iommu/io-pgtable-arm.c static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova, · line 485
Quoted 1 line
drivers/iommu/io-pgtable-arm.c +0
-0return -ERANGE ;This doesn't seem sufficient to prevent a mixture of TTBR1 and TTBR0 addresses from being mapped in the same TTBR. Perhaps we need a quirk for TTBR1, which could then take care of setting EPDx appropriately?
Right, that's the one downside of going for the minimalist "io-pgtable doesn't even have to know" approach. On reflection, though, in that paradigm it should probably be the caller's responsibility to convert TTBR1 addresses to preserve the "as if TTBR0" illusion anyway :/
The advantage of not having a quirk is that it allows split address spaces to fit more closely with the aux_domain idea, i.e. we could allocate and initialise a domain without having to assume, or even care, whether it will end up attached as a primary or aux domain. It *might* even be potentially useful to have a domain attached to TTBR0 of one device's context and TTBR1 of another's at the same time, although that's pretty niche.
Robin.
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu
Will Deacon
maintainerRe: [PATCH 4/4] iommu/io-pgtable-arm: Prepare for TTBR1 usage
Quoted 36 lines · Robin Murphy
Quoted 35 lines · Will Deacon
Quoted 19 lines · Robin Murphy
Now that callers are free to use a given table for TTBR1 if they wish (all they need do is shift the provided attributes when constructing their final TCR value), the only remaining impediment is the address validation on map/unmap. The fact that the LPAE address space split is symmetric makes this easy to accommodate - by simplifying the current range checks into explicit tests that address bits above IAS are all zero, it then follows straightforwardly to add the inverse test to allow the all-ones case as well.
Signed-off-by Robin Murphy <[email protected]>--- drivers/iommu/io-pgtable-arm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)drivers/iommu/io-pgtable-arm.c +0
-0drivers/iommu/io-pgtable-arm.c static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova, · line 482
Quoted 10 lines
drivers/iommu/io-pgtable-arm.c +2
-2@@ -475,13 +475,13 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,arm_lpae_iopte *ptep = data->pgd;int ret, lvl =ARM_LPAE_START_LVL (data);arm_lpae_iopte prot; +long iaext = (long )iova >> data->iop.cfg.ias;/* If no access, then nothing to do */ if (!(iommu_prot & (IOMMU_READ |IOMMU_WRITE )))return 0 ; -if (WARN_ON (iova >= (1ULL << data->iop.cfg.ias) || - paddr >= (1ULL << data->iop.cfg.oas))) +if (WARN_ON ((iaext && ~iaext) || paddr >> data->iop.cfg.oas))I had to read that '&&' twice, but I see what you're doing now :)
Quoted 1 line
drivers/iommu/io-pgtable-arm.c +0
-0return -ERANGE ;
Quoted 8 lines
Quoted 3 lines
This doesn't seem sufficient to prevent a mixture of TTBR1 and TTBR0 addresses from being mapped in the same TTBR. Perhaps we need a quirk for TTBR1, which could then take care of setting EPDx appropriately?
Right, that's the one downside of going for the minimalist "io-pgtable doesn't even have to know" approach. On reflection, though, in that paradigm it should probably be the caller's responsibility to convert TTBR1 addresses to preserve the "as if TTBR0" illusion anyway :/
Right, and I'd rather not push stuff into the caller for the common case. It's not exactly onerous to support this in io-pgtable. It's also why I'd still like to keep the EPDx in there, because the callers that care can rewrite the stuff, but at least we provided a default.
Quoted 6 lines
The advantage of not having a quirk is that it allows split address spaces to fit more closely with the
aux_domainidea, i.e. we could allocate and initialise a domain without having to assume, or even care, whether it will end up attached as a primary or aux domain. It *might* even be potentially useful to have a domain attached to TTBR0 of one device's context and TTBR1 of another's at the same time, although that's pretty niche.
That sounds pretty theoretical to me at the moment.
Will
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu