blob: b7d54a4f98f42d35355f3460c193e99656e99355 [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 .macro zero_fp
12#ifdef CONFIG_FRAME_POINTER
13 mov fp, #0
14#endif
15 .endm
16
17 .text
18
19@ Bad Abort numbers
20@ -----------------
21@
22#define BAD_PREFETCH 0
23#define BAD_DATA 1
24#define BAD_ADDREXCPTN 2
25#define BAD_IRQ 3
26#define BAD_UNDEFINSTR 4
27
Linus Torvalds1da177e2005-04-16 15:20:36 -070028@
Russell King925c8a12005-04-26 15:18:59 +010029@ Most of the stack format comes from struct pt_regs, but with
30@ the addition of 8 bytes for storing syscall args 5 and 6.
Linus Torvalds1da177e2005-04-16 15:20:36 -070031@
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#define S_OFF 8
33
Russell King925c8a12005-04-26 15:18:59 +010034/*
35 * The SWI code relies on the fact that R0 is at the bottom of the stack
36 * (due to slow/fast restore user regs).
37 */
38#if S_R0 != 0
39#error "Please fix"
40#endif
41
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#if __LINUX_ARM_ARCH__ >= 6
Russell King1ec42c02005-04-26 15:18:26 +010043 .macro disable_irq
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 cpsid i
45 .endm
46
Russell King1ec42c02005-04-26 15:18:26 +010047 .macro enable_irq
Linus Torvalds1da177e2005-04-16 15:20:36 -070048 cpsie i
49 .endm
50#else
Russell King1ec42c02005-04-26 15:18:26 +010051 .macro disable_irq
52 msr cpsr_c, #PSR_I_BIT | SVC_MODE
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 .endm
54
Russell King1ec42c02005-04-26 15:18:26 +010055 .macro enable_irq
56 msr cpsr_c, #SVC_MODE
Linus Torvalds1da177e2005-04-16 15:20:36 -070057 .endm
58#endif
59
60 .macro save_user_regs
61 sub sp, sp, #S_FRAME_SIZE
62 stmia sp, {r0 - r12} @ Calling r0 - r12
63 add r8, sp, #S_PC
64 stmdb r8, {sp, lr}^ @ Calling sp, lr
65 mrs r8, spsr @ called from non-FIQ mode, so ok.
66 str lr, [sp, #S_PC] @ Save calling PC
67 str r8, [sp, #S_PSR] @ Save CPSR
68 str r0, [sp, #S_OLD_R0] @ Save OLD_R0
69 .endm
70
71 .macro restore_user_regs
72 ldr r1, [sp, #S_PSR] @ Get calling cpsr
73 disable_irq ip @ disable IRQs
74 ldr lr, [sp, #S_PC]! @ Get PC
75 msr spsr_cxsf, r1 @ save in spsr_svc
76 ldmdb sp, {r0 - lr}^ @ Get calling r0 - lr
77 mov r0, r0
78 add sp, sp, #S_FRAME_SIZE - S_PC
79 movs pc, lr @ return & move spsr_svc into cpsr
80 .endm
81
82/*
83 * Must be called with IRQs already disabled.
84 */
85 .macro fast_restore_user_regs
86 ldr r1, [sp, #S_OFF + S_PSR] @ get calling cpsr
87 ldr lr, [sp, #S_OFF + S_PC]! @ get pc
88 msr spsr_cxsf, r1 @ save in spsr_svc
89 ldmdb sp, {r1 - lr}^ @ get calling r1 - 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 slow_restore_user_regs
99 ldr r1, [sp, #S_PSR] @ get calling cpsr
100 ldr lr, [sp, #S_PC]! @ get pc
101 msr spsr_cxsf, r1 @ save in spsr_svc
102 ldmdb sp, {r0 - 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 .macro mask_pc, rd, rm
109 .endm
110
111 .macro get_thread_info, rd
112 mov \rd, sp, lsr #13
113 mov \rd, \rd, lsl #13
114 .endm
115
116 .macro alignment_trap, rbase, rtemp, sym
117#ifdef CONFIG_ALIGNMENT_TRAP
118#define OFF_CR_ALIGNMENT(x) cr_alignment - x
119
120 ldr \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
121 mcr p15, 0, \rtemp, c1, c0
122#endif
123 .endm
124
125
126/*
127 * These are the registers used in the syscall handler, and allow us to
128 * have in theory up to 7 arguments to a function - r0 to r6.
129 *
130 * r7 is reserved for the system call number for thumb mode.
131 *
132 * Note that tbl == why is intentional.
133 *
134 * We must set at least "tsk" and "why" when calling ret_with_reschedule.
135 */
136scno .req r7 @ syscall number
137tbl .req r8 @ syscall table pointer
138why .req r8 @ Linux syscall (!= 0)
139tsk .req r9 @ current thread_info