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>
15 #ifdef CONFIG_FRAME_POINTER
25 #define BAD_PREFETCH 0
27 #define BAD_ADDREXCPTN 2
29 #define BAD_UNDEFINSTR 4
31 #define PT_TRACESYS 0x00000002
33 @ OS version number used in SWIs
38 #define ARMSWI_OFFSET 0x000f0000
41 @ Stack format (ensured by USER_* and SVC_*)
43 #define S_FRAME_SIZE 72
65 .macro set_cpsr_c, reg, mode
69 #if __LINUX_ARM_ARCH__ >= 6
70 .macro disable_irq, temp
74 .macro enable_irq, temp
78 .macro disable_irq, temp
79 set_cpsr_c \temp, #PSR_I_BIT | MODE_SVC
82 .macro enable_irq, temp
83 set_cpsr_c \temp, #MODE_SVC
88 sub sp, sp, #S_FRAME_SIZE
89 stmia sp, {r0 - r12} @ Calling r0 - r12
91 stmdb r8, {sp, lr}^ @ Calling sp, lr
92 mrs r8, spsr @ called from non-FIQ mode, so ok.
93 str lr, [sp, #S_PC] @ Save calling PC
94 str r8, [sp, #S_PSR] @ Save CPSR
95 str r0, [sp, #S_OLD_R0] @ Save OLD_R0
98 .macro restore_user_regs
99 ldr r1, [sp, #S_PSR] @ Get calling cpsr
100 disable_irq ip @ disable IRQs
101 ldr lr, [sp, #S_PC]! @ Get PC
102 msr spsr, r1 @ save in spsr_svc
103 ldmdb sp, {r0 - lr}^ @ Get calling r0 - lr
105 add sp, sp, #S_FRAME_SIZE - S_PC
106 movs pc, lr @ return & move spsr_svc into cpsr
110 * Must be called with IRQs already disabled.
112 .macro fast_restore_user_regs
113 ldr r1, [sp, #S_OFF + S_PSR] @ get calling cpsr
114 ldr lr, [sp, #S_OFF + S_PC]! @ get pc
115 msr spsr, r1 @ save in spsr_svc
116 ldmdb sp, {r1 - lr}^ @ get calling r1 - lr
118 add sp, sp, #S_FRAME_SIZE - S_PC
119 movs pc, lr @ return & move spsr_svc into cpsr
123 * Must be called with IRQs already disabled.
125 .macro slow_restore_user_regs
126 ldr r1, [sp, #S_PSR] @ get calling cpsr
127 ldr lr, [sp, #S_PC]! @ get pc
128 msr spsr, r1 @ save in spsr_svc
129 ldmdb sp, {r0 - lr}^ @ get calling r1 - lr
131 add sp, sp, #S_FRAME_SIZE - S_PC
132 movs pc, lr @ return & move spsr_svc into cpsr
135 .macro mask_pc, rd, rm
138 .macro get_thread_info, rd
140 mov \rd, \rd, lsl #13
144 * Like adr, but force SVC mode (if required)
146 .macro adrsvc, cond, reg, label
147 adr\cond \reg, \label
150 .macro alignment_trap, rbase, rtemp, sym
151 #ifdef CONFIG_ALIGNMENT_TRAP
152 #define OFF_CR_ALIGNMENT(x) cr_alignment - x
154 ldr \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
155 mcr p15, 0, \rtemp, c1, c0
161 * These are the registers used in the syscall handler, and allow us to
162 * have in theory up to 7 arguments to a function - r0 to r6.
164 * r7 is reserved for the system call number for thumb mode.
166 * Note that tbl == why is intentional.
168 * We must set at least "tsk" and "why" when calling ret_with_reschedule.
170 scno .req r7 @ syscall number
171 tbl .req r8 @ syscall table pointer
172 why .req r8 @ Linux syscall (!= 0)
173 tsk .req r9 @ current thread_info
176 * Get the system call number.
179 #ifdef CONFIG_ARM_THUMB
180 tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs
181 addne scno, r7, #OS_NUMBER << 20 @ put OS number in
182 ldreq scno, [lr, #-4]
186 ldr scno, [lr, #-4] @ get SWI instruction