diff options
Diffstat (limited to 'arch/avr32/mm/cache.c')
| -rw-r--r-- | arch/avr32/mm/cache.c | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/arch/avr32/mm/cache.c b/arch/avr32/mm/cache.c index 450515b245a..85d635cd7b2 100644 --- a/arch/avr32/mm/cache.c +++ b/arch/avr32/mm/cache.c @@ -13,6 +13,7 @@ #include <asm/cachectl.h> #include <asm/processor.h> #include <asm/uaccess.h> +#include <asm/syscalls.h> /* * If you attempt to flush anything more than this, you need superuser @@ -22,18 +23,30 @@ void invalidate_dcache_region(void *start, size_t size) { - unsigned long v, begin, end, linesz; + unsigned long v, begin, end, linesz, mask; linesz = boot_cpu_data.dcache.linesz; + mask = linesz - 1; - //printk("invalidate dcache: %p + %u\n", start, size); + /* when first and/or last cachelines are shared, flush them + * instead of invalidating ... never discard valid data! + */ + begin = (unsigned long)start; + end = begin + size; - /* You asked for it, you got it */ - begin = (unsigned long)start & ~(linesz - 1); - end = ((unsigned long)start + size + linesz - 1) & ~(linesz - 1); + if (begin & mask) { + flush_dcache_line(start); + begin += linesz; + } + if (end & mask) { + flush_dcache_line((void *)end); + end &= ~mask; + } + /* remaining cachelines only need invalidation */ for (v = begin; v < end; v += linesz) invalidate_dcache_line((void *)v); + flush_write_buffer(); } void clean_dcache_region(void *start, size_t size) @@ -98,29 +111,19 @@ void flush_icache_range(unsigned long start, unsigned long end) __flush_icache_range(start & ~(linesz - 1), (end + linesz - 1) & ~(linesz - 1)); } +EXPORT_SYMBOL(flush_icache_range); /* - * This one is called from do_no_page(), do_swap_page() and install_page(). + * This one is called from __do_fault() and do_swap_page(). */ void flush_icache_page(struct vm_area_struct *vma, struct page *page) { if (vma->vm_flags & VM_EXEC) { - void *v = kmap(page); + void *v = page_address(page); __flush_icache_range((unsigned long)v, (unsigned long)v + PAGE_SIZE); - kunmap(v); } } -/* - * This one is used by copy_to_user_page() - */ -void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, - unsigned long addr, int len) -{ - if (vma->vm_flags & VM_EXEC) - flush_icache_range(addr, addr + len); -} - asmlinkage int sys_cacheflush(int operation, void __user *addr, size_t len) { int ret; @@ -148,3 +151,13 @@ asmlinkage int sys_cacheflush(int operation, void __user *addr, size_t len) out: return ret; } + +void copy_to_user_page(struct vm_area_struct *vma, struct page *page, + unsigned long vaddr, void *dst, const void *src, + unsigned long len) +{ + memcpy(dst, src, len); + if (vma->vm_flags & VM_EXEC) + flush_icache_range((unsigned long)dst, + (unsigned long)dst + len); +} |
