1 #include <linux/config.h> /* for CONFIG_ARCH_xxxx */
2 #include <linux/linkage.h>
4 #include <asm/assembler.h>
5 #include <asm/constants.h>
7 #include <asm/hardware.h>
8 #include <asm/arch/irqs.h>
9 #include <asm/arch/entry-macro.S>
16 #ifdef CONFIG_FRAME_POINTER
26 #define BAD_PREFETCH 0
28 #define BAD_ADDREXCPTN 2
30 #define BAD_UNDEFINSTR 4
32 #define PT_TRACESYS 0x00000002
34 @ OS version number used in SWIs
39 #define ARMSWI_OFFSET 0x000f0000
42 @ Most of the stack format comes from struct pt_regs, but with
43 @ the addition of 8 bytes for storing syscall args 5 and 6.
48 * The SWI code relies on the fact that R0 is at the bottom of the stack
49 * (due to slow/fast restore user regs).
55 #if __LINUX_ARM_ARCH__ >= 6
65 msr cpsr_c, #PSR_I_BIT | SVC_MODE
74 sub sp, sp, #S_FRAME_SIZE
75 stmia sp, {r0 - r12} @ Calling r0 - r12
77 stmdb r8, {sp, lr}^ @ Calling sp, lr
78 mrs r8, spsr @ called from non-FIQ mode, so ok.
79 str lr, [sp, #S_PC] @ Save calling PC
80 str r8, [sp, #S_PSR] @ Save CPSR
81 str r0, [sp, #S_OLD_R0] @ Save OLD_R0
84 .macro restore_user_regs
85 ldr r1, [sp, #S_PSR] @ Get calling cpsr
86 disable_irq ip @ disable IRQs
87 ldr lr, [sp, #S_PC]! @ Get PC
88 msr spsr_cxsf, r1 @ save in spsr_svc
89 ldmdb sp, {r0 - lr}^ @ Get calling r0 - lr
91 add sp, sp, #S_FRAME_SIZE - S_PC
92 movs pc, lr @ return & move spsr_svc into cpsr
96 * Must be called with IRQs already disabled.
98 .macro fast_restore_user_regs
99 ldr r1, [sp, #S_OFF + S_PSR] @ get calling cpsr
100 ldr lr, [sp, #S_OFF + S_PC]! @ get pc
101 msr spsr_cxsf, r1 @ save in spsr_svc
102 ldmdb sp, {r1 - lr}^ @ get calling r1 - lr
104 add sp, sp, #S_FRAME_SIZE - S_PC
105 movs pc, lr @ return & move spsr_svc into cpsr
109 * Must be called with IRQs already disabled.
111 .macro slow_restore_user_regs
112 ldr r1, [sp, #S_PSR] @ get calling cpsr
113 ldr lr, [sp, #S_PC]! @ get pc
114 msr spsr_cxsf, r1 @ save in spsr_svc
115 ldmdb sp, {r0 - lr}^ @ get calling r1 - lr
117 add sp, sp, #S_FRAME_SIZE - S_PC
118 movs pc, lr @ return & move spsr_svc into cpsr
121 .macro mask_pc, rd, rm
124 .macro get_thread_info, rd
126 mov \rd, \rd, lsl #13
129 .macro alignment_trap, rbase, rtemp, sym
130 #ifdef CONFIG_ALIGNMENT_TRAP
131 #define OFF_CR_ALIGNMENT(x) cr_alignment - x
133 ldr \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
134 mcr p15, 0, \rtemp, c1, c0
140 * These are the registers used in the syscall handler, and allow us to
141 * have in theory up to 7 arguments to a function - r0 to r6.
143 * r7 is reserved for the system call number for thumb mode.
145 * Note that tbl == why is intentional.
147 * We must set at least "tsk" and "why" when calling ret_with_reschedule.
149 scno .req r7 @ syscall number
150 tbl .req r8 @ syscall table pointer
151 why .req r8 @ Linux syscall (!= 0)
152 tsk .req r9 @ current thread_info
155 * Get the system call number.
158 #ifdef CONFIG_ARM_THUMB
159 tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs
160 addne scno, r7, #OS_NUMBER << 20 @ put OS number in
161 ldreq scno, [lr, #-4]
165 ldr scno, [lr, #-4] @ get SWI instruction