diff options
| -rw-r--r-- | arch/arm/mm/flush.c | 26 | ||||
| -rw-r--r-- | include/asm-arm/cacheflush.h | 18 |
2 files changed, 41 insertions, 3 deletions
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index b103e56806bd..d438ce41cdd5 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c | |||
| @@ -87,6 +87,32 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsig | |||
| 87 | if (cache_is_vipt_aliasing()) | 87 | if (cache_is_vipt_aliasing()) |
| 88 | flush_pfn_alias(pfn, user_addr); | 88 | flush_pfn_alias(pfn, user_addr); |
| 89 | } | 89 | } |
| 90 | |||
| 91 | void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, | ||
| 92 | unsigned long uaddr, void *kaddr, | ||
| 93 | unsigned long len, int write) | ||
| 94 | { | ||
| 95 | if (cache_is_vivt()) { | ||
| 96 | if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) { | ||
| 97 | unsigned long addr = (unsigned long)kaddr; | ||
| 98 | __cpuc_coherent_kern_range(addr, addr + len); | ||
| 99 | } | ||
| 100 | return; | ||
| 101 | } | ||
| 102 | |||
| 103 | if (cache_is_vipt_aliasing()) { | ||
| 104 | flush_pfn_alias(page_to_pfn(page), uaddr); | ||
| 105 | return; | ||
| 106 | } | ||
| 107 | |||
| 108 | /* VIPT non-aliasing cache */ | ||
| 109 | if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask) && | ||
| 110 | vma->vm_flags | VM_EXEC) { | ||
| 111 | unsigned long addr = (unsigned long)kaddr; | ||
| 112 | /* only flushing the kernel mapping on non-aliasing VIPT */ | ||
| 113 | __cpuc_coherent_kern_range(addr, addr + len); | ||
| 114 | } | ||
| 115 | } | ||
| 90 | #else | 116 | #else |
| 91 | #define flush_pfn_alias(pfn,vaddr) do { } while (0) | 117 | #define flush_pfn_alias(pfn,vaddr) do { } while (0) |
| 92 | #endif | 118 | #endif |
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h index fe0c744e0266..e4a2569c636c 100644 --- a/include/asm-arm/cacheflush.h +++ b/include/asm-arm/cacheflush.h | |||
| @@ -247,14 +247,12 @@ extern void dmac_flush_range(unsigned long, unsigned long); | |||
| 247 | */ | 247 | */ |
| 248 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ | 248 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ |
| 249 | do { \ | 249 | do { \ |
| 250 | flush_cache_page(vma, vaddr, page_to_pfn(page));\ | ||
| 251 | memcpy(dst, src, len); \ | 250 | memcpy(dst, src, len); \ |
| 252 | flush_dcache_page(page); \ | 251 | flush_ptrace_access(vma, page, vaddr, dst, len, 1);\ |
| 253 | } while (0) | 252 | } while (0) |
| 254 | 253 | ||
| 255 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ | 254 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ |
| 256 | do { \ | 255 | do { \ |
| 257 | flush_cache_page(vma, vaddr, page_to_pfn(page));\ | ||
| 258 | memcpy(dst, src, len); \ | 256 | memcpy(dst, src, len); \ |
| 259 | } while (0) | 257 | } while (0) |
| 260 | 258 | ||
| @@ -285,10 +283,24 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned l | |||
| 285 | __cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags); | 283 | __cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags); |
| 286 | } | 284 | } |
| 287 | } | 285 | } |
| 286 | |||
| 287 | static inline void | ||
| 288 | flush_ptrace_access(struct vm_area_struct *vma, struct page *page, | ||
| 289 | unsigned long uaddr, void *kaddr, | ||
| 290 | unsigned long len, int write) | ||
| 291 | { | ||
| 292 | if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) { | ||
| 293 | unsigned long addr = (unsigned long)kaddr; | ||
| 294 | __cpuc_coherent_kern_range(addr, addr + len); | ||
| 295 | } | ||
| 296 | } | ||
| 288 | #else | 297 | #else |
| 289 | extern void flush_cache_mm(struct mm_struct *mm); | 298 | extern void flush_cache_mm(struct mm_struct *mm); |
| 290 | extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); | 299 | extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); |
| 291 | extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn); | 300 | extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn); |
| 301 | extern void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, | ||
| 302 | unsigned long uaddr, void *kaddr, | ||
| 303 | unsigned long len, int write); | ||
| 292 | #endif | 304 | #endif |
| 293 | 305 | ||
| 294 | /* | 306 | /* |
