Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | #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 | ||
66 | .macro set_cpsr_c, reg, mode | |
67 | msr cpsr_c, \mode | |
68 | .endm | |
69 | ||
70 | #if __LINUX_ARM_ARCH__ >= 6 | |
71 | .macro disable_irq, temp | |
72 | cpsid i | |
73 | .endm | |
74 | ||
75 | .macro enable_irq, temp | |
76 | cpsie i | |
77 | .endm | |
78 | #else | |
79 | .macro disable_irq, temp | |
80 | set_cpsr_c \temp, #PSR_I_BIT | MODE_SVC | |
81 | .endm | |
82 | ||
83 | .macro enable_irq, temp | |
84 | set_cpsr_c \temp, #MODE_SVC | |
85 | .endm | |
86 | #endif | |
87 | ||
88 | .macro save_user_regs | |
89 | sub sp, sp, #S_FRAME_SIZE | |
90 | stmia sp, {r0 - r12} @ Calling r0 - r12 | |
91 | add r8, sp, #S_PC | |
92 | stmdb r8, {sp, lr}^ @ Calling sp, lr | |
93 | mrs r8, spsr @ called from non-FIQ mode, so ok. | |
94 | str lr, [sp, #S_PC] @ Save calling PC | |
95 | str r8, [sp, #S_PSR] @ Save CPSR | |
96 | str r0, [sp, #S_OLD_R0] @ Save OLD_R0 | |
97 | .endm | |
98 | ||
99 | .macro restore_user_regs | |
100 | ldr r1, [sp, #S_PSR] @ Get calling cpsr | |
101 | disable_irq ip @ disable IRQs | |
102 | ldr lr, [sp, #S_PC]! @ Get PC | |
103 | msr spsr_cxsf, r1 @ save in spsr_svc | |
104 | ldmdb sp, {r0 - lr}^ @ Get calling r0 - lr | |
105 | mov r0, r0 | |
106 | add sp, sp, #S_FRAME_SIZE - S_PC | |
107 | movs pc, lr @ return & move spsr_svc into cpsr | |
108 | .endm | |
109 | ||
110 | /* | |
111 | * Must be called with IRQs already disabled. | |
112 | */ | |
113 | .macro fast_restore_user_regs | |
114 | ldr r1, [sp, #S_OFF + S_PSR] @ get calling cpsr | |
115 | ldr lr, [sp, #S_OFF + S_PC]! @ get pc | |
116 | msr spsr_cxsf, r1 @ save in spsr_svc | |
117 | ldmdb sp, {r1 - lr}^ @ get calling r1 - lr | |
118 | mov r0, r0 | |
119 | add sp, sp, #S_FRAME_SIZE - S_PC | |
120 | movs pc, lr @ return & move spsr_svc into cpsr | |
121 | .endm | |
122 | ||
123 | /* | |
124 | * Must be called with IRQs already disabled. | |
125 | */ | |
126 | .macro slow_restore_user_regs | |
127 | ldr r1, [sp, #S_PSR] @ get calling cpsr | |
128 | ldr lr, [sp, #S_PC]! @ get pc | |
129 | msr spsr_cxsf, r1 @ save in spsr_svc | |
130 | ldmdb sp, {r0 - lr}^ @ get calling r1 - lr | |
131 | mov r0, r0 | |
132 | add sp, sp, #S_FRAME_SIZE - S_PC | |
133 | movs pc, lr @ return & move spsr_svc into cpsr | |
134 | .endm | |
135 | ||
136 | .macro mask_pc, rd, rm | |
137 | .endm | |
138 | ||
139 | .macro get_thread_info, rd | |
140 | mov \rd, sp, lsr #13 | |
141 | mov \rd, \rd, lsl #13 | |
142 | .endm | |
143 | ||
144 | .macro alignment_trap, rbase, rtemp, sym | |
145 | #ifdef CONFIG_ALIGNMENT_TRAP | |
146 | #define OFF_CR_ALIGNMENT(x) cr_alignment - x | |
147 | ||
148 | ldr \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)] | |
149 | mcr p15, 0, \rtemp, c1, c0 | |
150 | #endif | |
151 | .endm | |
152 | ||
153 | ||
154 | /* | |
155 | * These are the registers used in the syscall handler, and allow us to | |
156 | * have in theory up to 7 arguments to a function - r0 to r6. | |
157 | * | |
158 | * r7 is reserved for the system call number for thumb mode. | |
159 | * | |
160 | * Note that tbl == why is intentional. | |
161 | * | |
162 | * We must set at least "tsk" and "why" when calling ret_with_reschedule. | |
163 | */ | |
164 | scno .req r7 @ syscall number | |
165 | tbl .req r8 @ syscall table pointer | |
166 | why .req r8 @ Linux syscall (!= 0) | |
167 | tsk .req r9 @ current thread_info | |
168 | ||
169 | /* | |
170 | * Get the system call number. | |
171 | */ | |
172 | .macro get_scno | |
173 | #ifdef CONFIG_ARM_THUMB | |
174 | tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs | |
175 | addne scno, r7, #OS_NUMBER << 20 @ put OS number in | |
176 | ldreq scno, [lr, #-4] | |
177 | ||
178 | #else | |
179 | mask_pc lr, lr | |
180 | ldr scno, [lr, #-4] @ get SWI instruction | |
181 | #endif | |
182 | .endm |