blob: 9d4d286d3808520756aded403e7e973ebda65e78 [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@
Russell King925c8a12005-04-26 15:18:59 +010042@ 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.
Linus Torvalds1da177e2005-04-16 15:20:36 -070044@
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#define S_OFF 8
46
Russell King925c8a12005-04-26 15:18:59 +010047/*
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
Linus Torvalds1da177e2005-04-16 15:20:36 -070055#if __LINUX_ARM_ARCH__ >= 6
Russell King1ec42c02005-04-26 15:18:26 +010056 .macro disable_irq
Linus Torvalds1da177e2005-04-16 15:20:36 -070057 cpsid i
58 .endm
59
Russell King1ec42c02005-04-26 15:18:26 +010060 .macro enable_irq
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 cpsie i
62 .endm
63#else
Russell King1ec42c02005-04-26 15:18:26 +010064 .macro disable_irq
65 msr cpsr_c, #PSR_I_BIT | SVC_MODE
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 .endm
67
Russell King1ec42c02005-04-26 15:18:26 +010068 .macro enable_irq
69 msr cpsr_c, #SVC_MODE
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 .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 */
149scno .req r7 @ syscall number
150tbl .req r8 @ syscall table pointer
151why .req r8 @ Linux syscall (!= 0)
152tsk .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