aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mm/flush.c26
-rw-r--r--include/asm-arm/cacheflush.h18
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
91void 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
287static inline void
288flush_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
289extern void flush_cache_mm(struct mm_struct *mm); 298extern void flush_cache_mm(struct mm_struct *mm);
290extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); 299extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
291extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn); 300extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn);
301extern 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/*