]> git.karo-electronics.de Git - karo-tx-linux.git/blob - arch/arm/kernel/entry-header.S
9d4d286d3808520756aded403e7e973ebda65e78
[karo-tx-linux.git] / 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 @ Most of the stack format comes from struct pt_regs, but with
43 @ the addition of 8 bytes for storing syscall args 5 and 6.
44 @
45 #define S_OFF           8
46
47 /* 
48  * The SWI code relies on the fact that R0 is at the bottom of the stack
49  * (due to slow/fast restore user regs).
50  */
51 #if S_R0 != 0
52 #error "Please fix"
53 #endif
54
55 #if __LINUX_ARM_ARCH__ >= 6
56         .macro  disable_irq
57         cpsid   i
58         .endm
59
60         .macro  enable_irq
61         cpsie   i
62         .endm
63 #else
64         .macro  disable_irq
65         msr     cpsr_c, #PSR_I_BIT | SVC_MODE
66         .endm
67
68         .macro  enable_irq
69         msr     cpsr_c, #SVC_MODE
70         .endm
71 #endif
72
73         .macro  save_user_regs
74         sub     sp, sp, #S_FRAME_SIZE
75         stmia   sp, {r0 - r12}                  @ Calling r0 - r12
76         add     r8, sp, #S_PC
77         stmdb   r8, {sp, lr}^                   @ Calling sp, lr
78         mrs     r8, spsr                        @ called from non-FIQ mode, so ok.
79         str     lr, [sp, #S_PC]                 @ Save calling PC
80         str     r8, [sp, #S_PSR]                @ Save CPSR
81         str     r0, [sp, #S_OLD_R0]             @ Save OLD_R0
82         .endm
83
84         .macro  restore_user_regs
85         ldr     r1, [sp, #S_PSR]                @ Get calling cpsr
86         disable_irq ip                          @ disable IRQs
87         ldr     lr, [sp, #S_PC]!                @ Get PC
88         msr     spsr_cxsf, r1                   @ save in spsr_svc
89         ldmdb   sp, {r0 - lr}^                  @ Get calling r0 - lr
90         mov     r0, r0
91         add     sp, sp, #S_FRAME_SIZE - S_PC
92         movs    pc, lr                          @ return & move spsr_svc into cpsr
93         .endm
94
95 /*
96  * Must be called with IRQs already disabled.
97  */
98         .macro  fast_restore_user_regs
99         ldr     r1, [sp, #S_OFF + S_PSR]        @ get calling cpsr
100         ldr     lr, [sp, #S_OFF + S_PC]!        @ get pc
101         msr     spsr_cxsf, r1                   @ save in spsr_svc
102         ldmdb   sp, {r1 - lr}^                  @ get calling r1 - lr
103         mov     r0, r0
104         add     sp, sp, #S_FRAME_SIZE - S_PC
105         movs    pc, lr                          @ return & move spsr_svc into cpsr
106         .endm
107
108 /*
109  * Must be called with IRQs already disabled.
110  */
111         .macro  slow_restore_user_regs
112         ldr     r1, [sp, #S_PSR]                @ get calling cpsr
113         ldr     lr, [sp, #S_PC]!                @ get pc
114         msr     spsr_cxsf, r1                   @ save in spsr_svc
115         ldmdb   sp, {r0 - lr}^                  @ get calling r1 - lr
116         mov     r0, r0
117         add     sp, sp, #S_FRAME_SIZE - S_PC
118         movs    pc, lr                          @ return & move spsr_svc into cpsr
119         .endm
120
121         .macro  mask_pc, rd, rm
122         .endm
123
124         .macro  get_thread_info, rd
125         mov     \rd, sp, lsr #13
126         mov     \rd, \rd, lsl #13
127         .endm
128
129         .macro  alignment_trap, rbase, rtemp, sym
130 #ifdef CONFIG_ALIGNMENT_TRAP
131 #define OFF_CR_ALIGNMENT(x)     cr_alignment - x
132
133         ldr     \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
134         mcr     p15, 0, \rtemp, c1, c0
135 #endif
136         .endm
137
138
139 /*
140  * These are the registers used in the syscall handler, and allow us to
141  * have in theory up to 7 arguments to a function - r0 to r6.
142  *
143  * r7 is reserved for the system call number for thumb mode.
144  *
145  * Note that tbl == why is intentional.
146  *
147  * We must set at least "tsk" and "why" when calling ret_with_reschedule.
148  */
149 scno    .req    r7              @ syscall number
150 tbl     .req    r8              @ syscall table pointer
151 why     .req    r8              @ Linux syscall (!= 0)
152 tsk     .req    r9              @ current thread_info
153
154 /*
155  * Get the system call number.
156  */
157         .macro  get_scno
158 #ifdef CONFIG_ARM_THUMB
159         tst     r8, #PSR_T_BIT          @ this is SPSR from save_user_regs
160         addne   scno, r7, #OS_NUMBER << 20 @ put OS number in
161         ldreq   scno, [lr, #-4]
162
163 #else
164         mask_pc lr, lr
165         ldr     scno, [lr, #-4]         @ get SWI instruction
166 #endif
167         .endm