aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/flush.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2009-11-05 08:29:36 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2009-12-14 09:54:28 -0500
commit2ef7f3dbd7a70a48c3f09b498df528cb00ea03a4 (patch)
treeed6478d2eb2a9062b6f586acd4cc28ac0cfe30a5 /arch/arm/mm/flush.c
parentbf32eb85492af197ea5ff20e0be56f667a80584d (diff)
ARM: Fix ptrace accesses
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm/flush.c')
-rw-r--r--arch/arm/mm/flush.c51
1 files changed, 43 insertions, 8 deletions
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 6f3a4b7a3b82..e34f095e2090 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -13,6 +13,7 @@
13 13
14#include <asm/cacheflush.h> 14#include <asm/cacheflush.h>
15#include <asm/cachetype.h> 15#include <asm/cachetype.h>
16#include <asm/smp_plat.h>
16#include <asm/system.h> 17#include <asm/system.h>
17#include <asm/tlbflush.h> 18#include <asm/tlbflush.h>
18 19
@@ -87,13 +88,26 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsig
87 if (vma->vm_flags & VM_EXEC && icache_is_vivt_asid_tagged()) 88 if (vma->vm_flags & VM_EXEC && icache_is_vivt_asid_tagged())
88 __flush_icache_all(); 89 __flush_icache_all();
89} 90}
91#else
92#define flush_pfn_alias(pfn,vaddr) do { } while (0)
93#endif
90 94
95#ifdef CONFIG_SMP
96static void flush_ptrace_access_other(void *args)
97{
98 __flush_icache_all();
99}
100#endif
101
102static
91void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, 103void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
92 unsigned long uaddr, void *kaddr, 104 unsigned long uaddr, void *kaddr, unsigned long len)
93 unsigned long len, int write)
94{ 105{
95 if (cache_is_vivt()) { 106 if (cache_is_vivt()) {
96 vivt_flush_ptrace_access(vma, page, uaddr, kaddr, len, write); 107 if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) {
108 unsigned long addr = (unsigned long)kaddr;
109 __cpuc_coherent_kern_range(addr, addr + len);
110 }
97 return; 111 return;
98 } 112 }
99 113
@@ -104,16 +118,37 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
104 } 118 }
105 119
106 /* VIPT non-aliasing cache */ 120 /* VIPT non-aliasing cache */
107 if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm)) && 121 if (vma->vm_flags & VM_EXEC) {
108 vma->vm_flags & VM_EXEC) {
109 unsigned long addr = (unsigned long)kaddr; 122 unsigned long addr = (unsigned long)kaddr;
110 /* only flushing the kernel mapping on non-aliasing VIPT */
111 __cpuc_coherent_kern_range(addr, addr + len); 123 __cpuc_coherent_kern_range(addr, addr + len);
124#ifdef CONFIG_SMP
125 if (cache_ops_need_broadcast())
126 smp_call_function(flush_ptrace_access_other,
127 NULL, 1);
128#endif
112 } 129 }
113} 130}
114#else 131
115#define flush_pfn_alias(pfn,vaddr) do { } while (0) 132/*
133 * Copy user data from/to a page which is mapped into a different
134 * processes address space. Really, we want to allow our "user
135 * space" model to handle this.
136 *
137 * Note that this code needs to run on the current CPU.
138 */
139void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
140 unsigned long uaddr, void *dst, const void *src,
141 unsigned long len)
142{
143#ifdef CONFIG_SMP
144 preempt_disable();
116#endif 145#endif
146 memcpy(dst, src, len);
147 flush_ptrace_access(vma, page, uaddr, dst, len);
148#ifdef CONFIG_SMP
149 preempt_enable();
150#endif
151}
117 152
118void __flush_dcache_page(struct address_space *mapping, struct page *page) 153void __flush_dcache_page(struct address_space *mapping, struct page *page)
119{ 154{