Commit 03beb076 authored by James Bottomley's avatar James Bottomley Committed by Linus Torvalds

[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: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 64a07bd8
...@@ -362,6 +362,15 @@ maps this page at its virtual address. ...@@ -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.
......
...@@ -7,6 +7,12 @@ ...@@ -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>
......
...@@ -1071,6 +1071,8 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, ...@@ -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)
......
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