From: Robin Murphy <robin.murphy@arm.com> Date: 2018-09-14 14:30:32
Hi all,
Since we'd like to get this polished up and merged and Leizhen has other
commitments, here's v7 of the previous series[1] wherein I address all
my own feedback :) This is a quick tweak of the v6 I sent yesterday
since I figured out slightly too late a much neater way of setting the
attribute at the appropriate time.
The principal change is that I've inverted things slightly such that
it's now a generic domain attribute controlled by iommu-dma given the
necessary support from individual IOMMU drivers. That way we can easily
enable other drivers straight away, as I've done for SMMUv2 here (which
also allowed me to give it a quick test with MMU-401s on a Juno board).
Otherwise it's really just cosmetic cleanup and rebasing onto Will's
pending SMMU queue.
Robin.
[1] https://www.mail-archive.com/iommu at lists.linux-foundation.org/msg25150.html
Robin Murphy (1):
iommu/arm-smmu: Support non-strict mode
Zhen Lei (5):
iommu/arm-smmu-v3: Implement flush_iotlb_all hook
iommu/dma: Add support for non-strict mode
iommu/io-pgtable-arm: Add support for non-strict mode
iommu: Add bootup option "iommu.non_strict"
iommu/arm-smmu-v3: Add support for non-strict mode
.../admin-guide/kernel-parameters.txt | 13 ++++++
drivers/iommu/arm-smmu-v3.c | 40 +++++++++++++++----
drivers/iommu/arm-smmu.c | 40 +++++++++++++++----
drivers/iommu/dma-iommu.c | 29 +++++++++++++-
drivers/iommu/io-pgtable-arm.c | 9 +++--
drivers/iommu/io-pgtable.h | 5 +++
drivers/iommu/iommu.c | 26 ++++++++++++
include/linux/iommu.h | 1 +
8 files changed, 145 insertions(+), 18 deletions(-)
--
2.19.0.dirty
From: Robin Murphy <robin.murphy@arm.com> Date: 2018-09-14 14:30:37
From: Zhen Lei <redacted>
.flush_iotlb_all is currently stubbed to arm_smmu_iotlb_sync() since the
only time it would ever need to actually do anything is for callers
doing their own explicit batching, e.g.:
iommu_unmap_fast(domain, ...);
iommu_unmap_fast(domain, ...);
iommu_iotlb_flush_all(domain, ...);
where since io-pgtable still issues the TLBI commands implicitly in the
unmap instead of implementing .iotlb_range_add, the "flush" only needs
to ensure completion of those already-in-flight invalidations.
However, we're about to start using it in anger with flush queues, so
let's get a proper implementation wired up.
Signed-off-by: Zhen Lei <redacted>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
[rm: expand commit message]
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/arm-smmu-v3.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
From: Robin Murphy <robin.murphy@arm.com> Date: 2018-09-14 14:30:40
From: Zhen Lei <redacted>
1. Save the related domain pointer in struct iommu_dma_cookie, make iovad
capable call domain->ops->flush_iotlb_all to flush TLB.
2. During the iommu domain initialization phase, base on domain->non_strict
field to check whether non-strict mode is supported or not. If so, call
init_iova_flush_queue to register iovad->flush_cb callback.
3. All unmap(contains iova-free) APIs will finally invoke __iommu_dma_unmap
-->iommu_dma_free_iova. If the domain is non-strict, call queue_iova to
put off iova freeing, and omit iommu_tlb_sync operation.
Signed-off-by: Zhen Lei <redacted>
[rm: convert raw boolean to domain attribute]
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/dma-iommu.c | 29 ++++++++++++++++++++++++++++-
include/linux/iommu.h | 1 +
2 files changed, 29 insertions(+), 1 deletion(-)
@@ -55,6 +55,9 @@ struct iommu_dma_cookie {};structlist_headmsi_page_list;spinlock_tmsi_lock;++/* Only be assigned in non-strict mode, otherwise it's NULL */+structiommu_domain*domain;};staticinlinesize_tcookie_msi_granule(structiommu_dma_cookie*cookie)
@@ -257,6 +260,17 @@ static int iova_reserve_iommu_regions(struct device *dev,returnret;}+staticvoidiommu_dma_flush_iotlb_all(structiova_domain*iovad)+{+structiommu_dma_cookie*cookie;+structiommu_domain*domain;++cookie=container_of(iovad,structiommu_dma_cookie,iovad);+domain=cookie->domain;++domain->ops->flush_iotlb_all(domain);+}+/***iommu_dma_init_domain-InitialiseaDMAmappingdomain*@domain:IOMMUdomainpreviouslypreparedbyiommu_get_dma_cookie()
@@ -275,6 +289,7 @@ int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,structiommu_dma_cookie*cookie=domain->iova_cookie;structiova_domain*iovad=&cookie->iovad;unsignedlongorder,base_pfn,end_pfn;+intattr=1;if(!cookie||cookie->type!=IOMMU_DMA_IOVA_COOKIE)return-EINVAL;
@@ -308,6 +323,13 @@ int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,}init_iova_domain(iovad,1UL<<order,base_pfn);++if(!iommu_domain_get_attr(domain,DOMAIN_ATTR_DMA_USE_FLUSH_QUEUE,+&attr)&&attr){+cookie->domain=domain;+init_iova_flush_queue(iovad,iommu_dma_flush_iotlb_all,NULL);+}+if(!dev)return0;
@@ -393,6 +415,9 @@ static void iommu_dma_free_iova(struct iommu_dma_cookie *cookie,/* The MSI case is only ever cleaning up its most recent allocation */if(cookie->type==IOMMU_DMA_MSI_COOKIE)cookie->msi_iova-=size;+elseif(cookie->domain)/* non-strict mode */+queue_iova(iovad,iova_pfn(iovad,iova),+size>>iova_shift(iovad),0);elsefree_iova_fast(iovad,iova_pfn(iovad,iova),size>>iova_shift(iovad));
From: Will Deacon <hidden> Date: 2018-09-18 17:09:51
Hi Robin,
On Fri, Sep 14, 2018 at 03:30:20PM +0100, Robin Murphy wrote:
From: Zhen Lei <redacted>
1. Save the related domain pointer in struct iommu_dma_cookie, make iovad
capable call domain->ops->flush_iotlb_all to flush TLB.
2. During the iommu domain initialization phase, base on domain->non_strict
field to check whether non-strict mode is supported or not. If so, call
init_iova_flush_queue to register iovad->flush_cb callback.
3. All unmap(contains iova-free) APIs will finally invoke __iommu_dma_unmap
-->iommu_dma_free_iova. If the domain is non-strict, call queue_iova to
put off iova freeing, and omit iommu_tlb_sync operation.
Hmm, this is basically just a commentary on the code. Please could you write
it more in terms of the problem that's being solved?
quoted hunk
Signed-off-by: Zhen Lei <redacted>
[rm: convert raw boolean to domain attribute]
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/dma-iommu.c | 29 ++++++++++++++++++++++++++++-
include/linux/iommu.h | 1 +
2 files changed, 29 insertions(+), 1 deletion(-)
From: Robin Murphy <robin.murphy@arm.com> Date: 2018-09-18 18:52:11
On 2018-09-18 6:10 PM, Will Deacon wrote:
Hi Robin,
On Fri, Sep 14, 2018 at 03:30:20PM +0100, Robin Murphy wrote:
quoted
From: Zhen Lei <redacted>
1. Save the related domain pointer in struct iommu_dma_cookie, make iovad
capable call domain->ops->flush_iotlb_all to flush TLB.
2. During the iommu domain initialization phase, base on domain->non_strict
field to check whether non-strict mode is supported or not. If so, call
init_iova_flush_queue to register iovad->flush_cb callback.
3. All unmap(contains iova-free) APIs will finally invoke __iommu_dma_unmap
-->iommu_dma_free_iova. If the domain is non-strict, call queue_iova to
put off iova freeing, and omit iommu_tlb_sync operation.
Hmm, this is basically just a commentary on the code. Please could you write
it more in terms of the problem that's being solved?
Sure - I intentionally kept a light touch when it came to the
documentation and commit messages in this rework (other than patch #1
where I eventually remembered the original reasoning and that it wasn't
a bug). If we're more-or-less happy with the shape of the technical side
I'll make sure to take a final pass through v8 to tidy up all the prose.
quoted
Signed-off-by: Zhen Lei <redacted>
[rm: convert raw boolean to domain attribute]
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/dma-iommu.c | 29 ++++++++++++++++++++++++++++-
include/linux/iommu.h | 1 +
2 files changed, 29 insertions(+), 1 deletion(-)
@@ -55,6 +55,9 @@ struct iommu_dma_cookie {};structlist_headmsi_page_list;spinlock_tmsi_lock;++/* Only be assigned in non-strict mode, otherwise it's NULL */+structiommu_domain*domain;};staticinlinesize_tcookie_msi_granule(structiommu_dma_cookie*cookie)
@@ -257,6 +260,17 @@ static int iova_reserve_iommu_regions(struct device *dev,returnret;}+staticvoidiommu_dma_flush_iotlb_all(structiova_domain*iovad)+{+structiommu_dma_cookie*cookie;+structiommu_domain*domain;++cookie=container_of(iovad,structiommu_dma_cookie,iovad);+domain=cookie->domain;++domain->ops->flush_iotlb_all(domain);
Can we rely on this function pointer being non-NULL? I think it would
be better to call iommu_flush_tlb_all(cookie->domain) instead.
Yeah, that's deliberate - in fact got as far as writing that change,
then undid it as I realised that although the attribute conversion got
rid of the explicit ops->flush_iotlb_all check, it still makes zero
sense for an IOMMU driver to claim to support the flush queue attribute
without also providing the relevant callback, so I do actually want this
to blow up rather than silently do nothing if that assumption isn't met.
quoted
+}
+
/**
* iommu_dma_init_domain - Initialise a DMA mapping domain
* @domain: IOMMU domain previously prepared by iommu_get_dma_cookie()
@@ -275,6 +289,7 @@ int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base, struct iommu_dma_cookie *cookie = domain->iova_cookie; struct iova_domain *iovad = &cookie->iovad; unsigned long order, base_pfn, end_pfn;+ int attr = 1;
Do we actually need to initialise this?
Oops, no, that's a left-over from the turned-out-messier-that-I-thought
v6 implementation.
Thanks,
Robin.
From: Robin Murphy <robin.murphy@arm.com> Date: 2018-09-14 14:30:42
From: Zhen Lei <redacted>
To support non-strict mode, now we only TLBI and sync for strict mode,
except for non-leaf invalidations since page table updates themselves
must always be synchronous.
To save having to reason about it too much, make sure the invalidation
in arm_lpae_split_blk_unmap() just performs its own unconditional sync
to minimise the window in which we're technically violating the break-
before-make requirement on a live mapping. This might work out redundant
with an outer-level sync for strict unmaps, but we'll never be splitting
blocks on a DMA fastpath anyway.
Signed-off-by: Zhen Lei <redacted>
[rm: tweak comment, commit message, and split_blk_unmap logic]
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/io-pgtable-arm.c | 9 ++++++---
drivers/iommu/io-pgtable.h | 5 +++++
2 files changed, 11 insertions(+), 3 deletions(-)
From: Robin Murphy <robin.murphy@arm.com> Date: 2018-09-14 14:30:44
From: Zhen Lei <redacted>
Add a bootup option to make the system manager can choose which mode to
be used. The default mode is strict.
Signed-off-by: Zhen Lei <redacted>
[rm: move handling out of SMMUv3 driver]
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
.../admin-guide/kernel-parameters.txt | 13 ++++++++++
drivers/iommu/iommu.c | 26 +++++++++++++++++++
2 files changed, 39 insertions(+)
@@ -1749,6 +1749,19 @@ nobypass [PPC/POWERNV] Disable IOMMU bypass, using IOMMU for PCI devices.+ iommu.non_strict= [ARM64]+ Format: { "0" | "1" }+ 0 - strict mode, default.+ Release IOVAs after the related TLBs are invalid+ completely.+ 1 - non-strict mode.+ Put off TLBs invalidation and release memory first.+ It's good for scatter-gather performance but lacks+ full isolation, an untrusted device can access the+ reused memory because the TLBs may still valid.+ Please take full consideration before choosing this+ mode. Note that, VFIO will always use strict mode.+ iommu.passthrough= [ARM64] Configure DMA to bypass the IOMMU by default. Format: { "0" | "1" }
@@ -41,6 +41,7 @@ static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_IDENTITY;#elsestaticunsignedintiommu_def_domain_type=IOMMU_DOMAIN_DMA;#endif+staticbooliommu_dma_non_strict__read_mostly;structiommu_callback_data{conststructiommu_ops*ops;
@@ -131,6 +132,24 @@ static int __init iommu_set_def_domain_type(char *str)}early_param("iommu.passthrough",iommu_set_def_domain_type);+staticint__initiommu_dma_setup(char*str)+{+intret;++ret=kstrtobool(str,&iommu_dma_non_strict);+if(ret)+returnret;++if(iommu_dma_non_strict){+pr_warn("WARNING: iommu non-strict mode is chosen.\n"+"It's good for scatter-gather performance but lacks full isolation\n");+add_taint(TAINT_WARN,LOCKDEP_STILL_OK);+}++return0;+}+early_param("iommu.non_strict",iommu_dma_setup);+staticssize_tiommu_group_attr_show(structkobject*kobj,structattribute*__attr,char*buf){
From: Will Deacon <hidden> Date: 2018-09-18 17:09:57
On Fri, Sep 14, 2018 at 03:30:22PM +0100, Robin Murphy wrote:
quoted hunk
From: Zhen Lei <redacted>
Add a bootup option to make the system manager can choose which mode to
be used. The default mode is strict.
Signed-off-by: Zhen Lei <redacted>
[rm: move handling out of SMMUv3 driver]
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
.../admin-guide/kernel-parameters.txt | 13 ++++++++++
drivers/iommu/iommu.c | 26 +++++++++++++++++++
2 files changed, 39 insertions(+)
@@ -1749,6 +1749,19 @@ nobypass [PPC/POWERNV] Disable IOMMU bypass, using IOMMU for PCI devices.+ iommu.non_strict= [ARM64]+ Format: { "0" | "1" }+ 0 - strict mode, default.+ Release IOVAs after the related TLBs are invalid+ completely.+ 1 - non-strict mode.+ Put off TLBs invalidation and release memory first.+ It's good for scatter-gather performance but lacks+ full isolation, an untrusted device can access the+ reused memory because the TLBs may still valid.+ Please take full consideration before choosing this+ mode. Note that, VFIO will always use strict mode.
This text needs help. How about something like:
0 - strict mode, default.
Invalidate the TLB of the IOMMU hardware as part of every
unmap() operation.
1 - lazy mode.
Defer TLB invalidation so that the TLB of the IOMMU hardware
is invalidated periodically, rather than as part of every
unmap() operation.
(generally, I think I'd s/non strict/lazy/ in this patch to avoid the double
negatives)
quoted hunk
+
iommu.passthrough=
[ARM64] Configure DMA to bypass the IOMMU by default.
Format: { "0" | "1" }
@@ -41,6 +41,7 @@ static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_IDENTITY;#elsestaticunsignedintiommu_def_domain_type=IOMMU_DOMAIN_DMA;#endif+staticbooliommu_dma_non_strict__read_mostly;structiommu_callback_data{conststructiommu_ops*ops;
@@ -131,6 +132,24 @@ static int __init iommu_set_def_domain_type(char *str)}early_param("iommu.passthrough",iommu_set_def_domain_type);+staticint__initiommu_dma_setup(char*str)+{+intret;++ret=kstrtobool(str,&iommu_dma_non_strict);+if(ret)+returnret;++if(iommu_dma_non_strict){+pr_warn("WARNING: iommu non-strict mode is chosen.\n"+"It's good for scatter-gather performance but lacks full isolation\n");
Hmm, not sure about this message either and tainting is probably over the
top. Maybe drop the taint and just pr_info something like "IOMMU DMA ops
using lazy TLB invalidation: unable to protect against malicious devices"
From: Robin Murphy <robin.murphy@arm.com> Date: 2018-09-18 19:02:00
On 2018-09-18 6:10 PM, Will Deacon wrote:
On Fri, Sep 14, 2018 at 03:30:22PM +0100, Robin Murphy wrote:
quoted
From: Zhen Lei <redacted>
Add a bootup option to make the system manager can choose which mode to
be used. The default mode is strict.
Signed-off-by: Zhen Lei <redacted>
[rm: move handling out of SMMUv3 driver]
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
.../admin-guide/kernel-parameters.txt | 13 ++++++++++
drivers/iommu/iommu.c | 26 +++++++++++++++++++
2 files changed, 39 insertions(+)
@@ -1749,6 +1749,19 @@ nobypass [PPC/POWERNV] Disable IOMMU bypass, using IOMMU for PCI devices.+ iommu.non_strict= [ARM64]+ Format: { "0" | "1" }+ 0 - strict mode, default.+ Release IOVAs after the related TLBs are invalid+ completely.+ 1 - non-strict mode.+ Put off TLBs invalidation and release memory first.+ It's good for scatter-gather performance but lacks+ full isolation, an untrusted device can access the+ reused memory because the TLBs may still valid.+ Please take full consideration before choosing this+ mode. Note that, VFIO will always use strict mode.
This text needs help. How about something like:
0 - strict mode, default.
Invalidate the TLB of the IOMMU hardware as part of every
unmap() operation.
1 - lazy mode.
Defer TLB invalidation so that the TLB of the IOMMU hardware
is invalidated periodically, rather than as part of every
unmap() operation.
(generally, I think I'd s/non strict/lazy/ in this patch to avoid the double
negatives)
quoted
+
iommu.passthrough=
[ARM64] Configure DMA to bypass the IOMMU by default.
Format: { "0" | "1" }
@@ -41,6 +41,7 @@ static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_IDENTITY;#elsestaticunsignedintiommu_def_domain_type=IOMMU_DOMAIN_DMA;#endif+staticbooliommu_dma_non_strict__read_mostly;structiommu_callback_data{conststructiommu_ops*ops;
@@ -131,6 +132,24 @@ static int __init iommu_set_def_domain_type(char *str)}early_param("iommu.passthrough",iommu_set_def_domain_type);+staticint__initiommu_dma_setup(char*str)+{+intret;++ret=kstrtobool(str,&iommu_dma_non_strict);+if(ret)+returnret;++if(iommu_dma_non_strict){+pr_warn("WARNING: iommu non-strict mode is chosen.\n"+"It's good for scatter-gather performance but lacks full isolation\n");
Hmm, not sure about this message either and tainting is probably over the
top. Maybe drop the taint and just pr_info something like "IOMMU DMA ops
using lazy TLB invalidation: unable to protect against malicious devices"
@@ -1072,6 +1091,13 @@ struct iommu_group *iommu_group_get_for_dev(struct device *dev) group->default_domain = dom; if (!group->domain) group->domain = dom;++ if (dom && iommu_dma_non_strict) {+ int attr = 1;+ iommu_domain_set_attr(dom,+ DOMAIN_ATTR_DMA_USE_FLUSH_QUEUE,+ &attr);+ }
Hmm, I don't think we can guarantee that we're working with the DMA domain
here. Does this all fall out in the wash for the identity domain?
Indeed so - for one, I expect drivers to reject it for anything that
isn't their own default DMA ops domain type (as #5 and #6 do), and
furthermore it only has any effect once iommu_dma_init_domain() reads it
back if it stuck, and other domain types should never be getting passed
into there anyway.
Robin.
From: Robin Murphy <robin.murphy@arm.com> Date: 2018-09-14 14:30:46
From: Zhen Lei <redacted>
Dynamically choose strict or non-strict mode for page table config based
on the iommu domain type.
Signed-off-by: Zhen Lei <redacted>
[rm: convert to domain attribute]
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/arm-smmu-v3.c | 30 ++++++++++++++++++++++++------
1 file changed, 24 insertions(+), 6 deletions(-)
@@ -1633,6 +1634,9 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain)if(smmu->features&ARM_SMMU_FEAT_COHERENCY)pgtbl_cfg.quirks=IO_PGTABLE_QUIRK_NO_DMA;+if(smmu_domain->non_strict)+pgtbl_cfg.quirks|=IO_PGTABLE_QUIRK_NON_STRICT;+pgtbl_ops=alloc_io_pgtable_ops(fmt,&pgtbl_cfg,smmu_domain);if(!pgtbl_ops)return-ENOMEM;
@@ -1934,13 +1938,17 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain,{structarm_smmu_domain*smmu_domain=to_smmu_domain(domain);-if(domain->type!=IOMMU_DOMAIN_UNMANAGED)-return-EINVAL;-switch(attr){caseDOMAIN_ATTR_NESTING:+if(domain->type!=IOMMU_DOMAIN_UNMANAGED)+return-EINVAL;*(int*)data=(smmu_domain->stage==ARM_SMMU_DOMAIN_NESTED);return0;+caseDOMAIN_ATTR_DMA_USE_FLUSH_QUEUE:+if(domain->type!=IOMMU_DOMAIN_DMA)+return-EINVAL;+*(int*)data=smmu_domain->non_strict;+return0;default:return-ENODEV;
Hmm, there's a change in behaviour here (and also in the set function)
which is that unknown attributes now return -ENODEV for managed domains
instead of -EINVAL. I don't know if that's a problem, but I'd be inclined
to switch on the domain type and then have a nested switch for the supported
attributes.
Will
@@ -1633,6 +1634,9 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain)if(smmu->features&ARM_SMMU_FEAT_COHERENCY)pgtbl_cfg.quirks=IO_PGTABLE_QUIRK_NO_DMA;+if(smmu_domain->non_strict)+pgtbl_cfg.quirks|=IO_PGTABLE_QUIRK_NON_STRICT;+pgtbl_ops=alloc_io_pgtable_ops(fmt,&pgtbl_cfg,smmu_domain);if(!pgtbl_ops)return-ENOMEM;
@@ -1934,13 +1938,17 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain,{structarm_smmu_domain*smmu_domain=to_smmu_domain(domain);-if(domain->type!=IOMMU_DOMAIN_UNMANAGED)-return-EINVAL;-switch(attr){caseDOMAIN_ATTR_NESTING:+if(domain->type!=IOMMU_DOMAIN_UNMANAGED)+return-EINVAL;*(int*)data=(smmu_domain->stage==ARM_SMMU_DOMAIN_NESTED);return0;+caseDOMAIN_ATTR_DMA_USE_FLUSH_QUEUE:+if(domain->type!=IOMMU_DOMAIN_DMA)+return-EINVAL;+*(int*)data=smmu_domain->non_strict;+return0;default:return-ENODEV;
Hmm, there's a change in behaviour here (and also in the set function)
which is that unknown attributes now return -ENODEV for managed domains
instead of -EINVAL. I don't know if that's a problem, but I'd be inclined
to switch on the domain type and then have a nested switch for the supported
attributes.
Sure, a nested switch did actually cross my mind, but I was worried it
might be a little boilerplate-heavy since there's still only one of each
case (and this quick'n'dirty copy-paste job didn't need any thought...)
If that's your preference too, though, I'll respin both driver patches
that way.
Robin.
From: Robin Murphy <robin.murphy@arm.com> Date: 2018-09-14 14:30:48
All we need is to wire up .flush_iotlb_all properly and implement the
domain attribute, and iommu-dma and io-pgtable-arm will do the rest for
us. Rather than bother implementing it for v7s format for the highly
unlikely chance of that being relevant, we can simply hide the
non-strict flag from io-pgtable for that combination just so anyone who
does actually try it will simply get over-invalidation instead of
failure to initialise domains.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/arm-smmu.c | 40 +++++++++++++++++++++++++++++++++-------
1 file changed, 33 insertions(+), 7 deletions(-)
From: Will Deacon <hidden> Date: 2018-09-18 17:10:04
On Fri, Sep 14, 2018 at 03:30:24PM +0100, Robin Murphy wrote:
quoted hunk
All we need is to wire up .flush_iotlb_all properly and implement the
domain attribute, and iommu-dma and io-pgtable-arm will do the rest for
us. Rather than bother implementing it for v7s format for the highly
unlikely chance of that being relevant, we can simply hide the
non-strict flag from io-pgtable for that combination just so anyone who
does actually try it will simply get over-invalidation instead of
failure to initialise domains.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/arm-smmu.c | 40 +++++++++++++++++++++++++++++++++-------
1 file changed, 33 insertions(+), 7 deletions(-)
@@ -863,6 +864,9 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,if(smmu->features&ARM_SMMU_FEAT_COHERENT_WALK)pgtbl_cfg.quirks=IO_PGTABLE_QUIRK_NO_DMA;+if(smmu_domain->non_strict&&cfg->fmt!=ARM_SMMU_CTX_FMT_AARCH32_S)+pgtbl_cfg.quirks|=IO_PGTABLE_QUIRK_NON_STRICT;
Does this mean we end up over-invalidating when using short-descriptor?
Could we not bypass the flush queue in this case instead? Ideally, we'd
just reject the domain attribute but I don't know if we know about the
page-table format early enough for that. Alternatively, we could force
long format if the attribute is set.
What do you think?
Will
From: Robin Murphy <robin.murphy@arm.com> Date: 2018-09-18 19:22:27
On 2018-09-18 6:10 PM, Will Deacon wrote:
On Fri, Sep 14, 2018 at 03:30:24PM +0100, Robin Murphy wrote:
quoted
All we need is to wire up .flush_iotlb_all properly and implement the
domain attribute, and iommu-dma and io-pgtable-arm will do the rest for
us. Rather than bother implementing it for v7s format for the highly
unlikely chance of that being relevant, we can simply hide the
non-strict flag from io-pgtable for that combination just so anyone who
does actually try it will simply get over-invalidation instead of
failure to initialise domains.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/arm-smmu.c | 40 +++++++++++++++++++++++++++++++++-------
1 file changed, 33 insertions(+), 7 deletions(-)
@@ -863,6 +864,9 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,if(smmu->features&ARM_SMMU_FEAT_COHERENT_WALK)pgtbl_cfg.quirks=IO_PGTABLE_QUIRK_NO_DMA;+if(smmu_domain->non_strict&&cfg->fmt!=ARM_SMMU_CTX_FMT_AARCH32_S)+pgtbl_cfg.quirks|=IO_PGTABLE_QUIRK_NON_STRICT;
Does this mean we end up over-invalidating when using short-descriptor?
Could we not bypass the flush queue in this case instead? Ideally, we'd
just reject the domain attribute but I don't know if we know about the
page-table format early enough for that. Alternatively, we could force
long format if the attribute is set.
What do you think?
If someone manages to run an arm64 kernel on a theoretical SMMUv2
implementation which only supports short-descriptor, *and* explicitly
sets the command-line option, then yes, they'll get both the synchronous
TLBIs and the periodic TLBIALLs. As implied by the commit message, my
natural response is "don't do that".
However, it will almost certainly take more effort to argue about it or
come up with other bodges than it will to just implement the quirk in
the v7s code, so if you really think it's a valid concern just shout.
Robin.
From: Will Deacon <hidden> Date: 2018-09-18 17:09:44
Hi Robin,
Thanks for turning this around so quickly.
On Fri, Sep 14, 2018 at 03:30:18PM +0100, Robin Murphy wrote:
Since we'd like to get this polished up and merged and Leizhen has other
commitments, here's v7 of the previous series[1] wherein I address all
my own feedback :) This is a quick tweak of the v6 I sent yesterday
since I figured out slightly too late a much neater way of setting the
attribute at the appropriate time.
The principal change is that I've inverted things slightly such that
it's now a generic domain attribute controlled by iommu-dma given the
necessary support from individual IOMMU drivers. That way we can easily
enable other drivers straight away, as I've done for SMMUv2 here (which
also allowed me to give it a quick test with MMU-401s on a Juno board).
Otherwise it's really just cosmetic cleanup and rebasing onto Will's
pending SMMU queue.
I've been through and had a look, leaving some small comments on the patches
themselves. The only part I failed to figure out is how you tie the lifetime
of the flush queue to the lifetime of the domain so that the timer callback
can't fire after e.g. the DMA cookie has been freed. How does that work?
Cheers,
Will
From: Robin Murphy <robin.murphy@arm.com> Date: 2018-09-18 18:28:36
Hi Will,
On 2018-09-18 6:10 PM, Will Deacon wrote:
Hi Robin,
Thanks for turning this around so quickly.
Cheers for a pretty rapid review too :)
On Fri, Sep 14, 2018 at 03:30:18PM +0100, Robin Murphy wrote:
quoted
Since we'd like to get this polished up and merged and Leizhen has other
commitments, here's v7 of the previous series[1] wherein I address all
my own feedback :) This is a quick tweak of the v6 I sent yesterday
since I figured out slightly too late a much neater way of setting the
attribute at the appropriate time.
The principal change is that I've inverted things slightly such that
it's now a generic domain attribute controlled by iommu-dma given the
necessary support from individual IOMMU drivers. That way we can easily
enable other drivers straight away, as I've done for SMMUv2 here (which
also allowed me to give it a quick test with MMU-401s on a Juno board).
Otherwise it's really just cosmetic cleanup and rebasing onto Will's
pending SMMU queue.
I've been through and had a look, leaving some small comments on the patches
themselves. The only part I failed to figure out is how you tie the lifetime
of the flush queue to the lifetime of the domain so that the timer callback
can't fire after e.g. the DMA cookie has been freed. How does that work?
Er, to be honest I haven't looked or even considered it! Other than the
parts I've massaged I kinda took the functionality of the previous
series for granted. Let me cross-check the x86 code and figure it out.
Robin.