diff options
-rw-r--r-- | arch/arm/kernel/entry-common.S | 35 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 2 | ||||
-rw-r--r-- | include/asm-arm/unistd.h | 48 |
3 files changed, 48 insertions, 37 deletions
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index e2b42997ad33..34826bcceb7a 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S | |||
@@ -98,20 +98,14 @@ ENTRY(ret_from_fork) | |||
98 | run on an ARM7 and we can save a couple of instructions. | 98 | run on an ARM7 and we can save a couple of instructions. |
99 | --pb */ | 99 | --pb */ |
100 | #ifdef CONFIG_CPU_ARM710 | 100 | #ifdef CONFIG_CPU_ARM710 |
101 | .macro arm710_bug_check, instr, temp | 101 | #define A710(code...) code |
102 | and \temp, \instr, #0x0f000000 @ check for SWI | 102 | .Larm710bug: |
103 | teq \temp, #0x0f000000 | ||
104 | bne .Larm700bug | ||
105 | .endm | ||
106 | |||
107 | .Larm700bug: | ||
108 | ldmia sp, {r0 - lr}^ @ Get calling r0 - lr | 103 | ldmia sp, {r0 - lr}^ @ Get calling r0 - lr |
109 | mov r0, r0 | 104 | mov r0, r0 |
110 | add sp, sp, #S_FRAME_SIZE | 105 | add sp, sp, #S_FRAME_SIZE |
111 | subs pc, lr, #4 | 106 | subs pc, lr, #4 |
112 | #else | 107 | #else |
113 | .macro arm710_bug_check, instr, temp | 108 | #define A710(code...) |
114 | .endm | ||
115 | #endif | 109 | #endif |
116 | 110 | ||
117 | .align 5 | 111 | .align 5 |
@@ -129,14 +123,24 @@ ENTRY(vector_swi) | |||
129 | /* | 123 | /* |
130 | * Get the system call number. | 124 | * Get the system call number. |
131 | */ | 125 | */ |
132 | #ifdef CONFIG_ARM_THUMB | 126 | #if defined(CONFIG_AEABI) |
127 | |||
128 | @ syscall number is in scno (r7) already. | ||
129 | |||
130 | A710( ldr ip, [lr, #-4] @ get SWI instruction ) | ||
131 | A710( and ip, ip, #0x0f000000 @ check for SWI ) | ||
132 | A710( teq ip, #0x0f000000 ) | ||
133 | A710( bne .Larm710bug ) | ||
134 | #elif defined(CONFIG_ARM_THUMB) | ||
133 | tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs | 135 | tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs |
134 | addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in | 136 | addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in |
135 | ldreq scno, [lr, #-4] | 137 | ldreq scno, [lr, #-4] |
136 | #else | 138 | #else |
137 | ldr scno, [lr, #-4] @ get SWI instruction | 139 | ldr scno, [lr, #-4] @ get SWI instruction |
140 | A710( and ip, scno, #0x0f000000 @ check for SWI ) | ||
141 | A710( teq ip, #0x0f000000 ) | ||
142 | A710( bne .Larm710bug ) | ||
138 | #endif | 143 | #endif |
139 | arm710_bug_check scno, ip | ||
140 | 144 | ||
141 | #ifdef CONFIG_ALIGNMENT_TRAP | 145 | #ifdef CONFIG_ALIGNMENT_TRAP |
142 | ldr ip, __cr_alignment | 146 | ldr ip, __cr_alignment |
@@ -145,18 +149,19 @@ ENTRY(vector_swi) | |||
145 | #endif | 149 | #endif |
146 | enable_irq | 150 | enable_irq |
147 | 151 | ||
148 | stmdb sp!, {r4, r5} @ push fifth and sixth args | ||
149 | |||
150 | get_thread_info tsk | 152 | get_thread_info tsk |
151 | ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing | 153 | ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing |
154 | #ifndef CONFIG_AEABI | ||
152 | bic scno, scno, #0xff000000 @ mask off SWI op-code | 155 | bic scno, scno, #0xff000000 @ mask off SWI op-code |
153 | eor scno, scno, #__NR_SYSCALL_BASE @ check OS number | 156 | eor scno, scno, #__NR_SYSCALL_BASE @ check OS number |
157 | #endif | ||
154 | adr tbl, sys_call_table @ load syscall table pointer | 158 | adr tbl, sys_call_table @ load syscall table pointer |
159 | stmdb sp!, {r4, r5} @ push fifth and sixth args | ||
155 | tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls? | 160 | tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls? |
156 | bne __sys_trace | 161 | bne __sys_trace |
157 | 162 | ||
158 | adr lr, ret_fast_syscall @ return address | ||
159 | cmp scno, #NR_syscalls @ check upper syscall limit | 163 | cmp scno, #NR_syscalls @ check upper syscall limit |
164 | adr lr, ret_fast_syscall @ return address | ||
160 | ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine | 165 | ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine |
161 | 166 | ||
162 | add r1, sp, #S_OFF | 167 | add r1, sp, #S_OFF |
@@ -207,6 +212,7 @@ ENTRY(sys_call_table) | |||
207 | @ r8 = syscall table | 212 | @ r8 = syscall table |
208 | .type sys_syscall, #function | 213 | .type sys_syscall, #function |
209 | sys_syscall: | 214 | sys_syscall: |
215 | #ifndef CONFIG_AEABI | ||
210 | eor scno, r0, #__NR_SYSCALL_BASE | 216 | eor scno, r0, #__NR_SYSCALL_BASE |
211 | cmp scno, #__NR_syscall - __NR_SYSCALL_BASE | 217 | cmp scno, #__NR_syscall - __NR_SYSCALL_BASE |
212 | cmpne scno, #NR_syscalls @ check range | 218 | cmpne scno, #NR_syscalls @ check range |
@@ -216,6 +222,7 @@ sys_syscall: | |||
216 | movlo r2, r3 | 222 | movlo r2, r3 |
217 | movlo r3, r4 | 223 | movlo r3, r4 |
218 | ldrlo pc, [tbl, scno, lsl #2] | 224 | ldrlo pc, [tbl, scno, lsl #2] |
225 | #endif | ||
219 | b sys_ni_syscall | 226 | b sys_ni_syscall |
220 | 227 | ||
221 | sys_fork_wrapper: | 228 | sys_fork_wrapper: |
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 93cfd3ffcc72..10235b01582e 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -404,7 +404,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) | |||
404 | struct thread_info *thread = current_thread_info(); | 404 | struct thread_info *thread = current_thread_info(); |
405 | siginfo_t info; | 405 | siginfo_t info; |
406 | 406 | ||
407 | if ((no >> 16) != 0x9f) | 407 | if ((no >> 16) != (__ARM_NR_BASE>> 16)) |
408 | return bad_syscall(no, regs); | 408 | return bad_syscall(no, regs); |
409 | 409 | ||
410 | switch (no & 0xffff) { | 410 | switch (no & 0xffff) { |
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h index d626e70faded..c9e087fe7e11 100644 --- a/include/asm-arm/unistd.h +++ b/include/asm-arm/unistd.h | |||
@@ -15,10 +15,12 @@ | |||
15 | 15 | ||
16 | #include <linux/linkage.h> | 16 | #include <linux/linkage.h> |
17 | 17 | ||
18 | #if defined(__thumb__) | 18 | #define __NR_OABI_SYSCALL_BASE 0x900000 |
19 | |||
20 | #if defined(__thumb__) || defined(__ARM_EABI__) | ||
19 | #define __NR_SYSCALL_BASE 0 | 21 | #define __NR_SYSCALL_BASE 0 |
20 | #else | 22 | #else |
21 | #define __NR_SYSCALL_BASE 0x900000 | 23 | #define __NR_SYSCALL_BASE __NR_OABI_SYSCALL_BASE |
22 | #endif | 24 | #endif |
23 | 25 | ||
24 | /* | 26 | /* |
@@ -373,13 +375,13 @@ | |||
373 | #define __sys1(x) __sys2(x) | 375 | #define __sys1(x) __sys2(x) |
374 | 376 | ||
375 | #ifndef __syscall | 377 | #ifndef __syscall |
376 | #if defined(__thumb__) | 378 | #if defined(__thumb__) || defined(__ARM_EABI__) |
377 | #define __syscall(name) \ | 379 | #define __SYS_REG(name) register long __sysreg __asm__("r7") = __NR_##name; |
378 | "push {r7}\n\t" \ | 380 | #define __SYS_REG_LIST(regs...) "r" (__sysreg) , ##regs |
379 | "mov r7, #" __sys1(__NR_##name) "\n\t" \ | 381 | #define __syscall(name) "swi\t0" |
380 | "swi 0\n\t" \ | ||
381 | "pop {r7}" | ||
382 | #else | 382 | #else |
383 | #define __SYS_REG(name) | ||
384 | #define __SYS_REG_LIST(regs...) regs | ||
383 | #define __syscall(name) "swi\t" __sys1(__NR_##name) "" | 385 | #define __syscall(name) "swi\t" __sys1(__NR_##name) "" |
384 | #endif | 386 | #endif |
385 | #endif | 387 | #endif |
@@ -395,33 +397,34 @@ do { \ | |||
395 | 397 | ||
396 | #define _syscall0(type,name) \ | 398 | #define _syscall0(type,name) \ |
397 | type name(void) { \ | 399 | type name(void) { \ |
400 | __SYS_REG(name) \ | ||
398 | register long __res_r0 __asm__("r0"); \ | 401 | register long __res_r0 __asm__("r0"); \ |
399 | long __res; \ | 402 | long __res; \ |
400 | __asm__ __volatile__ ( \ | 403 | __asm__ __volatile__ ( \ |
401 | __syscall(name) \ | 404 | __syscall(name) \ |
402 | : "=r" (__res_r0) \ | 405 | : "=r" (__res_r0) \ |
403 | : \ | 406 | : __SYS_REG_LIST() ); \ |
404 | : "lr"); \ | ||
405 | __res = __res_r0; \ | 407 | __res = __res_r0; \ |
406 | __syscall_return(type,__res); \ | 408 | __syscall_return(type,__res); \ |
407 | } | 409 | } |
408 | 410 | ||
409 | #define _syscall1(type,name,type1,arg1) \ | 411 | #define _syscall1(type,name,type1,arg1) \ |
410 | type name(type1 arg1) { \ | 412 | type name(type1 arg1) { \ |
413 | __SYS_REG(name) \ | ||
411 | register long __r0 __asm__("r0") = (long)arg1; \ | 414 | register long __r0 __asm__("r0") = (long)arg1; \ |
412 | register long __res_r0 __asm__("r0"); \ | 415 | register long __res_r0 __asm__("r0"); \ |
413 | long __res; \ | 416 | long __res; \ |
414 | __asm__ __volatile__ ( \ | 417 | __asm__ __volatile__ ( \ |
415 | __syscall(name) \ | 418 | __syscall(name) \ |
416 | : "=r" (__res_r0) \ | 419 | : "=r" (__res_r0) \ |
417 | : "r" (__r0) \ | 420 | : __SYS_REG_LIST( "0" (__r0) ) ); \ |
418 | : "lr"); \ | ||
419 | __res = __res_r0; \ | 421 | __res = __res_r0; \ |
420 | __syscall_return(type,__res); \ | 422 | __syscall_return(type,__res); \ |
421 | } | 423 | } |
422 | 424 | ||
423 | #define _syscall2(type,name,type1,arg1,type2,arg2) \ | 425 | #define _syscall2(type,name,type1,arg1,type2,arg2) \ |
424 | type name(type1 arg1,type2 arg2) { \ | 426 | type name(type1 arg1,type2 arg2) { \ |
427 | __SYS_REG(name) \ | ||
425 | register long __r0 __asm__("r0") = (long)arg1; \ | 428 | register long __r0 __asm__("r0") = (long)arg1; \ |
426 | register long __r1 __asm__("r1") = (long)arg2; \ | 429 | register long __r1 __asm__("r1") = (long)arg2; \ |
427 | register long __res_r0 __asm__("r0"); \ | 430 | register long __res_r0 __asm__("r0"); \ |
@@ -429,8 +432,7 @@ type name(type1 arg1,type2 arg2) { \ | |||
429 | __asm__ __volatile__ ( \ | 432 | __asm__ __volatile__ ( \ |
430 | __syscall(name) \ | 433 | __syscall(name) \ |
431 | : "=r" (__res_r0) \ | 434 | : "=r" (__res_r0) \ |
432 | : "r" (__r0),"r" (__r1) \ | 435 | : __SYS_REG_LIST( "0" (__r0), "r" (__r1) ) ); \ |
433 | : "lr"); \ | ||
434 | __res = __res_r0; \ | 436 | __res = __res_r0; \ |
435 | __syscall_return(type,__res); \ | 437 | __syscall_return(type,__res); \ |
436 | } | 438 | } |
@@ -438,6 +440,7 @@ type name(type1 arg1,type2 arg2) { \ | |||
438 | 440 | ||
439 | #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ | 441 | #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ |
440 | type name(type1 arg1,type2 arg2,type3 arg3) { \ | 442 | type name(type1 arg1,type2 arg2,type3 arg3) { \ |
443 | __SYS_REG(name) \ | ||
441 | register long __r0 __asm__("r0") = (long)arg1; \ | 444 | register long __r0 __asm__("r0") = (long)arg1; \ |
442 | register long __r1 __asm__("r1") = (long)arg2; \ | 445 | register long __r1 __asm__("r1") = (long)arg2; \ |
443 | register long __r2 __asm__("r2") = (long)arg3; \ | 446 | register long __r2 __asm__("r2") = (long)arg3; \ |
@@ -446,8 +449,7 @@ type name(type1 arg1,type2 arg2,type3 arg3) { \ | |||
446 | __asm__ __volatile__ ( \ | 449 | __asm__ __volatile__ ( \ |
447 | __syscall(name) \ | 450 | __syscall(name) \ |
448 | : "=r" (__res_r0) \ | 451 | : "=r" (__res_r0) \ |
449 | : "r" (__r0),"r" (__r1),"r" (__r2) \ | 452 | : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2) ) ); \ |
450 | : "lr"); \ | ||
451 | __res = __res_r0; \ | 453 | __res = __res_r0; \ |
452 | __syscall_return(type,__res); \ | 454 | __syscall_return(type,__res); \ |
453 | } | 455 | } |
@@ -455,6 +457,7 @@ type name(type1 arg1,type2 arg2,type3 arg3) { \ | |||
455 | 457 | ||
456 | #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)\ | 458 | #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)\ |
457 | type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ | 459 | type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ |
460 | __SYS_REG(name) \ | ||
458 | register long __r0 __asm__("r0") = (long)arg1; \ | 461 | register long __r0 __asm__("r0") = (long)arg1; \ |
459 | register long __r1 __asm__("r1") = (long)arg2; \ | 462 | register long __r1 __asm__("r1") = (long)arg2; \ |
460 | register long __r2 __asm__("r2") = (long)arg3; \ | 463 | register long __r2 __asm__("r2") = (long)arg3; \ |
@@ -464,8 +467,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ | |||
464 | __asm__ __volatile__ ( \ | 467 | __asm__ __volatile__ ( \ |
465 | __syscall(name) \ | 468 | __syscall(name) \ |
466 | : "=r" (__res_r0) \ | 469 | : "=r" (__res_r0) \ |
467 | : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3) \ | 470 | : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) ) ); \ |
468 | : "lr"); \ | ||
469 | __res = __res_r0; \ | 471 | __res = __res_r0; \ |
470 | __syscall_return(type,__res); \ | 472 | __syscall_return(type,__res); \ |
471 | } | 473 | } |
@@ -473,6 +475,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ | |||
473 | 475 | ||
474 | #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ | 476 | #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ |
475 | type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ | 477 | type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ |
478 | __SYS_REG(name) \ | ||
476 | register long __r0 __asm__("r0") = (long)arg1; \ | 479 | register long __r0 __asm__("r0") = (long)arg1; \ |
477 | register long __r1 __asm__("r1") = (long)arg2; \ | 480 | register long __r1 __asm__("r1") = (long)arg2; \ |
478 | register long __r2 __asm__("r2") = (long)arg3; \ | 481 | register long __r2 __asm__("r2") = (long)arg3; \ |
@@ -483,14 +486,15 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ | |||
483 | __asm__ __volatile__ ( \ | 486 | __asm__ __volatile__ ( \ |
484 | __syscall(name) \ | 487 | __syscall(name) \ |
485 | : "=r" (__res_r0) \ | 488 | : "=r" (__res_r0) \ |
486 | : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3),"r" (__r4) \ | 489 | : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \ |
487 | : "lr"); \ | 490 | "r" (__r3), "r" (__r4) ) ); \ |
488 | __res = __res_r0; \ | 491 | __res = __res_r0; \ |
489 | __syscall_return(type,__res); \ | 492 | __syscall_return(type,__res); \ |
490 | } | 493 | } |
491 | 494 | ||
492 | #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ | 495 | #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ |
493 | type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \ | 496 | type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \ |
497 | __SYS_REG(name) \ | ||
494 | register long __r0 __asm__("r0") = (long)arg1; \ | 498 | register long __r0 __asm__("r0") = (long)arg1; \ |
495 | register long __r1 __asm__("r1") = (long)arg2; \ | 499 | register long __r1 __asm__("r1") = (long)arg2; \ |
496 | register long __r2 __asm__("r2") = (long)arg3; \ | 500 | register long __r2 __asm__("r2") = (long)arg3; \ |
@@ -502,8 +506,8 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6 | |||
502 | __asm__ __volatile__ ( \ | 506 | __asm__ __volatile__ ( \ |
503 | __syscall(name) \ | 507 | __syscall(name) \ |
504 | : "=r" (__res_r0) \ | 508 | : "=r" (__res_r0) \ |
505 | : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3), "r" (__r4),"r" (__r5) \ | 509 | : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \ |
506 | : "lr"); \ | 510 | "r" (__r3), "r" (__r4), "r" (__r5) ) ); \ |
507 | __res = __res_r0; \ | 511 | __res = __res_r0; \ |
508 | __syscall_return(type,__res); \ | 512 | __syscall_return(type,__res); \ |
509 | } | 513 | } |