aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2005-09-28 23:21:11 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-09-28 23:21:11 -0400
commit8cf14af0a740fb7e9f94a203b5a989beb875d58f (patch)
treea7bec4d60c352e780d6a2b75e9b95e637e3a14f7
parent705747ab87c96f1b4b8e73ba617c323d9087f6ac (diff)
[SPARC64]: Convert to use generic exception table support.
The funny "range" exception table entries we had were only used by the compat layer socketcall assembly, and it wasn't even needed there. For free we now get proper exception table sorting and fast binary searching. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc64/kernel/sys32.S145
-rw-r--r--arch/sparc64/kernel/traps.c24
-rw-r--r--arch/sparc64/kernel/unaligned.c9
-rw-r--r--arch/sparc64/mm/Makefile2
-rw-r--r--arch/sparc64/mm/extable.c80
-rw-r--r--arch/sparc64/mm/fault.c10
-rw-r--r--include/asm-sparc64/uaccess.h17
7 files changed, 101 insertions, 186 deletions
diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S
index 5f9e4fae612e..4fb99e0bc7c3 100644
--- a/arch/sparc64/kernel/sys32.S
+++ b/arch/sparc64/kernel/sys32.S
@@ -158,163 +158,163 @@ sys32_socketcall: /* %o0=call, %o1=args */
158 jmpl %g2 + %o0, %g0 158 jmpl %g2 + %o0, %g0
159 nop 159 nop
160 160
161 /* Each entry is exactly 32 bytes. */
162 .align 32 161 .align 32
163__socketcall_table_begin: 162__socketcall_table_begin:
163
164 /* Each entry is exactly 32 bytes. */
164do_sys_socket: /* sys_socket(int, int, int) */ 165do_sys_socket: /* sys_socket(int, int, int) */
165 ldswa [%o1 + 0x0] %asi, %o0 1661: ldswa [%o1 + 0x0] %asi, %o0
166 sethi %hi(sys_socket), %g1 167 sethi %hi(sys_socket), %g1
167 ldswa [%o1 + 0x8] %asi, %o2 1682: ldswa [%o1 + 0x8] %asi, %o2
168 jmpl %g1 + %lo(sys_socket), %g0 169 jmpl %g1 + %lo(sys_socket), %g0
169 ldswa [%o1 + 0x4] %asi, %o1 1703: ldswa [%o1 + 0x4] %asi, %o1
170 nop 171 nop
171 nop 172 nop
172 nop 173 nop
173do_sys_bind: /* sys_bind(int fd, struct sockaddr *, int) */ 174do_sys_bind: /* sys_bind(int fd, struct sockaddr *, int) */
174 ldswa [%o1 + 0x0] %asi, %o0 1754: ldswa [%o1 + 0x0] %asi, %o0
175 sethi %hi(sys_bind), %g1 176 sethi %hi(sys_bind), %g1
176 ldswa [%o1 + 0x8] %asi, %o2 1775: ldswa [%o1 + 0x8] %asi, %o2
177 jmpl %g1 + %lo(sys_bind), %g0 178 jmpl %g1 + %lo(sys_bind), %g0
178 lduwa [%o1 + 0x4] %asi, %o1 1796: lduwa [%o1 + 0x4] %asi, %o1
179 nop 180 nop
180 nop 181 nop
181 nop 182 nop
182do_sys_connect: /* sys_connect(int, struct sockaddr *, int) */ 183do_sys_connect: /* sys_connect(int, struct sockaddr *, int) */
183 ldswa [%o1 + 0x0] %asi, %o0 1847: ldswa [%o1 + 0x0] %asi, %o0
184 sethi %hi(sys_connect), %g1 185 sethi %hi(sys_connect), %g1
185 ldswa [%o1 + 0x8] %asi, %o2 1868: ldswa [%o1 + 0x8] %asi, %o2
186 jmpl %g1 + %lo(sys_connect), %g0 187 jmpl %g1 + %lo(sys_connect), %g0
187 lduwa [%o1 + 0x4] %asi, %o1 1889: lduwa [%o1 + 0x4] %asi, %o1
188 nop 189 nop
189 nop 190 nop
190 nop 191 nop
191do_sys_listen: /* sys_listen(int, int) */ 192do_sys_listen: /* sys_listen(int, int) */
192 ldswa [%o1 + 0x0] %asi, %o0 19310: ldswa [%o1 + 0x0] %asi, %o0
193 sethi %hi(sys_listen), %g1 194 sethi %hi(sys_listen), %g1
194 jmpl %g1 + %lo(sys_listen), %g0 195 jmpl %g1 + %lo(sys_listen), %g0
195 ldswa [%o1 + 0x4] %asi, %o1 19611: ldswa [%o1 + 0x4] %asi, %o1
196 nop 197 nop
197 nop 198 nop
198 nop 199 nop
199 nop 200 nop
200do_sys_accept: /* sys_accept(int, struct sockaddr *, int *) */ 201do_sys_accept: /* sys_accept(int, struct sockaddr *, int *) */
201 ldswa [%o1 + 0x0] %asi, %o0 20212: ldswa [%o1 + 0x0] %asi, %o0
202 sethi %hi(sys_accept), %g1 203 sethi %hi(sys_accept), %g1
203 lduwa [%o1 + 0x8] %asi, %o2 20413: lduwa [%o1 + 0x8] %asi, %o2
204 jmpl %g1 + %lo(sys_accept), %g0 205 jmpl %g1 + %lo(sys_accept), %g0
205 lduwa [%o1 + 0x4] %asi, %o1 20614: lduwa [%o1 + 0x4] %asi, %o1
206 nop 207 nop
207 nop 208 nop
208 nop 209 nop
209do_sys_getsockname: /* sys_getsockname(int, struct sockaddr *, int *) */ 210do_sys_getsockname: /* sys_getsockname(int, struct sockaddr *, int *) */
210 ldswa [%o1 + 0x0] %asi, %o0 21115: ldswa [%o1 + 0x0] %asi, %o0
211 sethi %hi(sys_getsockname), %g1 212 sethi %hi(sys_getsockname), %g1
212 lduwa [%o1 + 0x8] %asi, %o2 21316: lduwa [%o1 + 0x8] %asi, %o2
213 jmpl %g1 + %lo(sys_getsockname), %g0 214 jmpl %g1 + %lo(sys_getsockname), %g0
214 lduwa [%o1 + 0x4] %asi, %o1 21517: lduwa [%o1 + 0x4] %asi, %o1
215 nop 216 nop
216 nop 217 nop
217 nop 218 nop
218do_sys_getpeername: /* sys_getpeername(int, struct sockaddr *, int *) */ 219do_sys_getpeername: /* sys_getpeername(int, struct sockaddr *, int *) */
219 ldswa [%o1 + 0x0] %asi, %o0 22018: ldswa [%o1 + 0x0] %asi, %o0
220 sethi %hi(sys_getpeername), %g1 221 sethi %hi(sys_getpeername), %g1
221 lduwa [%o1 + 0x8] %asi, %o2 22219: lduwa [%o1 + 0x8] %asi, %o2
222 jmpl %g1 + %lo(sys_getpeername), %g0 223 jmpl %g1 + %lo(sys_getpeername), %g0
223 lduwa [%o1 + 0x4] %asi, %o1 22420: lduwa [%o1 + 0x4] %asi, %o1
224 nop 225 nop
225 nop 226 nop
226 nop 227 nop
227do_sys_socketpair: /* sys_socketpair(int, int, int, int *) */ 228do_sys_socketpair: /* sys_socketpair(int, int, int, int *) */
228 ldswa [%o1 + 0x0] %asi, %o0 22921: ldswa [%o1 + 0x0] %asi, %o0
229 sethi %hi(sys_socketpair), %g1 230 sethi %hi(sys_socketpair), %g1
230 ldswa [%o1 + 0x8] %asi, %o2 23122: ldswa [%o1 + 0x8] %asi, %o2
231 lduwa [%o1 + 0xc] %asi, %o3 23223: lduwa [%o1 + 0xc] %asi, %o3
232 jmpl %g1 + %lo(sys_socketpair), %g0 233 jmpl %g1 + %lo(sys_socketpair), %g0
233 ldswa [%o1 + 0x4] %asi, %o1 23424: ldswa [%o1 + 0x4] %asi, %o1
234 nop 235 nop
235 nop 236 nop
236do_sys_send: /* sys_send(int, void *, size_t, unsigned int) */ 237do_sys_send: /* sys_send(int, void *, size_t, unsigned int) */
237 ldswa [%o1 + 0x0] %asi, %o0 23825: ldswa [%o1 + 0x0] %asi, %o0
238 sethi %hi(sys_send), %g1 239 sethi %hi(sys_send), %g1
239 lduwa [%o1 + 0x8] %asi, %o2 24026: lduwa [%o1 + 0x8] %asi, %o2
240 lduwa [%o1 + 0xc] %asi, %o3 24127: lduwa [%o1 + 0xc] %asi, %o3
241 jmpl %g1 + %lo(sys_send), %g0 242 jmpl %g1 + %lo(sys_send), %g0
242 lduwa [%o1 + 0x4] %asi, %o1 24328: lduwa [%o1 + 0x4] %asi, %o1
243 nop 244 nop
244 nop 245 nop
245do_sys_recv: /* sys_recv(int, void *, size_t, unsigned int) */ 246do_sys_recv: /* sys_recv(int, void *, size_t, unsigned int) */
246 ldswa [%o1 + 0x0] %asi, %o0 24729: ldswa [%o1 + 0x0] %asi, %o0
247 sethi %hi(sys_recv), %g1 248 sethi %hi(sys_recv), %g1
248 lduwa [%o1 + 0x8] %asi, %o2 24930: lduwa [%o1 + 0x8] %asi, %o2
249 lduwa [%o1 + 0xc] %asi, %o3 25031: lduwa [%o1 + 0xc] %asi, %o3
250 jmpl %g1 + %lo(sys_recv), %g0 251 jmpl %g1 + %lo(sys_recv), %g0
251 lduwa [%o1 + 0x4] %asi, %o1 25232: lduwa [%o1 + 0x4] %asi, %o1
252 nop 253 nop
253 nop 254 nop
254do_sys_sendto: /* sys_sendto(int, u32, compat_size_t, unsigned int, u32, int) */ 255do_sys_sendto: /* sys_sendto(int, u32, compat_size_t, unsigned int, u32, int) */
255 ldswa [%o1 + 0x0] %asi, %o0 25633: ldswa [%o1 + 0x0] %asi, %o0
256 sethi %hi(sys_sendto), %g1 257 sethi %hi(sys_sendto), %g1
257 lduwa [%o1 + 0x8] %asi, %o2 25834: lduwa [%o1 + 0x8] %asi, %o2
258 lduwa [%o1 + 0xc] %asi, %o3 25935: lduwa [%o1 + 0xc] %asi, %o3
259 lduwa [%o1 + 0x10] %asi, %o4 26036: lduwa [%o1 + 0x10] %asi, %o4
260 ldswa [%o1 + 0x14] %asi, %o5 26137: ldswa [%o1 + 0x14] %asi, %o5
261 jmpl %g1 + %lo(sys_sendto), %g0 262 jmpl %g1 + %lo(sys_sendto), %g0
262 lduwa [%o1 + 0x4] %asi, %o1 26338: lduwa [%o1 + 0x4] %asi, %o1
263do_sys_recvfrom: /* sys_recvfrom(int, u32, compat_size_t, unsigned int, u32, u32) */ 264do_sys_recvfrom: /* sys_recvfrom(int, u32, compat_size_t, unsigned int, u32, u32) */
264 ldswa [%o1 + 0x0] %asi, %o0 26539: ldswa [%o1 + 0x0] %asi, %o0
265 sethi %hi(sys_recvfrom), %g1 266 sethi %hi(sys_recvfrom), %g1
266 lduwa [%o1 + 0x8] %asi, %o2 26740: lduwa [%o1 + 0x8] %asi, %o2
267 lduwa [%o1 + 0xc] %asi, %o3 26841: lduwa [%o1 + 0xc] %asi, %o3
268 lduwa [%o1 + 0x10] %asi, %o4 26942: lduwa [%o1 + 0x10] %asi, %o4
269 lduwa [%o1 + 0x14] %asi, %o5 27043: lduwa [%o1 + 0x14] %asi, %o5
270 jmpl %g1 + %lo(sys_recvfrom), %g0 271 jmpl %g1 + %lo(sys_recvfrom), %g0
271 lduwa [%o1 + 0x4] %asi, %o1 27244: lduwa [%o1 + 0x4] %asi, %o1
272do_sys_shutdown: /* sys_shutdown(int, int) */ 273do_sys_shutdown: /* sys_shutdown(int, int) */
273 ldswa [%o1 + 0x0] %asi, %o0 27445: ldswa [%o1 + 0x0] %asi, %o0
274 sethi %hi(sys_shutdown), %g1 275 sethi %hi(sys_shutdown), %g1
275 jmpl %g1 + %lo(sys_shutdown), %g0 276 jmpl %g1 + %lo(sys_shutdown), %g0
276 ldswa [%o1 + 0x4] %asi, %o1 27746: ldswa [%o1 + 0x4] %asi, %o1
277 nop 278 nop
278 nop 279 nop
279 nop 280 nop
280 nop 281 nop
281do_sys_setsockopt: /* compat_sys_setsockopt(int, int, int, char *, int) */ 282do_sys_setsockopt: /* compat_sys_setsockopt(int, int, int, char *, int) */
282 ldswa [%o1 + 0x0] %asi, %o0 28347: ldswa [%o1 + 0x0] %asi, %o0
283 sethi %hi(compat_sys_setsockopt), %g1 284 sethi %hi(compat_sys_setsockopt), %g1
284 ldswa [%o1 + 0x8] %asi, %o2 28548: ldswa [%o1 + 0x8] %asi, %o2
285 lduwa [%o1 + 0xc] %asi, %o3 28649: lduwa [%o1 + 0xc] %asi, %o3
286 ldswa [%o1 + 0x10] %asi, %o4 28750: ldswa [%o1 + 0x10] %asi, %o4
287 jmpl %g1 + %lo(compat_sys_setsockopt), %g0 288 jmpl %g1 + %lo(compat_sys_setsockopt), %g0
288 ldswa [%o1 + 0x4] %asi, %o1 28951: ldswa [%o1 + 0x4] %asi, %o1
289 nop 290 nop
290do_sys_getsockopt: /* compat_sys_getsockopt(int, int, int, u32, u32) */ 291do_sys_getsockopt: /* compat_sys_getsockopt(int, int, int, u32, u32) */
291 ldswa [%o1 + 0x0] %asi, %o0 29252: ldswa [%o1 + 0x0] %asi, %o0
292 sethi %hi(compat_sys_getsockopt), %g1 293 sethi %hi(compat_sys_getsockopt), %g1
293 ldswa [%o1 + 0x8] %asi, %o2 29453: ldswa [%o1 + 0x8] %asi, %o2
294 lduwa [%o1 + 0xc] %asi, %o3 29554: lduwa [%o1 + 0xc] %asi, %o3
295 lduwa [%o1 + 0x10] %asi, %o4 29655: lduwa [%o1 + 0x10] %asi, %o4
296 jmpl %g1 + %lo(compat_sys_getsockopt), %g0 297 jmpl %g1 + %lo(compat_sys_getsockopt), %g0
297 ldswa [%o1 + 0x4] %asi, %o1 29856: ldswa [%o1 + 0x4] %asi, %o1
298 nop 299 nop
299do_sys_sendmsg: /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */ 300do_sys_sendmsg: /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */
300 ldswa [%o1 + 0x0] %asi, %o0 30157: ldswa [%o1 + 0x0] %asi, %o0
301 sethi %hi(compat_sys_sendmsg), %g1 302 sethi %hi(compat_sys_sendmsg), %g1
302 lduwa [%o1 + 0x8] %asi, %o2 30358: lduwa [%o1 + 0x8] %asi, %o2
303 jmpl %g1 + %lo(compat_sys_sendmsg), %g0 304 jmpl %g1 + %lo(compat_sys_sendmsg), %g0
304 lduwa [%o1 + 0x4] %asi, %o1 30559: lduwa [%o1 + 0x4] %asi, %o1
305 nop 306 nop
306 nop 307 nop
307 nop 308 nop
308do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */ 309do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */
309 ldswa [%o1 + 0x0] %asi, %o0 31060: ldswa [%o1 + 0x0] %asi, %o0
310 sethi %hi(compat_sys_recvmsg), %g1 311 sethi %hi(compat_sys_recvmsg), %g1
311 lduwa [%o1 + 0x8] %asi, %o2 31261: lduwa [%o1 + 0x8] %asi, %o2
312 jmpl %g1 + %lo(compat_sys_recvmsg), %g0 313 jmpl %g1 + %lo(compat_sys_recvmsg), %g0
313 lduwa [%o1 + 0x4] %asi, %o1 31462: lduwa [%o1 + 0x4] %asi, %o1
314 nop 315 nop
315 nop 316 nop
316 nop 317 nop
317__socketcall_table_end:
318 318
319do_einval: 319do_einval:
320 retl 320 retl
@@ -325,5 +325,20 @@ do_efault:
325 325
326 .section __ex_table 326 .section __ex_table
327 .align 4 327 .align 4
328 .word __socketcall_table_begin, 0, __socketcall_table_end, do_efault 328 .word 1b, do_efault, 2b, do_efault, 3b, do_efault, 4b, do_efault
329 .word 5b, do_efault, 6b, do_efault, 7b, do_efault, 8b, do_efault
330 .word 9b, do_efault, 10b, do_efault, 11b, do_efault, 12b, do_efault
331 .word 13b, do_efault, 14b, do_efault, 15b, do_efault, 16b, do_efault
332 .word 17b, do_efault, 18b, do_efault, 19b, do_efault, 20b, do_efault
333 .word 21b, do_efault, 22b, do_efault, 23b, do_efault, 24b, do_efault
334 .word 25b, do_efault, 26b, do_efault, 27b, do_efault, 28b, do_efault
335 .word 29b, do_efault, 30b, do_efault, 31b, do_efault, 32b, do_efault
336 .word 33b, do_efault, 34b, do_efault, 35b, do_efault, 36b, do_efault
337 .word 37b, do_efault, 38b, do_efault, 39b, do_efault, 40b, do_efault
338 .word 41b, do_efault, 42b, do_efault, 43b, do_efault, 44b, do_efault
339 .word 45b, do_efault, 46b, do_efault, 47b, do_efault, 48b, do_efault
340 .word 49b, do_efault, 50b, do_efault, 51b, do_efault, 52b, do_efault
341 .word 53b, do_efault, 54b, do_efault, 55b, do_efault, 56b, do_efault
342 .word 57b, do_efault, 58b, do_efault, 59b, do_efault, 60b, do_efault
343 .word 61b, do_efault, 62b, do_efault
329 .previous 344 .previous
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index f8e7005fede9..1aa15990f5af 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -189,19 +189,18 @@ void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, un
189 189
190 if (regs->tstate & TSTATE_PRIV) { 190 if (regs->tstate & TSTATE_PRIV) {
191 /* Test if this comes from uaccess places. */ 191 /* Test if this comes from uaccess places. */
192 unsigned long fixup; 192 const struct exception_table_entry *entry;
193 unsigned long g2 = regs->u_regs[UREG_G2];
194 193
195 if ((fixup = search_extables_range(regs->tpc, &g2))) { 194 entry = search_exception_tables(regs->tpc);
196 /* Ouch, somebody is trying ugly VM hole tricks on us... */ 195 if (entry) {
196 /* Ouch, somebody is trying VM hole tricks on us... */
197#ifdef DEBUG_EXCEPTIONS 197#ifdef DEBUG_EXCEPTIONS
198 printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc); 198 printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc);
199 printk("EX_TABLE: insn<%016lx> fixup<%016lx> " 199 printk("EX_TABLE: insn<%016lx> fixup<%016lx>\n",
200 "g2<%016lx>\n", regs->tpc, fixup, g2); 200 regs->tpc, entry->fixup);
201#endif 201#endif
202 regs->tpc = fixup; 202 regs->tpc = entry->fixup;
203 regs->tnpc = regs->tpc + 4; 203 regs->tnpc = regs->tpc + 4;
204 regs->u_regs[UREG_G2] = g2;
205 return; 204 return;
206 } 205 }
207 /* Shit... */ 206 /* Shit... */
@@ -1610,10 +1609,10 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned
1610 /* OK, usermode access. */ 1609 /* OK, usermode access. */
1611 recoverable = 1; 1610 recoverable = 1;
1612 } else { 1611 } else {
1613 unsigned long g2 = regs->u_regs[UREG_G2]; 1612 const struct exception_table_entry *entry;
1614 unsigned long fixup = search_extables_range(regs->tpc, &g2);
1615 1613
1616 if (fixup != 0UL) { 1614 entry = search_exception_tables(regs->tpc);
1615 if (entry) {
1617 /* OK, kernel access to userspace. */ 1616 /* OK, kernel access to userspace. */
1618 recoverable = 1; 1617 recoverable = 1;
1619 1618
@@ -1632,9 +1631,8 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned
1632 * recoverable condition. 1631 * recoverable condition.
1633 */ 1632 */
1634 if (recoverable) { 1633 if (recoverable) {
1635 regs->tpc = fixup; 1634 regs->tpc = entry->fixup;
1636 regs->tnpc = regs->tpc + 4; 1635 regs->tnpc = regs->tpc + 4;
1637 regs->u_regs[UREG_G2] = g2;
1638 } 1636 }
1639 } 1637 }
1640 } 1638 }
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
index 02af08ffec8f..9d6be20f4125 100644
--- a/arch/sparc64/kernel/unaligned.c
+++ b/arch/sparc64/kernel/unaligned.c
@@ -246,10 +246,10 @@ void kernel_mna_trap_fault(void)
246{ 246{
247 struct pt_regs *regs = current_thread_info()->kern_una_regs; 247 struct pt_regs *regs = current_thread_info()->kern_una_regs;
248 unsigned int insn = current_thread_info()->kern_una_insn; 248 unsigned int insn = current_thread_info()->kern_una_insn;
249 unsigned long g2 = regs->u_regs[UREG_G2]; 249 const struct exception_table_entry *entry;
250 unsigned long fixup = search_extables_range(regs->tpc, &g2);
251 250
252 if (!fixup) { 251 entry = search_exception_tables(regs->tpc);
252 if (!entry) {
253 unsigned long address; 253 unsigned long address;
254 254
255 address = compute_effective_address(regs, insn, 255 address = compute_effective_address(regs, insn,
@@ -270,9 +270,8 @@ void kernel_mna_trap_fault(void)
270 die_if_kernel("Oops", regs); 270 die_if_kernel("Oops", regs);
271 /* Not reached */ 271 /* Not reached */
272 } 272 }
273 regs->tpc = fixup; 273 regs->tpc = entry->fixup;
274 regs->tnpc = regs->tpc + 4; 274 regs->tnpc = regs->tpc + 4;
275 regs->u_regs [UREG_G2] = g2;
276 275
277 regs->tstate &= ~TSTATE_ASI; 276 regs->tstate &= ~TSTATE_ASI;
278 regs->tstate |= (ASI_AIUS << 24UL); 277 regs->tstate |= (ASI_AIUS << 24UL);
diff --git a/arch/sparc64/mm/Makefile b/arch/sparc64/mm/Makefile
index cda87333a77b..9d0960e69f48 100644
--- a/arch/sparc64/mm/Makefile
+++ b/arch/sparc64/mm/Makefile
@@ -5,6 +5,6 @@
5EXTRA_AFLAGS := -ansi 5EXTRA_AFLAGS := -ansi
6EXTRA_CFLAGS := -Werror 6EXTRA_CFLAGS := -Werror
7 7
8obj-y := ultra.o tlb.o fault.o init.o generic.o extable.o 8obj-y := ultra.o tlb.o fault.o init.o generic.o
9 9
10obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o 10obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
diff --git a/arch/sparc64/mm/extable.c b/arch/sparc64/mm/extable.c
deleted file mode 100644
index ec334297ff4f..000000000000
--- a/arch/sparc64/mm/extable.c
+++ /dev/null
@@ -1,80 +0,0 @@
1/*
2 * linux/arch/sparc64/mm/extable.c
3 */
4
5#include <linux/config.h>
6#include <linux/module.h>
7#include <asm/uaccess.h>
8
9extern const struct exception_table_entry __start___ex_table[];
10extern const struct exception_table_entry __stop___ex_table[];
11
12void sort_extable(struct exception_table_entry *start,
13 struct exception_table_entry *finish)
14{
15}
16
17/* Caller knows they are in a range if ret->fixup == 0 */
18const struct exception_table_entry *
19search_extable(const struct exception_table_entry *start,
20 const struct exception_table_entry *last,
21 unsigned long value)
22{
23 const struct exception_table_entry *walk;
24
25 /* Single insn entries are encoded as:
26 * word 1: insn address
27 * word 2: fixup code address
28 *
29 * Range entries are encoded as:
30 * word 1: first insn address
31 * word 2: 0
32 * word 3: last insn address + 4 bytes
33 * word 4: fixup code address
34 *
35 * See asm/uaccess.h for more details.
36 */
37
38 /* 1. Try to find an exact match. */
39 for (walk = start; walk <= last; walk++) {
40 if (walk->fixup == 0) {
41 /* A range entry, skip both parts. */
42 walk++;
43 continue;
44 }
45
46 if (walk->insn == value)
47 return walk;
48 }
49
50 /* 2. Try to find a range match. */
51 for (walk = start; walk <= (last - 1); walk++) {
52 if (walk->fixup)
53 continue;
54
55 if (walk[0].insn <= value && walk[1].insn > value)
56 return walk;
57
58 walk++;
59 }
60
61 return NULL;
62}
63
64/* Special extable search, which handles ranges. Returns fixup */
65unsigned long search_extables_range(unsigned long addr, unsigned long *g2)
66{
67 const struct exception_table_entry *entry;
68
69 entry = search_exception_tables(addr);
70 if (!entry)
71 return 0;
72
73 /* Inside range? Fix g2 and return correct fixup */
74 if (!entry->fixup) {
75 *g2 = (addr - entry->insn) / 4;
76 return (entry + 1)->fixup;
77 }
78
79 return entry->fixup;
80}
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index db1e3310e907..59dc9a2ece5a 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -242,7 +242,6 @@ static unsigned int get_fault_insn(struct pt_regs *regs, unsigned int insn)
242static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code, 242static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
243 unsigned int insn, unsigned long address) 243 unsigned int insn, unsigned long address)
244{ 244{
245 unsigned long g2;
246 unsigned char asi = ASI_P; 245 unsigned char asi = ASI_P;
247 246
248 if ((!insn) && (regs->tstate & TSTATE_PRIV)) 247 if ((!insn) && (regs->tstate & TSTATE_PRIV))
@@ -273,11 +272,9 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
273 } 272 }
274 } 273 }
275 274
276 g2 = regs->u_regs[UREG_G2];
277
278 /* Is this in ex_table? */ 275 /* Is this in ex_table? */
279 if (regs->tstate & TSTATE_PRIV) { 276 if (regs->tstate & TSTATE_PRIV) {
280 unsigned long fixup; 277 const struct exception_table_entry *entry;
281 278
282 if (asi == ASI_P && (insn & 0xc0800000) == 0xc0800000) { 279 if (asi == ASI_P && (insn & 0xc0800000) == 0xc0800000) {
283 if (insn & 0x2000) 280 if (insn & 0x2000)
@@ -288,10 +285,9 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
288 285
289 /* Look in asi.h: All _S asis have LS bit set */ 286 /* Look in asi.h: All _S asis have LS bit set */
290 if ((asi & 0x1) && 287 if ((asi & 0x1) &&
291 (fixup = search_extables_range(regs->tpc, &g2))) { 288 (entry = search_exception_tables(regs->tpc))) {
292 regs->tpc = fixup; 289 regs->tpc = entry->fixup;
293 regs->tnpc = regs->tpc + 4; 290 regs->tnpc = regs->tpc + 4;
294 regs->u_regs[UREG_G2] = g2;
295 return; 291 return;
296 } 292 }
297 } else { 293 } else {
diff --git a/include/asm-sparc64/uaccess.h b/include/asm-sparc64/uaccess.h
index 80a65d7e3dbf..c099aa339784 100644
--- a/include/asm-sparc64/uaccess.h
+++ b/include/asm-sparc64/uaccess.h
@@ -70,25 +70,12 @@ static inline int access_ok(int type, const void __user * addr, unsigned long si
70 * with the main instruction path. This means when everything is well, 70 * with the main instruction path. This means when everything is well,
71 * we don't even have to jump over them. Further, they do not intrude 71 * we don't even have to jump over them. Further, they do not intrude
72 * on our cache or tlb entries. 72 * on our cache or tlb entries.
73 *
74 * There is a special way how to put a range of potentially faulting
75 * insns (like twenty ldd/std's with now intervening other instructions)
76 * You specify address of first in insn and 0 in fixup and in the next
77 * exception_table_entry you specify last potentially faulting insn + 1
78 * and in fixup the routine which should handle the fault.
79 * That fixup code will get
80 * (faulting_insn_address - first_insn_in_the_range_address)/4
81 * in %g2 (ie. index of the faulting instruction in the range).
82 */ 73 */
83 74
84struct exception_table_entry 75struct exception_table_entry {
85{ 76 unsigned int insn, fixup;
86 unsigned insn, fixup;
87}; 77};
88 78
89/* Special exable search, which handles ranges. Returns fixup */
90unsigned long search_extables_range(unsigned long addr, unsigned long *g2);
91
92extern void __ret_efault(void); 79extern void __ret_efault(void);
93 80
94/* Uh, these should become the main single-value transfer routines.. 81/* Uh, these should become the main single-value transfer routines..