* two dma-direct fixes for 4.18
@ 2018-08-24 6:53 Christoph Hellwig
[not found] ` <20180824065324.654-1-hch-jcswGhMUV9g@public.gmane.org>
0 siblings, 1 reply; 7+ messages in thread
From: Christoph Hellwig @ 2018-08-24 6:53 UTC (permalink / raw)
To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
Cc: thomas.lendacky-5C7GfCeVMHo, robin.murphy-5wv7dgnIgG8
Ensure we properly take the phys_to_dma translations into account when
checking dma masks.
^ permalink raw reply [flat|nested] 7+ messages in thread[parent not found: <20180824065324.654-1-hch-jcswGhMUV9g@public.gmane.org>]
* [PATCH 1/2] kernel/dma/direct: take DMA offset into account in dma_direct_supported [not found] ` <20180824065324.654-1-hch-jcswGhMUV9g@public.gmane.org> @ 2018-08-24 6:53 ` Christoph Hellwig [not found] ` <20180824065324.654-2-hch-jcswGhMUV9g@public.gmane.org> 2018-08-24 6:53 ` [PATCH 2/2] kernel/dma/direct: refine dma_direct_alloc zone selection Christoph Hellwig 1 sibling, 1 reply; 7+ messages in thread From: Christoph Hellwig @ 2018-08-24 6:53 UTC (permalink / raw) To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA Cc: thomas.lendacky-5C7GfCeVMHo, robin.murphy-5wv7dgnIgG8 When a device has a DMA offset the dma capable result will change due to the difference between the physical and DMA address. Take that into account. Signed-off-by: Christoph Hellwig <hch-jcswGhMUV9g@public.gmane.org> Reviewed-by: Benjamin Herrenschmidt <benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org> --- kernel/dma/direct.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c index 1c35b7b945d0..de87b0282e74 100644 --- a/kernel/dma/direct.c +++ b/kernel/dma/direct.c @@ -168,7 +168,7 @@ int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, int nents, int dma_direct_supported(struct device *dev, u64 mask) { #ifdef CONFIG_ZONE_DMA - if (mask < DMA_BIT_MASK(ARCH_ZONE_DMA_BITS)) + if (mask < phys_to_dma(dev, DMA_BIT_MASK(ARCH_ZONE_DMA_BITS))) return 0; #else /* @@ -177,7 +177,7 @@ int dma_direct_supported(struct device *dev, u64 mask) * memory, or by providing a ZONE_DMA32. If neither is the case, the * architecture needs to use an IOMMU instead of the direct mapping. */ - if (mask < DMA_BIT_MASK(32)) + if (mask < phys_to_dma(dev, DMA_BIT_MASK(32))) return 0; #endif /* -- 2.18.0 ^ permalink raw reply related [flat|nested] 7+ messages in thread
[parent not found: <20180824065324.654-2-hch-jcswGhMUV9g@public.gmane.org>]
* Re: [PATCH 1/2] kernel/dma/direct: take DMA offset into account in dma_direct_supported [not found] ` <20180824065324.654-2-hch-jcswGhMUV9g@public.gmane.org> @ 2018-08-24 11:11 ` Robin Murphy [not found] ` <0e95df80-38f7-7970-ef74-419567f13fdc-5wv7dgnIgG8@public.gmane.org> 0 siblings, 1 reply; 7+ messages in thread From: Robin Murphy @ 2018-08-24 11:11 UTC (permalink / raw) To: Christoph Hellwig, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA Cc: thomas.lendacky-5C7GfCeVMHo On 24/08/18 07:53, Christoph Hellwig wrote: > When a device has a DMA offset the dma capable result will change due > to the difference between the physical and DMA address. Take that into > account. The "phys_to_dma(..., DMA_BIT_MASK(...))" idiom always looks like a glaring error at first glance, but this whole function is fairly unintuitive anyway, and ultimately I think the change does work out to be correct. It might be nicer if we could reference max_zone_pfns[] for a bit more clarity, but I guess that's not arch-independent. Reviewed-by: Robin Murphy <robin.murphy-5wv7dgnIgG8@public.gmane.org> > Signed-off-by: Christoph Hellwig <hch-jcswGhMUV9g@public.gmane.org> > Reviewed-by: Benjamin Herrenschmidt <benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org> > --- > kernel/dma/direct.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c > index 1c35b7b945d0..de87b0282e74 100644 > --- a/kernel/dma/direct.c > +++ b/kernel/dma/direct.c > @@ -168,7 +168,7 @@ int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, int nents, > int dma_direct_supported(struct device *dev, u64 mask) > { > #ifdef CONFIG_ZONE_DMA > - if (mask < DMA_BIT_MASK(ARCH_ZONE_DMA_BITS)) > + if (mask < phys_to_dma(dev, DMA_BIT_MASK(ARCH_ZONE_DMA_BITS))) > return 0; > #else > /* > @@ -177,7 +177,7 @@ int dma_direct_supported(struct device *dev, u64 mask) > * memory, or by providing a ZONE_DMA32. If neither is the case, the > * architecture needs to use an IOMMU instead of the direct mapping. > */ > - if (mask < DMA_BIT_MASK(32)) > + if (mask < phys_to_dma(dev, DMA_BIT_MASK(32))) > return 0; > #endif > /* > ^ permalink raw reply [flat|nested] 7+ messages in thread
[parent not found: <0e95df80-38f7-7970-ef74-419567f13fdc-5wv7dgnIgG8@public.gmane.org>]
* Re: [PATCH 1/2] kernel/dma/direct: take DMA offset into account in dma_direct_supported [not found] ` <0e95df80-38f7-7970-ef74-419567f13fdc-5wv7dgnIgG8@public.gmane.org> @ 2018-08-29 16:59 ` Christoph Hellwig 0 siblings, 0 replies; 7+ messages in thread From: Christoph Hellwig @ 2018-08-29 16:59 UTC (permalink / raw) To: Robin Murphy Cc: thomas.lendacky-5C7GfCeVMHo, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Christoph Hellwig On Fri, Aug 24, 2018 at 12:11:23PM +0100, Robin Murphy wrote: > On 24/08/18 07:53, Christoph Hellwig wrote: >> When a device has a DMA offset the dma capable result will change due >> to the difference between the physical and DMA address. Take that into >> account. > > The "phys_to_dma(..., DMA_BIT_MASK(...))" idiom always looks like a glaring > error at first glance, but this whole function is fairly unintuitive > anyway, and ultimately I think the change does work out to be correct. > > It might be nicer if we could reference max_zone_pfns[] for a bit more > clarity, but I guess that's not arch-independent. Not just arch specific, but also local variables. There is arch_zone_lowest_possible_pfn in page_alloc.c, but that gets discarded after init. That being said this is the right direction and I'll look into it for 4.20 or later. ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/2] kernel/dma/direct: refine dma_direct_alloc zone selection [not found] ` <20180824065324.654-1-hch-jcswGhMUV9g@public.gmane.org> 2018-08-24 6:53 ` [PATCH 1/2] kernel/dma/direct: take DMA offset into account in dma_direct_supported Christoph Hellwig @ 2018-08-24 6:53 ` Christoph Hellwig [not found] ` <20180824065324.654-3-hch-jcswGhMUV9g@public.gmane.org> 1 sibling, 1 reply; 7+ messages in thread From: Christoph Hellwig @ 2018-08-24 6:53 UTC (permalink / raw) To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA Cc: thomas.lendacky-5C7GfCeVMHo, robin.murphy-5wv7dgnIgG8 We need to take the DMA offset and encryption bit into account when selecting a zone. Add a helper that takes those into account and use it. Signed-off-by: Christoph Hellwig <hch-jcswGhMUV9g@public.gmane.org> --- kernel/dma/direct.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c index de87b0282e74..3f8b596ea393 100644 --- a/kernel/dma/direct.c +++ b/kernel/dma/direct.c @@ -58,6 +58,14 @@ static bool dma_coherent_ok(struct device *dev, phys_addr_t phys, size_t size) return addr + size - 1 <= dev->coherent_dma_mask; } +static bool dma_coherent_below(struct device *dev, u64 mask) +{ + dma_addr_t addr = force_dma_unencrypted() ? + __phys_to_dma(dev, mask) : phys_to_dma(dev, mask); + + return dev->coherent_dma_mask <= addr; +} + void *dma_direct_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs) { @@ -70,9 +78,9 @@ void *dma_direct_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp &= ~__GFP_ZERO; /* GFP_DMA32 and GFP_DMA are no ops without the corresponding zones: */ - if (dev->coherent_dma_mask <= DMA_BIT_MASK(ARCH_ZONE_DMA_BITS)) + if (dma_coherent_below(dev, DMA_BIT_MASK(ARCH_ZONE_DMA_BITS))) gfp |= GFP_DMA; - if (dev->coherent_dma_mask <= DMA_BIT_MASK(32) && !(gfp & GFP_DMA)) + if (dma_coherent_below(dev, DMA_BIT_MASK(32) && !(gfp & GFP_DMA))) gfp |= GFP_DMA32; again: @@ -93,14 +101,14 @@ void *dma_direct_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, page = NULL; if (IS_ENABLED(CONFIG_ZONE_DMA32) && - dev->coherent_dma_mask < DMA_BIT_MASK(64) && + dma_coherent_below(dev, DMA_BIT_MASK(64)) && !(gfp & (GFP_DMA32 | GFP_DMA))) { gfp |= GFP_DMA32; goto again; } if (IS_ENABLED(CONFIG_ZONE_DMA) && - dev->coherent_dma_mask < DMA_BIT_MASK(32) && + dma_coherent_below(dev, DMA_BIT_MASK(32)) && !(gfp & GFP_DMA)) { gfp = (gfp & ~GFP_DMA32) | GFP_DMA; goto again; -- 2.18.0 ^ permalink raw reply related [flat|nested] 7+ messages in thread
[parent not found: <20180824065324.654-3-hch-jcswGhMUV9g@public.gmane.org>]
* Re: [PATCH 2/2] kernel/dma/direct: refine dma_direct_alloc zone selection [not found] ` <20180824065324.654-3-hch-jcswGhMUV9g@public.gmane.org> @ 2018-08-24 11:38 ` Robin Murphy [not found] ` <bfba5bae-a88c-f777-ba1f-f0db310904dc-5wv7dgnIgG8@public.gmane.org> 0 siblings, 1 reply; 7+ messages in thread From: Robin Murphy @ 2018-08-24 11:38 UTC (permalink / raw) To: Christoph Hellwig, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA Cc: thomas.lendacky-5C7GfCeVMHo On 24/08/18 07:53, Christoph Hellwig wrote: > We need to take the DMA offset and encryption bit into account when selecting > a zone. Add a helper that takes those into account and use it. > > Signed-off-by: Christoph Hellwig <hch-jcswGhMUV9g@public.gmane.org> > --- > kernel/dma/direct.c | 16 ++++++++++++---- > 1 file changed, 12 insertions(+), 4 deletions(-) > > diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c > index de87b0282e74..3f8b596ea393 100644 > --- a/kernel/dma/direct.c > +++ b/kernel/dma/direct.c > @@ -58,6 +58,14 @@ static bool dma_coherent_ok(struct device *dev, phys_addr_t phys, size_t size) > return addr + size - 1 <= dev->coherent_dma_mask; > } > > +static bool dma_coherent_below(struct device *dev, u64 mask) > +{ > + dma_addr_t addr = force_dma_unencrypted() ? > + __phys_to_dma(dev, mask) : phys_to_dma(dev, mask); > + > + return dev->coherent_dma_mask <= addr; > +} > + > void *dma_direct_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, > gfp_t gfp, unsigned long attrs) > { > @@ -70,9 +78,9 @@ void *dma_direct_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, > gfp &= ~__GFP_ZERO; > > /* GFP_DMA32 and GFP_DMA are no ops without the corresponding zones: */ > - if (dev->coherent_dma_mask <= DMA_BIT_MASK(ARCH_ZONE_DMA_BITS)) > + if (dma_coherent_below(dev, DMA_BIT_MASK(ARCH_ZONE_DMA_BITS))) > gfp |= GFP_DMA; > - if (dev->coherent_dma_mask <= DMA_BIT_MASK(32) && !(gfp & GFP_DMA)) > + if (dma_coherent_below(dev, DMA_BIT_MASK(32) && !(gfp & GFP_DMA))) > gfp |= GFP_DMA32; > > again: > @@ -93,14 +101,14 @@ void *dma_direct_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, > page = NULL; > > if (IS_ENABLED(CONFIG_ZONE_DMA32) && > - dev->coherent_dma_mask < DMA_BIT_MASK(64) && We're effectively changing the "<" into a "<="... > + dma_coherent_below(dev, DMA_BIT_MASK(64)) && ...which I think means this check now *always* returns true... > !(gfp & (GFP_DMA32 | GFP_DMA))) { > gfp |= GFP_DMA32; > goto again; > } > > if (IS_ENABLED(CONFIG_ZONE_DMA) && > - dev->coherent_dma_mask < DMA_BIT_MASK(32) && > + dma_coherent_below(dev, DMA_BIT_MASK(32)) && ...and this one subtly changes WRT ZONE_DMA32, but I can't quite figure out how much that matters :/ Robin. > !(gfp & GFP_DMA)) { > gfp = (gfp & ~GFP_DMA32) | GFP_DMA; > goto again; > ^ permalink raw reply [flat|nested] 7+ messages in thread
[parent not found: <bfba5bae-a88c-f777-ba1f-f0db310904dc-5wv7dgnIgG8@public.gmane.org>]
* Re: [PATCH 2/2] kernel/dma/direct: refine dma_direct_alloc zone selection [not found] ` <bfba5bae-a88c-f777-ba1f-f0db310904dc-5wv7dgnIgG8@public.gmane.org> @ 2018-08-24 11:49 ` Robin Murphy 0 siblings, 0 replies; 7+ messages in thread From: Robin Murphy @ 2018-08-24 11:49 UTC (permalink / raw) To: Christoph Hellwig, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA Cc: thomas.lendacky-5C7GfCeVMHo On 24/08/18 12:38, Robin Murphy wrote: > On 24/08/18 07:53, Christoph Hellwig wrote: >> We need to take the DMA offset and encryption bit into account when >> selecting >> a zone. Add a helper that takes those into account and use it. >> >> Signed-off-by: Christoph Hellwig <hch@lst.de> >> --- >> kernel/dma/direct.c | 16 ++++++++++++---- >> 1 file changed, 12 insertions(+), 4 deletions(-) >> >> diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c >> index de87b0282e74..3f8b596ea393 100644 >> --- a/kernel/dma/direct.c >> +++ b/kernel/dma/direct.c >> @@ -58,6 +58,14 @@ static bool dma_coherent_ok(struct device *dev, >> phys_addr_t phys, size_t size) >> return addr + size - 1 <= dev->coherent_dma_mask; >> } >> +static bool dma_coherent_below(struct device *dev, u64 mask) >> +{ >> + dma_addr_t addr = force_dma_unencrypted() ? >> + __phys_to_dma(dev, mask) : phys_to_dma(dev, mask); >> + >> + return dev->coherent_dma_mask <= addr; >> +} >> + >> void *dma_direct_alloc(struct device *dev, size_t size, dma_addr_t >> *dma_handle, >> gfp_t gfp, unsigned long attrs) >> { >> @@ -70,9 +78,9 @@ void *dma_direct_alloc(struct device *dev, size_t >> size, dma_addr_t *dma_handle, >> gfp &= ~__GFP_ZERO; >> /* GFP_DMA32 and GFP_DMA are no ops without the corresponding >> zones: */ >> - if (dev->coherent_dma_mask <= DMA_BIT_MASK(ARCH_ZONE_DMA_BITS)) >> + if (dma_coherent_below(dev, DMA_BIT_MASK(ARCH_ZONE_DMA_BITS))) >> gfp |= GFP_DMA; >> - if (dev->coherent_dma_mask <= DMA_BIT_MASK(32) && !(gfp & GFP_DMA)) >> + if (dma_coherent_below(dev, DMA_BIT_MASK(32) && !(gfp & GFP_DMA))) >> gfp |= GFP_DMA32; >> again: >> @@ -93,14 +101,14 @@ void *dma_direct_alloc(struct device *dev, size_t >> size, dma_addr_t *dma_handle, >> page = NULL; >> if (IS_ENABLED(CONFIG_ZONE_DMA32) && >> - dev->coherent_dma_mask < DMA_BIT_MASK(64) && > > We're effectively changing the "<" into a "<="... > >> + dma_coherent_below(dev, DMA_BIT_MASK(64)) && > > ...which I think means this check now *always* returns true... Although on closer inspection that was effectively already the case - we could never get here if dev->coherent_dma_mask == DMA_BIT_MASK(64), because dma_coherent_ok() couldn't possibly have returned false in the first place. So this one was always unnecessary. Robin. _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2018-08-29 16:59 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-08-24 6:53 two dma-direct fixes for 4.18 Christoph Hellwig
[not found] ` <20180824065324.654-1-hch-jcswGhMUV9g@public.gmane.org>
2018-08-24 6:53 ` [PATCH 1/2] kernel/dma/direct: take DMA offset into account in dma_direct_supported Christoph Hellwig
[not found] ` <20180824065324.654-2-hch-jcswGhMUV9g@public.gmane.org>
2018-08-24 11:11 ` Robin Murphy
[not found] ` <0e95df80-38f7-7970-ef74-419567f13fdc-5wv7dgnIgG8@public.gmane.org>
2018-08-29 16:59 ` Christoph Hellwig
2018-08-24 6:53 ` [PATCH 2/2] kernel/dma/direct: refine dma_direct_alloc zone selection Christoph Hellwig
[not found] ` <20180824065324.654-3-hch-jcswGhMUV9g@public.gmane.org>
2018-08-24 11:38 ` Robin Murphy
[not found] ` <bfba5bae-a88c-f777-ba1f-f0db310904dc-5wv7dgnIgG8@public.gmane.org>
2018-08-24 11:49 ` Robin Murphy
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).