[PATCH] Add API for flushing Anon pages

Currently, get_user_pages() returns fully coherent pages to the kernel for
anything other than anonymous pages.  This is a problem for things like
fuse and the SCSI generic ioctl SG_IO which can potentially wish to do DMA
to anonymous pages passed in by users.

The fix is to add a new memory management API: flush_anon_page() which
is used in get_user_pages() to make anonymous pages coherent.

Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
James Bottomley 2006-03-26 01:36:57 -08:00 committed by Linus Torvalds
parent 64a07bd82e
commit 03beb07664
3 changed files with 17 additions and 0 deletions

View file

@ -362,6 +362,15 @@ maps this page at its virtual address.
likely that you will need to flush the instruction cache likely that you will need to flush the instruction cache
for copy_to_user_page(). for copy_to_user_page().
void flush_anon_page(struct page *page, unsigned long vmaddr)
When the kernel needs to access the contents of an anonymous
page, it calls this function (currently only
get_user_pages()). Note: flush_dcache_page() deliberately
doesn't work for an anonymous page. The default
implementation is a nop (and should remain so for all coherent
architectures). For incoherent architectures, it should flush
the cache of the page at vmaddr in the current user process.
void flush_icache_range(unsigned long start, unsigned long end) void flush_icache_range(unsigned long start, unsigned long end)
When the kernel stores into addresses that it will execute When the kernel stores into addresses that it will execute
out of (eg when loading modules), this function is called. out of (eg when loading modules), this function is called.

View file

@ -7,6 +7,12 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#ifndef ARCH_HAS_FLUSH_ANON_PAGE
static inline void flush_anon_page(struct page *page, unsigned long vmaddr)
{
}
#endif
#ifdef CONFIG_HIGHMEM #ifdef CONFIG_HIGHMEM
#include <asm/highmem.h> #include <asm/highmem.h>

View file

@ -1071,6 +1071,8 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
} }
if (pages) { if (pages) {
pages[i] = page; pages[i] = page;
flush_anon_page(page, start);
flush_dcache_page(page); flush_dcache_page(page);
} }
if (vmas) if (vmas)