blob: 0eb7fc935e21f3b289892e5f0e4db3d0f4ebce0a [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070034@
Russell King925c8a12005-04-26 15:18:59 +010035@ Most of the stack format comes from struct pt_regs, but with
36@ the addition of 8 bytes for storing syscall args 5 and 6.
Linus Torvalds1da177e2005-04-16 15:20:36 -070037@
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#define S_OFF 8
39
Russell King925c8a12005-04-26 15:18:59 +010040/*
41 * The SWI code relies on the fact that R0 is at the bottom of the stack
42 * (due to slow/fast restore user regs).
43 */
44#if S_R0 != 0
45#error "Please fix"
46#endif
47
Linus Torvalds1da177e2005-04-16 15:20:36 -070048#if __LINUX_ARM_ARCH__ >= 6
Russell King1ec42c02005-04-26 15:18:26 +010049 .macro disable_irq
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 cpsid i
51 .endm
52
Russell King1ec42c02005-04-26 15:18:26 +010053 .macro enable_irq
Linus Torvalds1da177e2005-04-16 15:20:36 -070054 cpsie i
55 .endm
56#else
Russell King1ec42c02005-04-26 15:18:26 +010057 .macro disable_irq
58 msr cpsr_c, #PSR_I_BIT | SVC_MODE
Linus Torvalds1da177e2005-04-16 15:20:36 -070059 .endm
60
Russell King1ec42c02005-04-26 15:18:26 +010061 .macro enable_irq
62 msr cpsr_c, #SVC_MODE
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 .endm
64#endif
65
66 .macro save_user_regs
67 sub sp, sp, #S_FRAME_SIZE
68 stmia sp, {r0 - r12} @ Calling r0 - r12
69 add r8, sp, #S_PC
70 stmdb r8, {sp, lr}^ @ Calling sp, lr
71 mrs r8, spsr @ called from non-FIQ mode, so ok.
72 str lr, [sp, #S_PC] @ Save calling PC
73 str r8, [sp, #S_PSR] @ Save CPSR
74 str r0, [sp, #S_OLD_R0] @ Save OLD_R0
75 .endm
76
77 .macro restore_user_regs
78 ldr r1, [sp, #S_PSR] @ Get calling cpsr
79 disable_irq ip @ disable IRQs
80 ldr lr, [sp, #S_PC]! @ Get PC
81 msr spsr_cxsf, r1 @ save in spsr_svc
82 ldmdb sp, {r0 - lr}^ @ Get calling r0 - lr
83 mov r0, r0
84 add sp, sp, #S_FRAME_SIZE - S_PC
85 movs pc, lr @ return & move spsr_svc into cpsr
86 .endm
87
88/*
89 * Must be called with IRQs already disabled.
90 */
91 .macro fast_restore_user_regs
92 ldr r1, [sp, #S_OFF + S_PSR] @ get calling cpsr
93 ldr lr, [sp, #S_OFF + S_PC]! @ get pc
94 msr spsr_cxsf, r1 @ save in spsr_svc
95 ldmdb sp, {r1 - lr}^ @ get calling r1 - lr
96 mov r0, r0
97 add sp, sp, #S_FRAME_SIZE - S_PC
98 movs pc, lr @ return & move spsr_svc into cpsr
99 .endm
100
101/*
102 * Must be called with IRQs already disabled.
103 */
104 .macro slow_restore_user_regs
105 ldr r1, [sp, #S_PSR] @ get calling cpsr
106 ldr lr, [sp, #S_PC]! @ get pc
107 msr spsr_cxsf, r1 @ save in spsr_svc
108 ldmdb sp, {r0 - lr}^ @ get calling r1 - lr
109 mov r0, r0
110 add sp, sp, #S_FRAME_SIZE - S_PC
111 movs pc, lr @ return & move spsr_svc into cpsr
112 .endm
113
114 .macro mask_pc, rd, rm
115 .endm
116
117 .macro get_thread_info, rd
118 mov \rd, sp, lsr #13
119 mov \rd, \rd, lsl #13
120 .endm
121
122 .macro alignment_trap, rbase, rtemp, sym
123#ifdef CONFIG_ALIGNMENT_TRAP
124#define OFF_CR_ALIGNMENT(x) cr_alignment - x
125
126 ldr \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
127 mcr p15, 0, \rtemp, c1, c0
128#endif
129 .endm
130
131
132/*
133 * These are the registers used in the syscall handler, and allow us to
134 * have in theory up to 7 arguments to a function - r0 to r6.
135 *
136 * r7 is reserved for the system call number for thumb mode.
137 *
138 * Note that tbl == why is intentional.
139 *
140 * We must set at least "tsk" and "why" when calling ret_with_reschedule.
141 */
142scno .req r7 @ syscall number
143tbl .req r8 @ syscall table pointer
144why .req r8 @ Linux syscall (!= 0)
145tsk .req r9 @ current thread_info