diff mbox series

arm64: dma-mapping: Fix FORCE_CONTIGUOUS buffer clearing

Message ID 9bd208e9187db7a934428fe44ae0906028a8c9c3.1544469820.git.robin.murphy@arm.com (mailing list archive)
State New, archived
Headers show
Series arm64: dma-mapping: Fix FORCE_CONTIGUOUS buffer clearing | expand

Commit Message

Robin Murphy Dec. 10, 2018, 7:33 p.m. UTC
We need to invalidate the caches *before* clearing the buffer via the
non-cacheable alias, else in the worst case __dma_flush_area() may
write back dirty lines over the top of our nice new zeros.

Fixes: dd65a941f6ba ("arm64: dma-mapping: clear buffers allocated with FORCE_CONTIGUOUS flag")
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
 arch/arm64/mm/dma-mapping.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Will Deacon Dec. 10, 2018, 7:36 p.m. UTC | #1
On Mon, Dec 10, 2018 at 07:33:31PM +0000, Robin Murphy wrote:
> We need to invalidate the caches *before* clearing the buffer via the
> non-cacheable alias, else in the worst case __dma_flush_area() may
> write back dirty lines over the top of our nice new zeros.
> 
> Fixes: dd65a941f6ba ("arm64: dma-mapping: clear buffers allocated with FORCE_CONTIGUOUS flag")
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> ---
>  arch/arm64/mm/dma-mapping.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
> index a3ac26284845..a53704406099 100644
> --- a/arch/arm64/mm/dma-mapping.c
> +++ b/arch/arm64/mm/dma-mapping.c
> @@ -429,9 +429,9 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
>  						   prot,
>  						   __builtin_return_address(0));
>  		if (addr) {
> -			memset(addr, 0, size);
>  			if (!coherent)
>  				__dma_flush_area(page_to_virt(page), iosize);
> +			memset(addr, 0, size);
>  		} else {
>  			iommu_dma_unmap_page(dev, *handle, iosize, 0, attrs);
>  			dma_release_from_contiguous(dev, page,

Oh crikey, well spotted!

Acked-by: Will Deacon <will.deacon@arm.com>

Catalin, please take this with a Cc stable.

Will
Catalin Marinas Dec. 11, 2018, 11:55 a.m. UTC | #2
On Mon, Dec 10, 2018 at 07:36:18PM +0000, Will Deacon wrote:
> On Mon, Dec 10, 2018 at 07:33:31PM +0000, Robin Murphy wrote:
> > We need to invalidate the caches *before* clearing the buffer via the
> > non-cacheable alias, else in the worst case __dma_flush_area() may
> > write back dirty lines over the top of our nice new zeros.
> > 
> > Fixes: dd65a941f6ba ("arm64: dma-mapping: clear buffers allocated with FORCE_CONTIGUOUS flag")
> > Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> > ---
> >  arch/arm64/mm/dma-mapping.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
> > index a3ac26284845..a53704406099 100644
> > --- a/arch/arm64/mm/dma-mapping.c
> > +++ b/arch/arm64/mm/dma-mapping.c
> > @@ -429,9 +429,9 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
> >  						   prot,
> >  						   __builtin_return_address(0));
> >  		if (addr) {
> > -			memset(addr, 0, size);
> >  			if (!coherent)
> >  				__dma_flush_area(page_to_virt(page), iosize);
> > +			memset(addr, 0, size);
> >  		} else {
> >  			iommu_dma_unmap_page(dev, *handle, iosize, 0, attrs);
> >  			dma_release_from_contiguous(dev, page,
> 
> Oh crikey, well spotted!
> 
> Acked-by: Will Deacon <will.deacon@arm.com>
> 
> Catalin, please take this with a Cc stable.

Queued. Thanks.
Chintan Pandya Dec. 12, 2018, 7:31 a.m. UTC | #3
On 12/11/2018 1:03 AM, Robin Murphy wrote:
> We need to invalidate the caches *before* clearing the buffer via the
> non-cacheable alias, else in the worst case __dma_flush_area() may
> write back dirty lines over the top of our nice new zeros.
> 
> Fixes: dd65a941f6ba ("arm64: dma-mapping: clear buffers allocated with FORCE_CONTIGUOUS flag")
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> ---
>   arch/arm64/mm/dma-mapping.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
> index a3ac26284845..a53704406099 100644
> --- a/arch/arm64/mm/dma-mapping.c
> +++ b/arch/arm64/mm/dma-mapping.c
> @@ -429,9 +429,9 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
>   						   prot,
>   						   __builtin_return_address(0));
>   		if (addr) {
> -			memset(addr, 0, size);
>   			if (!coherent)
>   				__dma_flush_area(page_to_virt(page), iosize);
> +			memset(addr, 0, size);

For coherent case, we still skip flushing/invalidating dirty kernel
mappings. Isn't it a problem ?

Shouldn't it be,

--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -774,9 +774,8 @@ static void *__iommu_alloc_attrs(struct device *dev, 
size_t size,
                                                    prot,
 
__builtin_return_address(0));
                 if (addr) {
+                       __dma_flush_area(page_to_virt(page), iosize);
                         memset(addr, 0, size);
-                       if (!coherent)
-                               __dma_flush_area(page_to_virt(page), 
iosize);
                 } else {
                         iommu_dma_unmap_page(dev, *handle, iosize, 0, 
attrs);
                         dma_release_from_contiguous(dev, page,


>   		} else {
>   			iommu_dma_unmap_page(dev, *handle, iosize, 0, attrs);
>   			dma_release_from_contiguous(dev, page,
> 

Chintan
Christoph Hellwig Dec. 12, 2018, 7:37 a.m. UTC | #4
On Wed, Dec 12, 2018 at 01:01:41PM +0530, Chintan Pandya wrote:
>>   		if (addr) {
>> -			memset(addr, 0, size);
>>   			if (!coherent)
>>   				__dma_flush_area(page_to_virt(page), iosize);
>> +			memset(addr, 0, size);
>
> For coherent case, we still skip flushing/invalidating dirty kernel
> mappings. Isn't it a problem ?

For the dma coherent case there is no need to writeback and/or invalidate
the kernel mapping.
diff mbox series

Patch

diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index a3ac26284845..a53704406099 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -429,9 +429,9 @@  static void *__iommu_alloc_attrs(struct device *dev, size_t size,
 						   prot,
 						   __builtin_return_address(0));
 		if (addr) {
-			memset(addr, 0, size);
 			if (!coherent)
 				__dma_flush_area(page_to_virt(page), iosize);
+			memset(addr, 0, size);
 		} else {
 			iommu_dma_unmap_page(dev, *handle, iosize, 0, attrs);
 			dma_release_from_contiguous(dev, page,