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/proc-fns.h>
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 @ Stack format (ensured by USER_* and SVC_*)
45 #define S_FRAME_SIZE 72
49 #define S_FRAME_SIZE 68
73 .macro set_cpsr_c, reg, mode
83 .macro disable_irq, temp
84 set_cpsr_c \temp, #I_BIT | MODE_SVC
87 .macro enable_irq, temp
88 set_cpsr_c \temp, #MODE_SVC
92 sub sp, sp, #S_FRAME_SIZE
93 stmia sp, {r0 - r12} @ Calling r0 - r12
95 stmdb r8, {sp, lr}^ @ Calling sp, lr
96 mrs r8, spsr @ called from non-FIQ mode, so ok.
97 str lr, [sp, #S_PC] @ Save calling PC
98 str r8, [sp, #S_PSR] @ Save CPSR
99 str r0, [sp, #S_OLD_R0] @ Save OLD_R0
103 * Must be called with IRQs already disabled.
105 .macro restore_user_regs
106 ldr r1, [sp, #S_PSR] @ Get calling cpsr
107 ldr lr, [sp, #S_PC]! @ Get PC
108 msr spsr, r1 @ save in spsr_svc
109 ldmdb sp, {r0 - lr}^ @ Get calling r0 - lr
111 add sp, sp, #S_FRAME_SIZE - S_PC
112 movs pc, lr @ return & move spsr_svc into cpsr
116 * Must be called with IRQs already disabled.
118 .macro fast_restore_user_regs
119 ldr r1, [sp, #S_OFF + S_PSR] @ get calling cpsr
120 ldr lr, [sp, #S_OFF + S_PC]! @ get pc
121 msr spsr, r1 @ save in spsr_svc
122 ldmdb sp, {r1 - lr}^ @ get calling r1 - lr
124 add sp, sp, #S_FRAME_SIZE - S_PC
125 movs pc, lr @ return & move spsr_svc into cpsr
128 .macro mask_pc, rd, rm
131 .macro get_current_task, rd
133 mov \rd, \rd, lsl #13
137 * Like adr, but force SVC mode (if required)
139 .macro adrsvc, cond, reg, label
140 adr\cond \reg, \label
143 .macro alignment_trap, rbase, rtemp, sym
144 #ifdef CONFIG_ALIGNMENT_TRAP
145 #define OFF_CR_ALIGNMENT(x) cr_alignment - x
147 ldr \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
148 mcr p15, 0, \rtemp, c1, c0
153 .macro save_user_regs
154 sub sp, sp, #S_FRAME_SIZE
155 str r0, [sp, #S_OLD_R0]
161 .macro restore_user_regs
165 add sp, sp, #S_FRAME_SIZE
169 .macro fast_restore_user_regs
170 add sp, sp, #S_OFF + S_PC
173 ldr lr, [sp], #S_FRAME_SIZE - S_PC
177 .macro mask_pc, rd, rm
178 bic \rd, \rm, #PCMASK
181 .macro disable_irq, temp
185 .macro enable_irq, temp
189 .macro initialise_traps_extra
192 .macro get_current_task, rd
194 mov \rd, \rd, lsl #13
198 * Like adr, but force SVC mode (if required)
200 .macro adrsvc, cond, reg, label
201 adr\cond \reg, \label
202 orr\cond \reg, \reg, #0x08000003
209 * These are the registers used in the syscall handler, and allow us to
210 * have in theory up to 7 arguments to a function - r0 to r6.
212 * r7 is reserved for the system call number for thumb mode.
214 * Note that tbl == why is intentional.
216 * We must set at least "tsk" and "why" when calling ret_with_reschedule.
218 scno .req r7 @ syscall number
219 tbl .req r8 @ syscall table pointer
220 why .req r8 @ Linux syscall (!= 0)
221 tsk .req r9 @ current task
224 * Get the system call number.
227 #ifdef CONFIG_ARM_THUMB
228 tst r8, #T_BIT @ this is SPSR from save_user_regs
229 addne scno, r7, #OS_NUMBER << 20 @ put OS number in
230 ldreq scno, [lr, #-4]
234 ldr scno, [lr, #-4] @ get SWI instruction