| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /* | 
					
						
							|  |  |  |  *  linux/arch/arm/kernel/entry-common.S | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  Copyright (C) 2000 Russell King | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or modify
 | 
					
						
							|  |  |  |  * it under the terms of the GNU General Public License version 2 as | 
					
						
							|  |  |  |  * published by the Free Software Foundation. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-30 16:29:12 +01:00
										 |  |  | #include <asm/assembler.h> | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include <asm/unistd.h> | 
					
						
							| 
									
										
										
										
											2008-06-21 23:47:27 +05:30
										 |  |  | #include <asm/ftrace.h> | 
					
						
							| 
									
										
										
										
											2009-02-16 11:42:09 +01:00
										 |  |  | #include <asm/unwind.h> | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-07 09:28:22 -06:00
										 |  |  | #ifdef CONFIG_NEED_RET_TO_USER | 
					
						
							|  |  |  | #include <mach/entry-macro.S> | 
					
						
							|  |  |  | #else | 
					
						
							|  |  |  | 	.macro  arch_ret_to_user, tmp1, tmp2 | 
					
						
							|  |  |  | 	.endm | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include "entry-header.S" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.align	5
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * This is the fast syscall return path.  We do as little as | 
					
						
							|  |  |  |  * possible here, and this includes saving r0 back into the SVC | 
					
						
							|  |  |  |  * stack. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | ret_fast_syscall: | 
					
						
							| 
									
										
										
										
											2009-02-16 11:42:09 +01:00
										 |  |  |  UNWIND(.fnstart	) | 
					
						
							|  |  |  |  UNWIND(.cantunwind	) | 
					
						
							| 
									
										
										
										
											2005-04-26 15:18:26 +01:00
										 |  |  | 	disable_irq				@ disable interrupts
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	ldr	r1, [tsk, #TI_FLAGS] | 
					
						
							|  |  |  | 	tst	r1, #_TIF_WORK_MASK | 
					
						
							|  |  |  | 	bne	fast_work_pending | 
					
						
							| 
									
										
										
										
											2010-12-23 01:52:44 +01:00
										 |  |  | 	asm_trace_hardirqs_on | 
					
						
							| 
									
										
										
										
											2005-04-26 15:20:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-16 22:16:32 +01:00
										 |  |  | 	/* perform architecture specific actions before user return */ | 
					
						
							|  |  |  | 	arch_ret_to_user r1, lr | 
					
						
							| 
									
										
										
										
											2013-03-28 22:54:40 +01:00
										 |  |  | 	ct_user_enter | 
					
						
							| 
									
										
										
										
											2007-02-16 22:16:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-24 12:32:54 +01:00
										 |  |  | 	restore_user_regs fast = 1, offset = S_OFF | 
					
						
							| 
									
										
										
										
											2009-02-16 11:42:09 +01:00
										 |  |  |  UNWIND(.fnend		) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * Ok, we need to do extra processing, enter the slow path. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | fast_work_pending: | 
					
						
							|  |  |  | 	str	r0, [sp, #S_R0+S_OFF]!		@ returned r0
 | 
					
						
							|  |  |  | work_pending: | 
					
						
							|  |  |  | 	mov	r0, sp				@ 'regs'
 | 
					
						
							|  |  |  | 	mov	r2, why				@ 'syscall'
 | 
					
						
							| 
									
										
										
										
											2012-07-19 17:47:55 +01:00
										 |  |  | 	bl	do_work_pending | 
					
						
							| 
									
										
										
										
											2012-07-19 17:48:50 +01:00
										 |  |  | 	cmp	r0, #0 | 
					
						
							| 
									
										
										
										
											2012-07-19 17:48:21 +01:00
										 |  |  | 	beq	no_work_pending | 
					
						
							| 
									
										
										
										
											2012-07-19 17:48:50 +01:00
										 |  |  | 	movlt	scno, #(__NR_restart_syscall - __NR_SYSCALL_BASE) | 
					
						
							| 
									
										
										
										
											2012-07-19 17:48:21 +01:00
										 |  |  | 	ldmia	sp, {r0 - r6}			@ have to reload r0 - r6
 | 
					
						
							|  |  |  | 	b	local_restart			@ ... and off we go
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /* | 
					
						
							|  |  |  |  * "slow" syscall return path.  "why" tells us if this was a real syscall. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | ENTRY(ret_to_user) | 
					
						
							|  |  |  | ret_slow_syscall: | 
					
						
							| 
									
										
										
										
											2005-04-26 15:18:26 +01:00
										 |  |  | 	disable_irq				@ disable interrupts
 | 
					
						
							| 
									
										
										
										
											2011-06-05 02:24:58 +01:00
										 |  |  | ENTRY(ret_to_user_from_irq) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	ldr	r1, [tsk, #TI_FLAGS] | 
					
						
							|  |  |  | 	tst	r1, #_TIF_WORK_MASK | 
					
						
							|  |  |  | 	bne	work_pending | 
					
						
							|  |  |  | no_work_pending: | 
					
						
							| 
									
										
										
										
											2010-12-23 01:52:44 +01:00
										 |  |  | 	asm_trace_hardirqs_on | 
					
						
							| 
									
										
										
										
											2013-03-28 11:44:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-16 22:16:32 +01:00
										 |  |  | 	/* perform architecture specific actions before user return */ | 
					
						
							|  |  |  | 	arch_ret_to_user r1, lr | 
					
						
							| 
									
										
										
										
											2013-03-28 22:54:40 +01:00
										 |  |  | 	ct_user_enter save = 0 | 
					
						
							| 
									
										
										
										
											2007-02-16 22:16:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-24 12:32:54 +01:00
										 |  |  | 	restore_user_regs fast = 0, offset = 0 | 
					
						
							| 
									
										
										
										
											2011-06-05 02:24:58 +01:00
										 |  |  | ENDPROC(ret_to_user_from_irq) | 
					
						
							| 
									
										
										
										
											2008-08-28 11:22:32 +01:00
										 |  |  | ENDPROC(ret_to_user) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * This is how we return from a fork. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | ENTRY(ret_from_fork) | 
					
						
							|  |  |  | 	bl	schedule_tail | 
					
						
							| 
									
										
										
										
											2012-10-10 22:23:29 -04:00
										 |  |  | 	cmp	r5, #0 | 
					
						
							|  |  |  | 	movne	r0, r4 | 
					
						
							| 
									
										
											  
											
												ARM: fix oops on initial entry to userspace with Thumb2 kernels
Daniel Mack reports an oops at boot with the latest kernels:
  Internal error: Oops - undefined instruction: 0 [#1] SMP THUMB2
  Modules linked in:
  CPU: 0    Not tainted  (3.6.0-11057-g584df1d #145)
  PC is at cpsw_probe+0x45a/0x9ac
  LR is at trace_hardirqs_on_caller+0x8f/0xfc
  pc : [<c03493de>]    lr : [<c005e81f>]    psr: 60000113
  sp : cf055fb0  ip : 00000000  fp : 00000000
  r10: 00000000  r9 : 00000000  r8 : 00000000
  r7 : 00000000  r6 : 00000000  r5 : c0344555  r4 : 00000000
  r3 : cf057a40  r2 : 00000000  r1 : 00000001  r0 : 00000000
  Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM Segment user
  Control: 50c5387d  Table: 8f3f4019  DAC: 00000015
  Process init (pid: 1, stack limit = 0xcf054240)
  Stack: (0xcf055fb0 to 0xcf056000)
  5fa0:                                     00000001 00000000 00000000 00000000
  5fc0: cf055fb0 c000d1a8 00000000 00000000 00000000 00000000 00000000 00000000
  5fe0: 00000000 be9b3f10 00000000 b6f6add0 00000010 00000000 aaaabfaf a8babbaa
The analysis of this is as follows.  In init/main.c, we issue:
	kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
This creates a new thread, which falls through to the ret_from_fork
assembly, with r4 set NULL and r5 set to kernel_init.  You can see
this in your oops dump register set - r5 is 0xc0344555, which is the
address of kernel_init plus 1 which marks the function as Thumb code.
Now, let's look at this code a little closer - this is what the
disassembly looks like:
  c000d180 <ret_from_fork>:
  c000d180:       f03a fe08       bl      c0047d94 <schedule_tail>
  c000d184:       2d00            cmp     r5, #0
  c000d186:       bf1e            ittt    ne
  c000d188:       4620            movne   r0, r4
  c000d18a:       46fe            movne   lr, pc <-- XXXXXXX
  c000d18c:       46af            movne   pc, r5
  c000d18e:       46e9            mov     r9, sp
  c000d190:       ea4f 3959       mov.w   r9, r9, lsr #13
  c000d194:       ea4f 3949       mov.w   r9, r9, lsl #13
  c000d198:       e7c8            b.n     c000d12c <ret_to_user>
  c000d19a:       bf00            nop
  c000d19c:       f3af 8000       nop.w
This code was introduced in 9fff2fa0db911 (arm: switch to saner
kernel_execve() semantics).  I have marked one instruction, and it's
the significant one - I'll come back to that later.
Eventually, having had a successful call to kernel_execve(), kernel_init()
returns zero.
In returning, it uses the value in 'lr' which was set by the instruction
I marked above.  Unfortunately, this causes lr to contain 0xc000d18e -
an even address.  This switches the ISA to ARM on return but with a non
word aligned PC value.
So, what do we end up executing?  Well, not the instructions above - yes
the opcodes, but they don't mean the same thing in ARM mode.  In ARM mode,
it looks like this instead:
  c000d18c:       46e946af        strbtmi r4, [r9], pc, lsr #13
  c000d190:       3959ea4f        ldmdbcc r9, {r0, r1, r2, r3, r6, r9, fp, sp, lr, pc}^
  c000d194:       3949ea4f        stmdbcc r9, {r0, r1, r2, r3, r6, r9, fp, sp, lr, pc}^
  c000d198:       bf00e7c8        svclt   0x0000e7c8
  c000d19c:       8000f3af        andhi   pc, r0, pc, lsr #7
  c000d1a0:       e88db092        stm     sp, {r1, r4, r7, ip, sp, pc}
  c000d1a4:       46e81fff                        ; <UNDEFINED> instruction: 0x46e81fff
  c000d1a8:       8a00f3ef        bhi     0xc004a16c
  c000d1ac:       0a0cf08a        beq     0xc03493dc
I have included more above, because it's relevant.  The PSR flags which
we can see in the oops dump are nZCv, so Z and C are set.
All the above ARM instructions are not executed, except for two.
c000d1a0, which has no writeback, and writes below the current stack
pointer (and that data is lost when we take the next exception.) The
other instruction which is executed is c000d1ac, which takes us to...
0xc03493dc.  However, remember that bit 1 of the PC got set.  So that
makes the PC value 0xc03493de.
And that value is the value we find in the oops dump for PC.  What is
the instruction here when interpreted in ARM mode?
       0:       f71e150c                ; <UNDEFINED> instruction: 0xf71e150c
and there we have our undefined instruction (remember that the 'never'
condition code, 0xf, has been deprecated and is now always executed as
it is now being used for additional instructions.)
This path also nicely explains the state of the stack we see in the oops
dump too.
The above is a consistent and sane story for how we got to the oops
dump, which all stems from the instruction at 0xc000d18a being wrong.
Reported-by: Daniel Mack <zonque@gmail.com>
Tested-by: Daniel Mack <zonque@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
											
										 
											2012-10-15 00:16:49 +01:00
										 |  |  | 	adrne	lr, BSYM(1f) | 
					
						
							| 
									
										
										
										
											2014-06-30 16:29:12 +01:00
										 |  |  | 	retne	r5 | 
					
						
							| 
									
										
											  
											
												ARM: fix oops on initial entry to userspace with Thumb2 kernels
Daniel Mack reports an oops at boot with the latest kernels:
  Internal error: Oops - undefined instruction: 0 [#1] SMP THUMB2
  Modules linked in:
  CPU: 0    Not tainted  (3.6.0-11057-g584df1d #145)
  PC is at cpsw_probe+0x45a/0x9ac
  LR is at trace_hardirqs_on_caller+0x8f/0xfc
  pc : [<c03493de>]    lr : [<c005e81f>]    psr: 60000113
  sp : cf055fb0  ip : 00000000  fp : 00000000
  r10: 00000000  r9 : 00000000  r8 : 00000000
  r7 : 00000000  r6 : 00000000  r5 : c0344555  r4 : 00000000
  r3 : cf057a40  r2 : 00000000  r1 : 00000001  r0 : 00000000
  Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM Segment user
  Control: 50c5387d  Table: 8f3f4019  DAC: 00000015
  Process init (pid: 1, stack limit = 0xcf054240)
  Stack: (0xcf055fb0 to 0xcf056000)
  5fa0:                                     00000001 00000000 00000000 00000000
  5fc0: cf055fb0 c000d1a8 00000000 00000000 00000000 00000000 00000000 00000000
  5fe0: 00000000 be9b3f10 00000000 b6f6add0 00000010 00000000 aaaabfaf a8babbaa
The analysis of this is as follows.  In init/main.c, we issue:
	kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
This creates a new thread, which falls through to the ret_from_fork
assembly, with r4 set NULL and r5 set to kernel_init.  You can see
this in your oops dump register set - r5 is 0xc0344555, which is the
address of kernel_init plus 1 which marks the function as Thumb code.
Now, let's look at this code a little closer - this is what the
disassembly looks like:
  c000d180 <ret_from_fork>:
  c000d180:       f03a fe08       bl      c0047d94 <schedule_tail>
  c000d184:       2d00            cmp     r5, #0
  c000d186:       bf1e            ittt    ne
  c000d188:       4620            movne   r0, r4
  c000d18a:       46fe            movne   lr, pc <-- XXXXXXX
  c000d18c:       46af            movne   pc, r5
  c000d18e:       46e9            mov     r9, sp
  c000d190:       ea4f 3959       mov.w   r9, r9, lsr #13
  c000d194:       ea4f 3949       mov.w   r9, r9, lsl #13
  c000d198:       e7c8            b.n     c000d12c <ret_to_user>
  c000d19a:       bf00            nop
  c000d19c:       f3af 8000       nop.w
This code was introduced in 9fff2fa0db911 (arm: switch to saner
kernel_execve() semantics).  I have marked one instruction, and it's
the significant one - I'll come back to that later.
Eventually, having had a successful call to kernel_execve(), kernel_init()
returns zero.
In returning, it uses the value in 'lr' which was set by the instruction
I marked above.  Unfortunately, this causes lr to contain 0xc000d18e -
an even address.  This switches the ISA to ARM on return but with a non
word aligned PC value.
So, what do we end up executing?  Well, not the instructions above - yes
the opcodes, but they don't mean the same thing in ARM mode.  In ARM mode,
it looks like this instead:
  c000d18c:       46e946af        strbtmi r4, [r9], pc, lsr #13
  c000d190:       3959ea4f        ldmdbcc r9, {r0, r1, r2, r3, r6, r9, fp, sp, lr, pc}^
  c000d194:       3949ea4f        stmdbcc r9, {r0, r1, r2, r3, r6, r9, fp, sp, lr, pc}^
  c000d198:       bf00e7c8        svclt   0x0000e7c8
  c000d19c:       8000f3af        andhi   pc, r0, pc, lsr #7
  c000d1a0:       e88db092        stm     sp, {r1, r4, r7, ip, sp, pc}
  c000d1a4:       46e81fff                        ; <UNDEFINED> instruction: 0x46e81fff
  c000d1a8:       8a00f3ef        bhi     0xc004a16c
  c000d1ac:       0a0cf08a        beq     0xc03493dc
I have included more above, because it's relevant.  The PSR flags which
we can see in the oops dump are nZCv, so Z and C are set.
All the above ARM instructions are not executed, except for two.
c000d1a0, which has no writeback, and writes below the current stack
pointer (and that data is lost when we take the next exception.) The
other instruction which is executed is c000d1ac, which takes us to...
0xc03493dc.  However, remember that bit 1 of the PC got set.  So that
makes the PC value 0xc03493de.
And that value is the value we find in the oops dump for PC.  What is
the instruction here when interpreted in ARM mode?
       0:       f71e150c                ; <UNDEFINED> instruction: 0xf71e150c
and there we have our undefined instruction (remember that the 'never'
condition code, 0xf, has been deprecated and is now always executed as
it is now being used for additional instructions.)
This path also nicely explains the state of the stack we see in the oops
dump too.
The above is a consistent and sane story for how we got to the oops
dump, which all stems from the instruction at 0xc000d18a being wrong.
Reported-by: Daniel Mack <zonque@gmail.com>
Tested-by: Daniel Mack <zonque@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
											
										 
											2012-10-15 00:16:49 +01:00
										 |  |  | 1:	get_thread_info tsk | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	b	ret_slow_syscall | 
					
						
							| 
									
										
										
										
											2008-08-28 11:22:32 +01:00
										 |  |  | ENDPROC(ret_from_fork) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-19 12:57:01 +00:00
										 |  |  | 	.equ NR_syscalls,0 | 
					
						
							|  |  |  | #define CALL(x) .equ NR_syscalls,NR_syscalls+1 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include "calls.S" | 
					
						
							| 
									
										
										
										
											2012-09-07 18:18:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * Ensure that the system call table is equal to __NR_syscalls, | 
					
						
							|  |  |  |  * which is the value the rest of the system sees | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | .ifne NR_syscalls - __NR_syscalls | 
					
						
							|  |  |  | .error "__NR_syscalls is not equal to the size of the syscall table" | 
					
						
							|  |  |  | .endif | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-19 12:57:01 +00:00
										 |  |  | #undef CALL | 
					
						
							|  |  |  | #define CALL(x) .long x | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-06 19:06:12 -04:00
										 |  |  | #ifdef CONFIG_FUNCTION_TRACER | 
					
						
							| 
									
										
										
										
											2010-08-03 17:09:40 +01:00
										 |  |  | /* | 
					
						
							|  |  |  |  * When compiling with -pg, gcc inserts a call to the mcount routine at the | 
					
						
							|  |  |  |  * start of every function.  In mcount, apart from the function's address (in | 
					
						
							|  |  |  |  * lr), we need to get hold of the function's caller's address. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Older GCCs (pre-4.4) inserted a call to a routine called mcount like this: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	bl	mcount | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * These versions have the limitation that in order for the mcount routine to | 
					
						
							|  |  |  |  * be able to determine the function's caller's address, an APCS-style frame | 
					
						
							|  |  |  |  * pointer (which is set up with something like the code below) is required. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	mov     ip, sp | 
					
						
							|  |  |  |  *	push    {fp, ip, lr, pc} | 
					
						
							|  |  |  |  *	sub     fp, ip, #4 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * With EABI, these frame pointers are not available unless -mapcs-frame is | 
					
						
							|  |  |  |  * specified, and if building as Thumb-2, not even then. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Newer GCCs (4.4+) solve this problem by introducing a new version of mcount, | 
					
						
							|  |  |  |  * with call sites like: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	push	{lr} | 
					
						
							|  |  |  |  *	bl	__gnu_mcount_nc | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * With these compilers, frame pointers are not necessary. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * mcount can be thought of as a function called in the middle of a subroutine | 
					
						
							|  |  |  |  * call.  As such, it needs to be transparent for both the caller and the | 
					
						
							|  |  |  |  * callee: the original lr needs to be restored when leaving mcount, and no | 
					
						
							|  |  |  |  * registers should be clobbered.  (In the __gnu_mcount_nc implementation, we | 
					
						
							|  |  |  |  * clobber the ip register.  This is OK because the ARM calling convention | 
					
						
							|  |  |  |  * allows it to be clobbered in subroutines and doesn't use it to hold | 
					
						
							|  |  |  |  * parameters.) | 
					
						
							| 
									
										
										
										
											2010-08-10 19:43:28 +01:00
										 |  |  |  * | 
					
						
							|  |  |  |  * When using dynamic ftrace, we patch out the mcount call by a "mov r0, r0" | 
					
						
							|  |  |  |  * for the mcount case, and a "pop {lr}" for the __gnu_mcount_nc case (see | 
					
						
							|  |  |  |  * arch/arm/kernel/ftrace.c). | 
					
						
							| 
									
										
										
										
											2010-08-03 17:09:40 +01:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2010-08-10 19:32:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifndef CONFIG_OLD_MCOUNT | 
					
						
							|  |  |  | #if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) | 
					
						
							|  |  |  | #error Ftrace requires CONFIG_FRAME_POINTER=y with GCC older than 4.4.0. | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-24 16:52:52 +01:00
										 |  |  | .macro mcount_adjust_addr rd, rn | 
					
						
							|  |  |  | 	bic	\rd, \rn, #1		@ clear the Thumb bit if present
 | 
					
						
							|  |  |  | 	sub	\rd, \rd, #MCOUNT_INSN_SIZE | 
					
						
							|  |  |  | .endm | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | .macro __mcount suffix | 
					
						
							|  |  |  | 	mcount_enter | 
					
						
							|  |  |  | 	ldr	r0, =ftrace_trace_function | 
					
						
							|  |  |  | 	ldr	r2, [r0] | 
					
						
							|  |  |  | 	adr	r0, .Lftrace_stub | 
					
						
							|  |  |  | 	cmp	r0, r2 | 
					
						
							|  |  |  | 	bne	1f | 
					
						
							| 
									
										
										
										
											2010-08-10 19:43:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 22:24:38 +05:30
										 |  |  | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 
					
						
							|  |  |  | 	ldr     r1, =ftrace_graph_return | 
					
						
							|  |  |  | 	ldr     r2, [r1] | 
					
						
							|  |  |  | 	cmp     r0, r2 | 
					
						
							|  |  |  | 	bne     ftrace_graph_caller\suffix | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ldr     r1, =ftrace_graph_entry | 
					
						
							|  |  |  | 	ldr     r2, [r1] | 
					
						
							|  |  |  | 	ldr     r0, =ftrace_graph_entry_stub | 
					
						
							|  |  |  | 	cmp     r0, r2 | 
					
						
							|  |  |  | 	bne     ftrace_graph_caller\suffix | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | 	mcount_exit | 
					
						
							| 
									
										
										
										
											2010-08-10 19:43:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | 1: 	mcount_get_lr	r1			@ lr of instrumented func
 | 
					
						
							| 
									
										
										
										
											2012-01-24 16:52:52 +01:00
										 |  |  | 	mcount_adjust_addr	r0, lr		@ instrumented function
 | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | 	adr	lr, BSYM(2f) | 
					
						
							|  |  |  | 	mov	pc, r2 | 
					
						
							|  |  |  | 2:	mcount_exit | 
					
						
							|  |  |  | .endm | 
					
						
							| 
									
										
										
										
											2008-05-31 14:23:50 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | .macro __ftrace_caller suffix | 
					
						
							|  |  |  | 	mcount_enter | 
					
						
							| 
									
										
										
										
											2008-05-31 14:23:50 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | 	mcount_get_lr	r1			@ lr of instrumented func
 | 
					
						
							| 
									
										
										
										
											2012-01-24 16:52:52 +01:00
										 |  |  | 	mcount_adjust_addr	r0, lr		@ instrumented function
 | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | 	.globl ftrace_call\suffix | 
					
						
							|  |  |  | ftrace_call\suffix: | 
					
						
							| 
									
										
										
										
											2010-08-03 17:08:09 +01:00
										 |  |  | 	bl	ftrace_stub | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-06 23:03:21 +05:30
										 |  |  | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 
					
						
							|  |  |  | 	.globl ftrace_graph_call\suffix | 
					
						
							|  |  |  | ftrace_graph_call\suffix: | 
					
						
							|  |  |  | 	mov	r0, r0 | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | 	mcount_exit | 
					
						
							|  |  |  | .endm | 
					
						
							| 
									
										
										
										
											2008-05-31 14:23:50 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 22:24:38 +05:30
										 |  |  | .macro __ftrace_graph_caller
 | 
					
						
							|  |  |  | 	sub	r0, fp, #4		@ &lr of instrumented routine (&parent)
 | 
					
						
							| 
									
										
										
										
											2010-11-06 23:03:21 +05:30
										 |  |  | #ifdef CONFIG_DYNAMIC_FTRACE | 
					
						
							|  |  |  | 	@ called from __ftrace_caller, saved in mcount_enter
 | 
					
						
							|  |  |  | 	ldr	r1, [sp, #16]		@ instrumented routine (func)
 | 
					
						
							| 
									
										
										
										
											2012-01-24 16:52:52 +01:00
										 |  |  | 	mcount_adjust_addr	r1, r1 | 
					
						
							| 
									
										
										
										
											2010-11-06 23:03:21 +05:30
										 |  |  | #else | 
					
						
							|  |  |  | 	@ called from __mcount, untouched in lr
 | 
					
						
							| 
									
										
										
										
											2012-01-24 16:52:52 +01:00
										 |  |  | 	mcount_adjust_addr	r1, lr	@ instrumented routine (func)
 | 
					
						
							| 
									
										
										
										
											2010-11-06 23:03:21 +05:30
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2010-10-09 22:24:38 +05:30
										 |  |  | 	mov	r2, fp			@ frame pointer
 | 
					
						
							|  |  |  | 	bl	prepare_ftrace_return | 
					
						
							|  |  |  | 	mcount_exit | 
					
						
							|  |  |  | .endm | 
					
						
							| 
									
										
										
										
											2008-05-31 14:23:50 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-10 19:43:28 +01:00
										 |  |  | #ifdef CONFIG_OLD_MCOUNT | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | /* | 
					
						
							|  |  |  |  * mcount | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .macro mcount_enter
 | 
					
						
							|  |  |  | 	stmdb	sp!, {r0-r3, lr} | 
					
						
							|  |  |  | .endm | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .macro mcount_get_lr reg | 
					
						
							|  |  |  | 	ldr	\reg, [fp, #-4] | 
					
						
							|  |  |  | .endm | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .macro mcount_exit
 | 
					
						
							|  |  |  | 	ldr	lr, [fp, #-4] | 
					
						
							|  |  |  | 	ldmia	sp!, {r0-r3, pc} | 
					
						
							|  |  |  | .endm | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-10 19:43:28 +01:00
										 |  |  | ENTRY(mcount) | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | #ifdef CONFIG_DYNAMIC_FTRACE | 
					
						
							| 
									
										
										
										
											2010-08-10 19:43:28 +01:00
										 |  |  | 	stmdb	sp!, {lr} | 
					
						
							|  |  |  | 	ldr	lr, [fp, #-4] | 
					
						
							|  |  |  | 	ldmia	sp!, {pc} | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | #else | 
					
						
							|  |  |  | 	__mcount _old | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											2010-08-10 19:33:52 +01:00
										 |  |  | ENDPROC(mcount) | 
					
						
							| 
									
										
										
										
											2008-05-31 14:23:50 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | #ifdef CONFIG_DYNAMIC_FTRACE | 
					
						
							| 
									
										
										
										
											2010-08-10 19:43:28 +01:00
										 |  |  | ENTRY(ftrace_caller_old) | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | 	__ftrace_caller _old | 
					
						
							| 
									
										
										
										
											2010-08-10 19:43:28 +01:00
										 |  |  | ENDPROC(ftrace_caller_old) | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											2008-05-31 14:23:50 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 22:24:38 +05:30
										 |  |  | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 
					
						
							|  |  |  | ENTRY(ftrace_graph_caller_old) | 
					
						
							|  |  |  | 	__ftrace_graph_caller | 
					
						
							|  |  |  | ENDPROC(ftrace_graph_caller_old) | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											2008-05-31 14:23:50 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | .purgem mcount_enter
 | 
					
						
							|  |  |  | .purgem mcount_get_lr
 | 
					
						
							|  |  |  | .purgem mcount_exit
 | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											2008-05-31 14:23:50 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | /* | 
					
						
							|  |  |  |  * __gnu_mcount_nc | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .macro mcount_enter
 | 
					
						
							| 
									
										
										
										
											2013-04-02 22:11:46 +01:00
										 |  |  | /* | 
					
						
							|  |  |  |  * This pad compensates for the push {lr} at the call site.  Note that we are | 
					
						
							|  |  |  |  * unable to unwind through a function which does not otherwise save its lr. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  |  UNWIND(.pad	#4) | 
					
						
							| 
									
										
										
										
											2010-08-03 17:08:09 +01:00
										 |  |  | 	stmdb	sp!, {r0-r3, lr} | 
					
						
							| 
									
										
										
										
											2013-04-02 22:11:46 +01:00
										 |  |  |  UNWIND(.save	{r0-r3, lr}) | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | .endm | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .macro mcount_get_lr reg | 
					
						
							|  |  |  | 	ldr	\reg, [sp, #20] | 
					
						
							|  |  |  | .endm | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .macro mcount_exit
 | 
					
						
							| 
									
										
										
										
											2010-08-03 17:08:09 +01:00
										 |  |  | 	ldmia	sp!, {r0-r3, ip, lr} | 
					
						
							| 
									
										
										
										
											2014-06-30 16:29:12 +01:00
										 |  |  | 	ret	ip | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | .endm | 
					
						
							| 
									
										
										
										
											2009-08-13 20:38:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | ENTRY(__gnu_mcount_nc) | 
					
						
							| 
									
										
										
										
											2013-04-02 22:11:46 +01:00
										 |  |  | UNWIND(.fnstart) | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | #ifdef CONFIG_DYNAMIC_FTRACE | 
					
						
							|  |  |  | 	mov	ip, lr | 
					
						
							|  |  |  | 	ldmia	sp!, {lr} | 
					
						
							| 
									
										
										
										
											2014-06-30 16:29:12 +01:00
										 |  |  | 	ret	ip | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | #else | 
					
						
							|  |  |  | 	__mcount | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											2013-04-02 22:11:46 +01:00
										 |  |  | UNWIND(.fnend) | 
					
						
							| 
									
										
										
										
											2010-08-10 19:33:52 +01:00
										 |  |  | ENDPROC(__gnu_mcount_nc) | 
					
						
							| 
									
										
										
										
											2009-08-13 20:38:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | #ifdef CONFIG_DYNAMIC_FTRACE | 
					
						
							|  |  |  | ENTRY(ftrace_caller) | 
					
						
							| 
									
										
										
										
											2013-04-02 22:11:46 +01:00
										 |  |  | UNWIND(.fnstart) | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | 	__ftrace_caller | 
					
						
							| 
									
										
										
										
											2013-04-02 22:11:46 +01:00
										 |  |  | UNWIND(.fnend) | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | ENDPROC(ftrace_caller) | 
					
						
							| 
									
										
										
										
											2010-08-10 19:32:37 +01:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2008-05-31 14:23:50 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 22:24:38 +05:30
										 |  |  | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 
					
						
							|  |  |  | ENTRY(ftrace_graph_caller) | 
					
						
							| 
									
										
										
										
											2013-04-02 22:11:46 +01:00
										 |  |  | UNWIND(.fnstart) | 
					
						
							| 
									
										
										
										
											2010-10-09 22:24:38 +05:30
										 |  |  | 	__ftrace_graph_caller | 
					
						
							| 
									
										
										
										
											2013-04-02 22:11:46 +01:00
										 |  |  | UNWIND(.fnend) | 
					
						
							| 
									
										
										
										
											2010-10-09 22:24:38 +05:30
										 |  |  | ENDPROC(ftrace_graph_caller) | 
					
						
							| 
									
										
										
										
											2010-08-10 19:32:37 +01:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2008-05-31 14:23:50 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-07 17:39:47 +05:30
										 |  |  | .purgem mcount_enter
 | 
					
						
							|  |  |  | .purgem mcount_get_lr
 | 
					
						
							|  |  |  | .purgem mcount_exit
 | 
					
						
							| 
									
										
										
										
											2008-05-31 14:23:50 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 22:24:38 +05:30
										 |  |  | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 
					
						
							|  |  |  | 	.globl return_to_handler
 | 
					
						
							|  |  |  | return_to_handler: | 
					
						
							|  |  |  | 	stmdb	sp!, {r0-r3} | 
					
						
							|  |  |  | 	mov	r0, fp			@ frame pointer
 | 
					
						
							|  |  |  | 	bl	ftrace_return_to_handler | 
					
						
							|  |  |  | 	mov	lr, r0			@ r0 has real ret addr
 | 
					
						
							|  |  |  | 	ldmia	sp!, {r0-r3} | 
					
						
							| 
									
										
										
										
											2014-06-30 16:29:12 +01:00
										 |  |  | 	ret	lr | 
					
						
							| 
									
										
										
										
											2010-10-09 22:24:38 +05:30
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2008-05-31 14:23:50 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-10 19:33:52 +01:00
										 |  |  | ENTRY(ftrace_stub) | 
					
						
							| 
									
										
										
										
											2010-08-10 19:37:21 +01:00
										 |  |  | .Lftrace_stub: | 
					
						
							| 
									
										
										
										
											2014-06-30 16:29:12 +01:00
										 |  |  | 	ret	lr | 
					
						
							| 
									
										
										
										
											2010-08-10 19:33:52 +01:00
										 |  |  | ENDPROC(ftrace_stub) | 
					
						
							| 
									
										
										
										
											2008-05-31 14:23:50 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-06 19:06:12 -04:00
										 |  |  | #endif /* CONFIG_FUNCTION_TRACER */ | 
					
						
							| 
									
										
										
										
											2008-05-31 14:23:50 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*============================================================================= | 
					
						
							|  |  |  |  * SWI handler | 
					
						
							|  |  |  |  *----------------------------------------------------------------------------- | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.align	5
 | 
					
						
							|  |  |  | ENTRY(vector_swi) | 
					
						
							| 
									
										
										
										
											2010-05-21 18:06:42 +01:00
										 |  |  | #ifdef CONFIG_CPU_V7M | 
					
						
							|  |  |  | 	v7m_exception_entry | 
					
						
							|  |  |  | #else | 
					
						
							| 
									
										
										
										
											2005-04-26 15:20:34 +01:00
										 |  |  | 	sub	sp, sp, #S_FRAME_SIZE | 
					
						
							|  |  |  | 	stmia	sp, {r0 - r12}			@ Calling r0 - r12
 | 
					
						
							| 
									
										
										
										
											2009-07-24 12:32:54 +01:00
										 |  |  |  ARM(	add	r8, sp, #S_PC		) | 
					
						
							|  |  |  |  ARM(	stmdb	r8, {sp, lr}^		)	@ Calling sp, lr
 | 
					
						
							|  |  |  |  THUMB(	mov	r8, sp			) | 
					
						
							|  |  |  |  THUMB(	store_user_sp_lr r8, r10, S_SP	)	@ calling sp, lr
 | 
					
						
							| 
									
										
										
										
											2005-04-26 15:20:34 +01:00
										 |  |  | 	mrs	r8, spsr			@ called from non-FIQ mode, so ok.
 | 
					
						
							|  |  |  | 	str	lr, [sp, #S_PC]			@ Save calling PC | 
					
						
							|  |  |  | 	str	r8, [sp, #S_PSR]		@ Save CPSR | 
					
						
							|  |  |  | 	str	r0, [sp, #S_OLD_R0]		@ Save OLD_R0
 | 
					
						
							| 
									
										
										
										
											2010-05-21 18:06:42 +01:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	zero_fp | 
					
						
							| 
									
										
										
										
											2014-08-28 13:08:14 +01:00
										 |  |  | 	alignment_trap r10, ip, __cr_alignment | 
					
						
							| 
									
										
										
										
											2013-06-05 11:25:13 +01:00
										 |  |  | 	enable_irq | 
					
						
							|  |  |  | 	ct_user_exit | 
					
						
							|  |  |  | 	get_thread_info tsk | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-26 15:19:24 +01:00
										 |  |  | 	/* | 
					
						
							|  |  |  | 	 * Get the system call number. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2006-01-14 16:31:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-14 16:36:12 +00:00
										 |  |  | #if defined(CONFIG_OABI_COMPAT) | 
					
						
							| 
									
										
										
										
											2006-01-14 16:31:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-14 16:36:12 +00:00
										 |  |  | 	/* | 
					
						
							|  |  |  | 	 * If we have CONFIG_OABI_COMPAT then we need to look at the swi | 
					
						
							|  |  |  | 	 * value to determine if it is an EABI or an old ABI call. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | #ifdef CONFIG_ARM_THUMB | 
					
						
							|  |  |  | 	tst	r8, #PSR_T_BIT | 
					
						
							|  |  |  | 	movne	r10, #0				@ no thumb OABI emulation
 | 
					
						
							| 
									
										
										
										
											2013-06-05 11:25:13 +01:00
										 |  |  |  USER(	ldreq	r10, [lr, #-4]		)	@ get SWI instruction
 | 
					
						
							| 
									
										
										
										
											2006-01-14 16:36:12 +00:00
										 |  |  | #else | 
					
						
							| 
									
										
										
										
											2013-06-05 11:25:13 +01:00
										 |  |  |  USER(	ldr	r10, [lr, #-4]		)	@ get SWI instruction
 | 
					
						
							| 
									
										
										
										
											2006-01-14 16:36:12 +00:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2013-02-12 18:59:57 +00:00
										 |  |  |  ARM_BE8(rev	r10, r10)			@ little endian instruction
 | 
					
						
							| 
									
										
										
										
											2006-01-14 16:36:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #elif defined(CONFIG_AEABI) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * Pure EABI user space always put syscall number into scno (r7). | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2006-01-14 16:31:29 +00:00
										 |  |  | #elif defined(CONFIG_ARM_THUMB) | 
					
						
							| 
									
										
										
										
											2006-01-14 16:36:12 +00:00
										 |  |  | 	/* Legacy ABI only, possibly thumb mode. */ | 
					
						
							| 
									
										
										
										
											2005-04-26 15:19:24 +01:00
										 |  |  | 	tst	r8, #PSR_T_BIT			@ this is SPSR from save_user_regs | 
					
						
							|  |  |  | 	addne	scno, r7, #__NR_SYSCALL_BASE	@ put OS number in | 
					
						
							| 
									
										
										
										
											2013-06-05 11:25:13 +01:00
										 |  |  |  USER(	ldreq	scno, [lr, #-4]		) | 
					
						
							| 
									
										
										
										
											2006-01-14 16:36:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-26 15:19:24 +01:00
										 |  |  | #else | 
					
						
							| 
									
										
										
										
											2006-01-14 16:36:12 +00:00
										 |  |  | 	/* Legacy ABI only. */ | 
					
						
							| 
									
										
										
										
											2013-06-05 11:25:13 +01:00
										 |  |  |  USER(	ldr	scno, [lr, #-4]		)	@ get SWI instruction
 | 
					
						
							| 
									
										
										
										
											2005-04-26 15:19:24 +01:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-14 16:36:12 +00:00
										 |  |  | 	adr	tbl, sys_call_table		@ load syscall table pointer
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(CONFIG_OABI_COMPAT) | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * If the swi argument is zero, this is an EABI call and we do nothing. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * If this is an old ABI call, get the syscall number into scno and | 
					
						
							|  |  |  | 	 * get the old ABI syscall table address. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	bics	r10, r10, #0xff000000 | 
					
						
							|  |  |  | 	eorne	scno, r10, #__NR_OABI_SYSCALL_BASE | 
					
						
							|  |  |  | 	ldrne	tbl, =sys_oabi_call_table | 
					
						
							|  |  |  | #elif !defined(CONFIG_AEABI) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	bic	scno, scno, #0xff000000		@ mask off SWI op-code
 | 
					
						
							| 
									
										
										
										
											2005-04-26 15:19:24 +01:00
										 |  |  | 	eor	scno, scno, #__NR_SYSCALL_BASE	@ check OS number | 
					
						
							| 
									
										
										
										
											2006-01-14 16:31:29 +00:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2006-01-14 16:36:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-19 17:48:21 +01:00
										 |  |  | local_restart: | 
					
						
							| 
									
										
										
										
											2010-08-26 15:08:35 -07:00
										 |  |  | 	ldr	r10, [tsk, #TI_FLAGS]		@ check for syscall tracing | 
					
						
							| 
									
										
										
										
											2006-01-14 16:31:29 +00:00
										 |  |  | 	stmdb	sp!, {r4, r5}			@ push fifth and sixth args
 | 
					
						
							| 
									
										
										
										
											2010-08-26 15:08:35 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-03 14:23:09 -05:00
										 |  |  | 	tst	r10, #_TIF_SYSCALL_WORK		@ are we tracing syscalls? | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	bne	__sys_trace | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cmp	scno, #NR_syscalls		@ check upper syscall limit | 
					
						
							| 
									
										
										
										
											2009-07-24 12:32:54 +01:00
										 |  |  | 	adr	lr, BSYM(ret_fast_syscall)	@ return address
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	add	r1, sp, #S_OFF | 
					
						
							| 
									
										
										
										
											2013-09-19 10:32:20 +01:00
										 |  |  | 2:	cmp	scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE) | 
					
						
							| 
									
										
										
										
											2005-04-26 15:19:24 +01:00
										 |  |  | 	eor	r0, scno, #__NR_SYSCALL_BASE	@ put OS number back | 
					
						
							| 
									
										
										
										
											2013-05-13 19:16:34 +01:00
										 |  |  | 	bcs	arm_syscall | 
					
						
							| 
									
										
										
										
											2013-09-19 10:32:20 +01:00
										 |  |  | 	mov	why, #0				@ no longer a real syscall
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	b	sys_ni_syscall			@ not private func
 | 
					
						
							| 
									
										
										
										
											2013-06-05 11:25:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined(CONFIG_OABI_COMPAT) || !defined(CONFIG_AEABI) | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * We failed to handle a fault trying to access the page | 
					
						
							|  |  |  | 	 * containing the swi instruction, but we're not really in a | 
					
						
							|  |  |  | 	 * position to return -EFAULT. Instead, return back to the | 
					
						
							|  |  |  | 	 * instruction and re-enter the user fault handling path trying | 
					
						
							|  |  |  | 	 * to page it in. This will likely result in sending SEGV to the | 
					
						
							|  |  |  | 	 * current task. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 9001: | 
					
						
							|  |  |  | 	sub	lr, lr, #4 | 
					
						
							|  |  |  | 	str	lr, [sp, #S_PC] | 
					
						
							|  |  |  | 	b	ret_fast_syscall | 
					
						
							|  |  |  | #endif | 
					
						
							| 
									
										
										
										
											2008-08-28 11:22:32 +01:00
										 |  |  | ENDPROC(vector_swi) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 	 * This is the really slow path.  We're going to be doing | 
					
						
							|  |  |  | 	 * context switches, and waiting for our parent to respond. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | __sys_trace: | 
					
						
							| 
									
										
										
										
											2012-07-06 15:50:14 +01:00
										 |  |  | 	mov	r1, scno | 
					
						
							|  |  |  | 	add	r0, sp, #S_OFF | 
					
						
							|  |  |  | 	bl	syscall_trace_enter | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-24 12:32:54 +01:00
										 |  |  | 	adr	lr, BSYM(__sys_trace_return)	@ return address
 | 
					
						
							| 
									
										
										
										
											2006-01-14 19:30:04 +00:00
										 |  |  | 	mov	scno, r0			@ syscall number (possibly new)
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	add	r1, sp, #S_R0 + S_OFF		@ pointer to regs
 | 
					
						
							|  |  |  | 	cmp	scno, #NR_syscalls		@ check upper syscall limit | 
					
						
							| 
									
										
										
										
											2012-07-19 17:49:22 +01:00
										 |  |  | 	ldmccia	r1, {r0 - r6}			@ have to reload r0 - r6
 | 
					
						
							|  |  |  | 	stmccia	sp, {r4, r5}			@ and update the stack args
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine
 | 
					
						
							| 
									
										
										
										
											2012-11-15 22:12:17 +01:00
										 |  |  | 	cmp	scno, #-1			@ skip the syscall?
 | 
					
						
							|  |  |  | 	bne	2b | 
					
						
							|  |  |  | 	add	sp, sp, #S_OFF			@ restore stack | 
					
						
							|  |  |  | 	b	ret_slow_syscall | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | __sys_trace_return: | 
					
						
							|  |  |  | 	str	r0, [sp, #S_R0 + S_OFF]!	@ save returned r0
 | 
					
						
							| 
									
										
										
										
											2012-07-06 15:50:14 +01:00
										 |  |  | 	mov	r0, sp | 
					
						
							|  |  |  | 	bl	syscall_trace_exit | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	b	ret_slow_syscall | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.align	5
 | 
					
						
							|  |  |  | #ifdef CONFIG_ALIGNMENT_TRAP | 
					
						
							|  |  |  | 	.type	__cr_alignment, #object | 
					
						
							|  |  |  | __cr_alignment: | 
					
						
							|  |  |  | 	.word	cr_alignment
 | 
					
						
							| 
									
										
										
										
											2006-01-14 16:36:12 +00:00
										 |  |  | #endif | 
					
						
							|  |  |  | 	.ltorg | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * This is the syscall table declaration for native ABI syscalls. | 
					
						
							|  |  |  |  * With EABI a couple syscalls are obsolete and defined as sys_ni_syscall. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #define ABI(native, compat) native | 
					
						
							|  |  |  | #ifdef CONFIG_AEABI | 
					
						
							|  |  |  | #define OBSOLETE(syscall) sys_ni_syscall | 
					
						
							|  |  |  | #else | 
					
						
							|  |  |  | #define OBSOLETE(syscall) syscall | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.type	sys_call_table, #object | 
					
						
							|  |  |  | ENTRY(sys_call_table) | 
					
						
							|  |  |  | #include "calls.S" | 
					
						
							| 
									
										
										
										
											2006-01-14 16:36:12 +00:00
										 |  |  | #undef ABI | 
					
						
							|  |  |  | #undef OBSOLETE | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*============================================================================ | 
					
						
							|  |  |  |  * Special system call wrappers | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | @ r0 = syscall number
 | 
					
						
							| 
									
										
										
										
											2005-12-17 15:25:42 +00:00
										 |  |  | @ r8 = syscall table
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | sys_syscall: | 
					
						
							| 
									
										
										
										
											2006-05-16 14:25:55 +01:00
										 |  |  | 		bic	scno, r0, #__NR_OABI_SYSCALL_BASE | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		cmp	scno, #__NR_syscall - __NR_SYSCALL_BASE | 
					
						
							|  |  |  | 		cmpne	scno, #NR_syscalls	@ check range | 
					
						
							|  |  |  | 		stmloia	sp, {r5, r6}		@ shuffle args
 | 
					
						
							|  |  |  | 		movlo	r0, r1 | 
					
						
							|  |  |  | 		movlo	r1, r2 | 
					
						
							|  |  |  | 		movlo	r2, r3 | 
					
						
							|  |  |  | 		movlo	r3, r4 | 
					
						
							|  |  |  | 		ldrlo	pc, [tbl, scno, lsl #2] | 
					
						
							|  |  |  | 		b	sys_ni_syscall | 
					
						
							| 
									
										
										
										
											2008-08-28 11:22:32 +01:00
										 |  |  | ENDPROC(sys_syscall) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | sys_sigreturn_wrapper: | 
					
						
							|  |  |  | 		add	r0, sp, #S_OFF | 
					
						
							| 
									
										
											  
											
												arm: fix really nasty sigreturn bug
If a signal hits us outside of a syscall and another gets delivered
when we are in sigreturn (e.g. because it had been in sa_mask for
the first one and got sent to us while we'd been in the first handler),
we have a chance of returning from the second handler to location one
insn prior to where we ought to return.  If r0 happens to contain -513
(-ERESTARTNOINTR), sigreturn will get confused into doing restart
syscall song and dance.
Incredible joy to debug, since it manifests as random, infrequent and
very hard to reproduce double execution of instructions in userland
code...
The fix is simple - mark it "don't bother with restarts" in wrapper,
i.e. set r8 to 0 in sys_sigreturn and sys_rt_sigreturn wrappers,
suppressing the syscall restart handling on return from these guys.
They can't legitimately return a restart-worthy error anyway.
Testcase:
	#include <unistd.h>
	#include <signal.h>
	#include <stdlib.h>
	#include <sys/time.h>
	#include <errno.h>
	void f(int n)
	{
		__asm__ __volatile__(
			"ldr r0, [%0]\n"
			"b 1f\n"
			"b 2f\n"
			"1:b .\n"
			"2:\n" : : "r"(&n));
	}
	void handler1(int sig) { }
	void handler2(int sig) { raise(1); }
	void handler3(int sig) { exit(0); }
	main()
	{
		struct sigaction s = {.sa_handler = handler2};
		struct itimerval t1 = { .it_value = {1} };
		struct itimerval t2 = { .it_value = {2} };
		signal(1, handler1);
		sigemptyset(&s.sa_mask);
		sigaddset(&s.sa_mask, 1);
		sigaction(SIGALRM, &s, NULL);
		signal(SIGVTALRM, handler3);
		setitimer(ITIMER_REAL, &t1, NULL);
		setitimer(ITIMER_VIRTUAL, &t2, NULL);
		f(-513); /* -ERESTARTNOINTR */
		write(1, "buggered\n", 9);
		return 1;
	}
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: stable@kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
											
										 
											2010-09-17 14:34:39 +01:00
										 |  |  | 		mov	why, #0		@ prevent syscall restart handling
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		b	sys_sigreturn | 
					
						
							| 
									
										
										
										
											2008-08-28 11:22:32 +01:00
										 |  |  | ENDPROC(sys_sigreturn_wrapper) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | sys_rt_sigreturn_wrapper: | 
					
						
							|  |  |  | 		add	r0, sp, #S_OFF | 
					
						
							| 
									
										
											  
											
												arm: fix really nasty sigreturn bug
If a signal hits us outside of a syscall and another gets delivered
when we are in sigreturn (e.g. because it had been in sa_mask for
the first one and got sent to us while we'd been in the first handler),
we have a chance of returning from the second handler to location one
insn prior to where we ought to return.  If r0 happens to contain -513
(-ERESTARTNOINTR), sigreturn will get confused into doing restart
syscall song and dance.
Incredible joy to debug, since it manifests as random, infrequent and
very hard to reproduce double execution of instructions in userland
code...
The fix is simple - mark it "don't bother with restarts" in wrapper,
i.e. set r8 to 0 in sys_sigreturn and sys_rt_sigreturn wrappers,
suppressing the syscall restart handling on return from these guys.
They can't legitimately return a restart-worthy error anyway.
Testcase:
	#include <unistd.h>
	#include <signal.h>
	#include <stdlib.h>
	#include <sys/time.h>
	#include <errno.h>
	void f(int n)
	{
		__asm__ __volatile__(
			"ldr r0, [%0]\n"
			"b 1f\n"
			"b 2f\n"
			"1:b .\n"
			"2:\n" : : "r"(&n));
	}
	void handler1(int sig) { }
	void handler2(int sig) { raise(1); }
	void handler3(int sig) { exit(0); }
	main()
	{
		struct sigaction s = {.sa_handler = handler2};
		struct itimerval t1 = { .it_value = {1} };
		struct itimerval t2 = { .it_value = {2} };
		signal(1, handler1);
		sigemptyset(&s.sa_mask);
		sigaddset(&s.sa_mask, 1);
		sigaction(SIGALRM, &s, NULL);
		signal(SIGVTALRM, handler3);
		setitimer(ITIMER_REAL, &t1, NULL);
		setitimer(ITIMER_VIRTUAL, &t2, NULL);
		f(-513); /* -ERESTARTNOINTR */
		write(1, "buggered\n", 9);
		return 1;
	}
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: stable@kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
											
										 
											2010-09-17 14:34:39 +01:00
										 |  |  | 		mov	why, #0		@ prevent syscall restart handling
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		b	sys_rt_sigreturn | 
					
						
							| 
									
										
										
										
											2008-08-28 11:22:32 +01:00
										 |  |  | ENDPROC(sys_rt_sigreturn_wrapper) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-14 16:35:03 +00:00
										 |  |  | sys_statfs64_wrapper: | 
					
						
							|  |  |  | 		teq	r1, #88 | 
					
						
							|  |  |  | 		moveq	r1, #84 | 
					
						
							|  |  |  | 		b	sys_statfs64 | 
					
						
							| 
									
										
										
										
											2008-08-28 11:22:32 +01:00
										 |  |  | ENDPROC(sys_statfs64_wrapper) | 
					
						
							| 
									
										
										
										
											2006-01-14 16:35:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | sys_fstatfs64_wrapper: | 
					
						
							|  |  |  | 		teq	r1, #88 | 
					
						
							|  |  |  | 		moveq	r1, #84 | 
					
						
							|  |  |  | 		b	sys_fstatfs64 | 
					
						
							| 
									
										
										
										
											2008-08-28 11:22:32 +01:00
										 |  |  | ENDPROC(sys_fstatfs64_wrapper) | 
					
						
							| 
									
										
										
										
											2006-01-14 16:35:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /* | 
					
						
							|  |  |  |  * Note: off_4k (r5) is always units of 4K.  If we can't do the requested | 
					
						
							|  |  |  |  * offset, we return EINVAL. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | sys_mmap2: | 
					
						
							|  |  |  | #if PAGE_SHIFT > 12 | 
					
						
							|  |  |  | 		tst	r5, #PGOFF_MASK | 
					
						
							|  |  |  | 		moveq	r5, r5, lsr #PAGE_SHIFT - 12 | 
					
						
							|  |  |  | 		streq	r5, [sp, #4] | 
					
						
							| 
									
										
										
										
											2009-11-30 17:37:04 -05:00
										 |  |  | 		beq	sys_mmap_pgoff | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		mov	r0, #-EINVAL | 
					
						
							| 
									
										
										
										
											2014-06-30 16:29:12 +01:00
										 |  |  | 		ret	lr | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #else | 
					
						
							|  |  |  | 		str	r5, [sp, #4] | 
					
						
							| 
									
										
										
										
											2009-11-30 17:37:04 -05:00
										 |  |  | 		b	sys_mmap_pgoff | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #endif | 
					
						
							| 
									
										
										
										
											2008-08-28 11:22:32 +01:00
										 |  |  | ENDPROC(sys_mmap2) | 
					
						
							| 
									
										
										
										
											2006-01-14 16:35:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_OABI_COMPAT | 
					
						
							| 
									
										
										
										
											2006-01-14 16:36:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-14 16:35:31 +00:00
										 |  |  | /* | 
					
						
							|  |  |  |  * These are syscalls with argument register differences | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | sys_oabi_pread64: | 
					
						
							|  |  |  | 		stmia	sp, {r3, r4} | 
					
						
							|  |  |  | 		b	sys_pread64 | 
					
						
							| 
									
										
										
										
											2008-08-28 11:22:32 +01:00
										 |  |  | ENDPROC(sys_oabi_pread64) | 
					
						
							| 
									
										
										
										
											2006-01-14 16:35:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | sys_oabi_pwrite64: | 
					
						
							|  |  |  | 		stmia	sp, {r3, r4} | 
					
						
							|  |  |  | 		b	sys_pwrite64 | 
					
						
							| 
									
										
										
										
											2008-08-28 11:22:32 +01:00
										 |  |  | ENDPROC(sys_oabi_pwrite64) | 
					
						
							| 
									
										
										
										
											2006-01-14 16:35:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | sys_oabi_truncate64: | 
					
						
							|  |  |  | 		mov	r3, r2 | 
					
						
							|  |  |  | 		mov	r2, r1 | 
					
						
							|  |  |  | 		b	sys_truncate64 | 
					
						
							| 
									
										
										
										
											2008-08-28 11:22:32 +01:00
										 |  |  | ENDPROC(sys_oabi_truncate64) | 
					
						
							| 
									
										
										
										
											2006-01-14 16:35:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | sys_oabi_ftruncate64: | 
					
						
							|  |  |  | 		mov	r3, r2 | 
					
						
							|  |  |  | 		mov	r2, r1 | 
					
						
							|  |  |  | 		b	sys_ftruncate64 | 
					
						
							| 
									
										
										
										
											2008-08-28 11:22:32 +01:00
										 |  |  | ENDPROC(sys_oabi_ftruncate64) | 
					
						
							| 
									
										
										
										
											2006-01-14 16:35:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | sys_oabi_readahead: | 
					
						
							|  |  |  | 		str	r3, [sp] | 
					
						
							|  |  |  | 		mov	r3, r2 | 
					
						
							|  |  |  | 		mov	r2, r1 | 
					
						
							|  |  |  | 		b	sys_readahead | 
					
						
							| 
									
										
										
										
											2008-08-28 11:22:32 +01:00
										 |  |  | ENDPROC(sys_oabi_readahead) | 
					
						
							| 
									
										
										
										
											2006-01-14 16:35:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-14 16:36:12 +00:00
										 |  |  | /* | 
					
						
							|  |  |  |  * Let's declare a second syscall table for old ABI binaries | 
					
						
							|  |  |  |  * using the compatibility syscall entries. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #define ABI(native, compat) compat | 
					
						
							|  |  |  | #define OBSOLETE(syscall) syscall | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.type	sys_oabi_call_table, #object | 
					
						
							|  |  |  | ENTRY(sys_oabi_call_table) | 
					
						
							|  |  |  | #include "calls.S" | 
					
						
							|  |  |  | #undef ABI | 
					
						
							|  |  |  | #undef OBSOLETE | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-14 16:35:31 +00:00
										 |  |  | #endif | 
					
						
							|  |  |  | 
 |