Linux-2.6.12-rc2
[linux-2.6] / arch / arm / kernel / entry-header.S
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