aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorNicolas Pitre <nico@cam.org>2006-01-14 11:31:29 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-01-14 11:31:29 -0500
commit3f2829a31573e3e502b874c8d69a765f7a778793 (patch)
tree40f64826c0d2964c56c366f770e2d3959123eb59 /arch/arm/kernel
parentba95e4e4a0a8a3c6aba363d45f78d5f2e2d111eb (diff)
[ARM] 3105/4: ARM EABI: new syscall entry convention
Patch from Nicolas Pitre For a while we wanted to change the way syscalls were called on ARM. Instead of encoding the syscall number in the swi instruction which requires reading back the instruction from memory to extract that number and polluting the data cache, it was decided that simply storing the syscall number into r7 would be more efficient. Since this represents an ABI change then making that change at the same time as EABI support is the right thing to do. It is now expected that EABI user space binaries put the syscall number into r7 and use "swi 0" to call the kernel. Syscall register argument are also expected to have "EABI arrangement" i.e. 64-bit arguments should be put in a pair of registers from an even register number. Example with long ftruncate64(unsigned int fd, loff_t length): legacy ABI: - put fd into r0 - put length into r1-r2 - use "swi #(0x900000 + 194)" to call the kernel new ARM EABI: - put fd into r0 - put length into r2-r3 (skipping over r1) - put 194 into r7 - use "swi 0" to call the kernel Note that it is important to use 0 for the swi argument as backward compatibility with legacy ABI user space relies on this. The syscall macros in asm-arm/unistd.h were also updated to support both ABIs and implement the right call method automatically. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/entry-common.S35
-rw-r--r--arch/arm/kernel/traps.c2
2 files changed, 22 insertions, 15 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
209sys_syscall: 214sys_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
221sys_fork_wrapper: 228sys_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) {