Commit 0abdd7a8 authored by Dan Williams's avatar Dan Williams Committed by Linus Torvalds

dma-debug: introduce debug_dma_assert_idle()

Record actively mapped pages and provide an api for asserting a given
page is dma inactive before execution proceeds.  Placing
debug_dma_assert_idle() in cow_user_page() flagged the violation of the
dma-api in the NET_DMA implementation (see commit 77873803 "net_dma:
mark broken").

The implementation includes the capability to count, in a limited way,
repeat mappings of the same page that occur without an intervening
unmap.  This 'overlap' counter is limited to the few bits of tag space
in a radix tree.  This mechanism is added to mitigate false negative
cases where, for example, a page is dma mapped twice and
debug_dma_assert_idle() is called after the page is un-mapped once.
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Vinod Koul <vinod.koul@intel.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: James Bottomley <JBottomley@Parallels.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 03d11a0e
...@@ -85,6 +85,8 @@ extern void debug_dma_sync_sg_for_device(struct device *dev, ...@@ -85,6 +85,8 @@ extern void debug_dma_sync_sg_for_device(struct device *dev,
extern void debug_dma_dump_mappings(struct device *dev); extern void debug_dma_dump_mappings(struct device *dev);
extern void debug_dma_assert_idle(struct page *page);
#else /* CONFIG_DMA_API_DEBUG */ #else /* CONFIG_DMA_API_DEBUG */
static inline void dma_debug_add_bus(struct bus_type *bus) static inline void dma_debug_add_bus(struct bus_type *bus)
...@@ -183,6 +185,10 @@ static inline void debug_dma_dump_mappings(struct device *dev) ...@@ -183,6 +185,10 @@ static inline void debug_dma_dump_mappings(struct device *dev)
{ {
} }
static inline void debug_dma_assert_idle(struct page *page)
{
}
#endif /* CONFIG_DMA_API_DEBUG */ #endif /* CONFIG_DMA_API_DEBUG */
#endif /* __DMA_DEBUG_H */ #endif /* __DMA_DEBUG_H */
...@@ -1584,8 +1584,16 @@ config DMA_API_DEBUG ...@@ -1584,8 +1584,16 @@ config DMA_API_DEBUG
With this option you will be able to detect common bugs in device With this option you will be able to detect common bugs in device
drivers like double-freeing of DMA mappings or freeing mappings that drivers like double-freeing of DMA mappings or freeing mappings that
were never allocated. were never allocated.
This option causes a performance degredation. Use only if you want
to debug device drivers. If unsure, say N. This also attempts to catch cases where a page owned by DMA is
accessed by the cpu in a way that could cause data corruption. For
example, this enables cow_user_page() to check that the source page is
not undergoing DMA.
This option causes a performance degradation. Use only if you want to
debug device drivers and dma interactions.
If unsure, say N.
source "samples/Kconfig" source "samples/Kconfig"
......
This diff is collapsed.
...@@ -59,6 +59,7 @@ ...@@ -59,6 +59,7 @@
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/migrate.h> #include <linux/migrate.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/dma-debug.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
...@@ -2559,6 +2560,8 @@ static inline int pte_unmap_same(struct mm_struct *mm, pmd_t *pmd, ...@@ -2559,6 +2560,8 @@ static inline int pte_unmap_same(struct mm_struct *mm, pmd_t *pmd,
static inline void cow_user_page(struct page *dst, struct page *src, unsigned long va, struct vm_area_struct *vma) static inline void cow_user_page(struct page *dst, struct page *src, unsigned long va, struct vm_area_struct *vma)
{ {
debug_dma_assert_idle(src);
/* /*
* If the source page was a PFN mapping, we don't have * If the source page was a PFN mapping, we don't have
* a "struct page" for it. We do a best-effort copy by * a "struct page" for it. We do a best-effort copy by
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment