* 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
* [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
* [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
* 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
* 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
* 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
* 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
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).