blob: 109f4f10d314db798fe1e2089f4515cca87523e4 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001#include <linux/config.h> /* for CONFIG_ARCH_xxxx */
2#include <linux/linkage.h>
3
4#include <asm/assembler.h>
5#include <asm/constants.h>
6#include <asm/errno.h>
7#include <asm/hardware.h>
8#include <asm/arch/irqs.h>
9#include <asm/arch/entry-macro.S>
10
11#ifndef MODE_SVC
12#define MODE_SVC 0x13
13#endif
14
15 .macro zero_fp
16#ifdef CONFIG_FRAME_POINTER
17 mov fp, #0
18#endif
19 .endm
20
21 .text
22
23@ Bad Abort numbers
24@ -----------------
25@
26#define BAD_PREFETCH 0
27#define BAD_DATA 1
28#define BAD_ADDREXCPTN 2
29#define BAD_IRQ 3
30#define BAD_UNDEFINSTR 4
31
32#define PT_TRACESYS 0x00000002
33
34@ OS version number used in SWIs
35@ RISC OS is 0
36@ RISC iX is 8
37@
38#define OS_NUMBER 9
39#define ARMSWI_OFFSET 0x000f0000
40
41@
42@ Stack format (ensured by USER_* and SVC_*)
43@
44#define S_FRAME_SIZE 72
45#define S_OLD_R0 68
46#define S_PSR 64
47
48#define S_PC 60
49#define S_LR 56
50#define S_SP 52
51#define S_IP 48
52#define S_FP 44
53#define S_R10 40
54#define S_R9 36
55#define S_R8 32
56#define S_R7 28
57#define S_R6 24
58#define S_R5 20
59#define S_R4 16
60#define S_R3 12
61#define S_R2 8
62#define S_R1 4
63#define S_R0 0
64#define S_OFF 8
65
Linus Torvalds1da177e2005-04-16 15:20:36 -070066#if __LINUX_ARM_ARCH__ >= 6
Russell King1ec42c02005-04-26 15:18:26 +010067 .macro disable_irq
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 cpsid i
69 .endm
70
Russell King1ec42c02005-04-26 15:18:26 +010071 .macro enable_irq
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 cpsie i
73 .endm
74#else
Russell King1ec42c02005-04-26 15:18:26 +010075 .macro disable_irq
76 msr cpsr_c, #PSR_I_BIT | SVC_MODE
Linus Torvalds1da177e2005-04-16 15:20:36 -070077 .endm
78
Russell King1ec42c02005-04-26 15:18:26 +010079 .macro enable_irq
80 msr cpsr_c, #SVC_MODE
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 .endm
82#endif
83
84 .macro save_user_regs
85 sub sp, sp, #S_FRAME_SIZE
86 stmia sp, {r0 - r12} @ Calling r0 - r12
87 add r8, sp, #S_PC
88 stmdb r8, {sp, lr}^ @ Calling sp, lr
89 mrs r8, spsr @ called from non-FIQ mode, so ok.
90 str lr, [sp, #S_PC] @ Save calling PC
91 str r8, [sp, #S_PSR] @ Save CPSR
92 str r0, [sp, #S_OLD_R0] @ Save OLD_R0
93 .endm
94
95 .macro restore_user_regs
96 ldr r1, [sp, #S_PSR] @ Get calling cpsr
97 disable_irq ip @ disable IRQs
98 ldr lr, [sp, #S_PC]! @ Get PC
99 msr spsr_cxsf, r1 @ save in spsr_svc
100 ldmdb sp, {r0 - lr}^ @ Get calling r0 - lr
101 mov r0, r0
102 add sp, sp, #S_FRAME_SIZE - S_PC
103 movs pc, lr @ return & move spsr_svc into cpsr
104 .endm
105
106/*
107 * Must be called with IRQs already disabled.
108 */
109 .macro fast_restore_user_regs
110 ldr r1, [sp, #S_OFF + S_PSR] @ get calling cpsr
111 ldr lr, [sp, #S_OFF + S_PC]! @ get pc
112 msr spsr_cxsf, r1 @ save in spsr_svc
113 ldmdb sp, {r1 - lr}^ @ get calling r1 - lr
114 mov r0, r0
115 add sp, sp, #S_FRAME_SIZE - S_PC
116 movs pc, lr @ return & move spsr_svc into cpsr
117 .endm
118
119/*
120 * Must be called with IRQs already disabled.
121 */
122 .macro slow_restore_user_regs
123 ldr r1, [sp, #S_PSR] @ get calling cpsr
124 ldr lr, [sp, #S_PC]! @ get pc
125 msr spsr_cxsf, r1 @ save in spsr_svc
126 ldmdb sp, {r0 - lr}^ @ get calling r1 - lr
127 mov r0, r0
128 add sp, sp, #S_FRAME_SIZE - S_PC
129 movs pc, lr @ return & move spsr_svc into cpsr
130 .endm
131
132 .macro mask_pc, rd, rm
133 .endm
134
135 .macro get_thread_info, rd
136 mov \rd, sp, lsr #13
137 mov \rd, \rd, lsl #13
138 .endm
139
140 .macro alignment_trap, rbase, rtemp, sym
141#ifdef CONFIG_ALIGNMENT_TRAP
142#define OFF_CR_ALIGNMENT(x) cr_alignment - x
143
144 ldr \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
145 mcr p15, 0, \rtemp, c1, c0
146#endif
147 .endm
148
149
150/*
151 * These are the registers used in the syscall handler, and allow us to
152 * have in theory up to 7 arguments to a function - r0 to r6.
153 *
154 * r7 is reserved for the system call number for thumb mode.
155 *
156 * Note that tbl == why is intentional.
157 *
158 * We must set at least "tsk" and "why" when calling ret_with_reschedule.
159 */
160scno .req r7 @ syscall number
161tbl .req r8 @ syscall table pointer
162why .req r8 @ Linux syscall (!= 0)
163tsk .req r9 @ current thread_info
164
165/*
166 * Get the system call number.
167 */
168 .macro get_scno
169#ifdef CONFIG_ARM_THUMB
170 tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs
171 addne scno, r7, #OS_NUMBER << 20 @ put OS number in
172 ldreq scno, [lr, #-4]
173
174#else
175 mask_pc lr, lr
176 ldr scno, [lr, #-4] @ get SWI instruction
177#endif
178 .endm