[AVR32] Fix copy_to_user_page() breakage

The current implementation of copy_to_user_page() gives "vaddr" to the
cache instruction when trying to sync the icache with the dcache. If
vaddr does not exist in the TLB, the CPU will silently abort the
operation, which may result in the caches staying out of sync.

To fix this, pass the "dst" parameter to flush_icache_range() instead
-- we know this is valid because we just wrote to it.

Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>

+20 -19
+10 -10
arch/avr32/mm/cache.c
··· 122 } 123 } 124 125 - /* 126 - * This one is used by copy_to_user_page() 127 - */ 128 - void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, 129 - unsigned long addr, int len) 130 - { 131 - if (vma->vm_flags & VM_EXEC) 132 - flush_icache_range(addr, addr + len); 133 - } 134 - 135 asmlinkage int sys_cacheflush(int operation, void __user *addr, size_t len) 136 { 137 int ret; ··· 148 149 out: 150 return ret; 151 }
··· 122 } 123 } 124 125 asmlinkage int sys_cacheflush(int operation, void __user *addr, size_t len) 126 { 127 int ret; ··· 158 159 out: 160 return ret; 161 + } 162 + 163 + void copy_to_user_page(struct vm_area_struct *vma, struct page *page, 164 + unsigned long vaddr, void *dst, const void *src, 165 + unsigned long len) 166 + { 167 + memcpy(dst, src, len); 168 + if (vma->vm_flags & VM_EXEC) 169 + flush_icache_range((unsigned long)dst, 170 + (unsigned long)dst + len); 171 }
+10 -9
include/asm-avr32/cacheflush.h
··· 116 * flush with all configurations. 117 */ 118 extern void flush_icache_range(unsigned long start, unsigned long end); 119 - extern void flush_icache_user_range(struct vm_area_struct *vma, 120 - struct page *page, 121 - unsigned long addr, int len); 122 123 - #define copy_to_user_page(vma, page, vaddr, dst, src, len) do { \ 124 - memcpy(dst, src, len); \ 125 - flush_icache_user_range(vma, page, vaddr, len); \ 126 - } while(0) 127 - #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ 128 - memcpy(dst, src, len) 129 130 #endif /* __ASM_AVR32_CACHEFLUSH_H */
··· 116 * flush with all configurations. 117 */ 118 extern void flush_icache_range(unsigned long start, unsigned long end); 119 120 + extern void copy_to_user_page(struct vm_area_struct *vma, struct page *page, 121 + unsigned long vaddr, void *dst, const void *src, 122 + unsigned long len); 123 + 124 + static inline void copy_from_user_page(struct vm_area_struct *vma, 125 + struct page *page, unsigned long vaddr, void *dst, 126 + const void *src, unsigned long len) 127 + { 128 + memcpy(dst, src, len); 129 + } 130 131 #endif /* __ASM_AVR32_CACHEFLUSH_H */