diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2009-10-06 12:57:09 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-10-07 08:12:59 -0400 |
commit | 32cfb1b16f2b68d2296536811cadfffe26a06c1b (patch) | |
tree | 6872f034656cc4ffb80ba51f9b29c35bb8da9f9e /arch/arm/mm | |
parent | cc1ad4a69667be885ac6036a315066854ef8c871 (diff) |
ARM: 5746/1: Handle possible translation errors in ARMv6/v7 coherent_user_range
This is needed because applications using the sys_cacheflush system call
can pass a memory range which isn't mapped yet even though the
corresponding vma is valid. The patch also adds unwinding annotations
for correct backtraces from the coherent_user_range() functions.
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/cache-v6.S | 20 | ||||
-rw-r--r-- | arch/arm/mm/cache-v7.S | 19 |
2 files changed, 35 insertions, 4 deletions
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index 8f5c13f4c936..295e25dd6381 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/linkage.h> | 12 | #include <linux/linkage.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <asm/assembler.h> | 14 | #include <asm/assembler.h> |
15 | #include <asm/unwind.h> | ||
15 | 16 | ||
16 | #include "proc-macros.S" | 17 | #include "proc-macros.S" |
17 | 18 | ||
@@ -121,11 +122,13 @@ ENTRY(v6_coherent_kern_range) | |||
121 | * - the Icache does not read data from the write buffer | 122 | * - the Icache does not read data from the write buffer |
122 | */ | 123 | */ |
123 | ENTRY(v6_coherent_user_range) | 124 | ENTRY(v6_coherent_user_range) |
124 | 125 | UNWIND(.fnstart ) | |
125 | #ifdef HARVARD_CACHE | 126 | #ifdef HARVARD_CACHE |
126 | bic r0, r0, #CACHE_LINE_SIZE - 1 | 127 | bic r0, r0, #CACHE_LINE_SIZE - 1 |
127 | 1: mcr p15, 0, r0, c7, c10, 1 @ clean D line | 128 | 1: |
129 | USER( mcr p15, 0, r0, c7, c10, 1 ) @ clean D line | ||
128 | add r0, r0, #CACHE_LINE_SIZE | 130 | add r0, r0, #CACHE_LINE_SIZE |
131 | 2: | ||
129 | cmp r0, r1 | 132 | cmp r0, r1 |
130 | blo 1b | 133 | blo 1b |
131 | #endif | 134 | #endif |
@@ -143,6 +146,19 @@ ENTRY(v6_coherent_user_range) | |||
143 | mov pc, lr | 146 | mov pc, lr |
144 | 147 | ||
145 | /* | 148 | /* |
149 | * Fault handling for the cache operation above. If the virtual address in r0 | ||
150 | * isn't mapped, just try the next page. | ||
151 | */ | ||
152 | 9001: | ||
153 | mov r0, r0, lsr #12 | ||
154 | mov r0, r0, lsl #12 | ||
155 | add r0, r0, #4096 | ||
156 | b 2b | ||
157 | UNWIND(.fnend ) | ||
158 | ENDPROC(v6_coherent_user_range) | ||
159 | ENDPROC(v6_coherent_kern_range) | ||
160 | |||
161 | /* | ||
146 | * v6_flush_kern_dcache_page(kaddr) | 162 | * v6_flush_kern_dcache_page(kaddr) |
147 | * | 163 | * |
148 | * Ensure that the data held in the page kaddr is written back | 164 | * Ensure that the data held in the page kaddr is written back |
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index bda0ec31a4e2..e1bd9759617f 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <asm/assembler.h> | 15 | #include <asm/assembler.h> |
16 | #include <asm/unwind.h> | ||
16 | 17 | ||
17 | #include "proc-macros.S" | 18 | #include "proc-macros.S" |
18 | 19 | ||
@@ -153,13 +154,16 @@ ENTRY(v7_coherent_kern_range) | |||
153 | * - the Icache does not read data from the write buffer | 154 | * - the Icache does not read data from the write buffer |
154 | */ | 155 | */ |
155 | ENTRY(v7_coherent_user_range) | 156 | ENTRY(v7_coherent_user_range) |
157 | UNWIND(.fnstart ) | ||
156 | dcache_line_size r2, r3 | 158 | dcache_line_size r2, r3 |
157 | sub r3, r2, #1 | 159 | sub r3, r2, #1 |
158 | bic r0, r0, r3 | 160 | bic r0, r0, r3 |
159 | 1: mcr p15, 0, r0, c7, c11, 1 @ clean D line to the point of unification | 161 | 1: |
162 | USER( mcr p15, 0, r0, c7, c11, 1 ) @ clean D line to the point of unification | ||
160 | dsb | 163 | dsb |
161 | mcr p15, 0, r0, c7, c5, 1 @ invalidate I line | 164 | USER( mcr p15, 0, r0, c7, c5, 1 ) @ invalidate I line |
162 | add r0, r0, r2 | 165 | add r0, r0, r2 |
166 | 2: | ||
163 | cmp r0, r1 | 167 | cmp r0, r1 |
164 | blo 1b | 168 | blo 1b |
165 | mov r0, #0 | 169 | mov r0, #0 |
@@ -167,6 +171,17 @@ ENTRY(v7_coherent_user_range) | |||
167 | dsb | 171 | dsb |
168 | isb | 172 | isb |
169 | mov pc, lr | 173 | mov pc, lr |
174 | |||
175 | /* | ||
176 | * Fault handling for the cache operation above. If the virtual address in r0 | ||
177 | * isn't mapped, just try the next page. | ||
178 | */ | ||
179 | 9001: | ||
180 | mov r0, r0, lsr #12 | ||
181 | mov r0, r0, lsl #12 | ||
182 | add r0, r0, #4096 | ||
183 | b 2b | ||
184 | UNWIND(.fnend ) | ||
170 | ENDPROC(v7_coherent_kern_range) | 185 | ENDPROC(v7_coherent_kern_range) |
171 | ENDPROC(v7_coherent_user_range) | 186 | ENDPROC(v7_coherent_user_range) |
172 | 187 | ||