1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
|
/*============================================================================
* All exits to user mode from the kernel go through this code.
*/
#include <linux/config.h>
.globl ret_from_sys_call
ret_from_exception:
adr r0, 1f
ldmia r0, {r0, r1}
ldr r0, [r0]
ldr r1, [r1]
tst r0, r1
blne SYMBOL_NAME(do_bottom_half)
ret_from_intr: ldr r0, [sp, #S_PSR]
tst r0, #3
beq ret_with_reschedule
b ret_from_all
ret_signal: mov r1, sp
adrsvc al, lr, ret_from_all
b SYMBOL_NAME(do_signal)
2: bl SYMBOL_NAME(schedule)
ret_from_sys_call:
adr r0, 1f
ldmia r0, {r0, r1}
ldr r0, [r0]
ldr r1, [r1]
tst r0, r1
adrsvc ne, lr, ret_from_intr
bne SYMBOL_NAME(do_bottom_half)
ret_with_reschedule:
get_current_task r1
ldr r0, [r1, #TSK_NEED_RESCHED]
teq r0, #0
bne 2b
ldr r1, [r1, #TSK_SIGPENDING]
teq r1, #0
bne ret_signal
ret_from_all: restore_user_regs
1: .word SYMBOL_NAME(bh_mask)
.word SYMBOL_NAME(bh_active)
/*=============================================================================
* SWI handler
*-----------------------------------------------------------------------------
*
* We now handle sys-call tracing, and the errno in the task structure.
* Still have a problem with >4 arguments for functions. Theres only
* a couple of functions in the code that have 5 arguments, so Im not
* too worried.
*/
#include "calls.S"
vector_swi: save_user_regs
mov fp, #0
mask_pc lr, lr
ldr r6, [lr, #-4]! @ get SWI instruction
arm700_bug_check r6, r7
enable_irqs r7
bic r6, r6, #0xff000000 @ mask off SWI op-code
eor r6, r6, #OS_NUMBER<<20 @ check OS number
cmp r6, #NR_syscalls @ check upper syscall limit
bcs 2f
get_current_task r5
ldr ip, [r5, #TSK_FLAGS] @ check for syscall tracing
tst ip, #PF_TRACESYS
bne 1f
adr ip, SYMBOL_NAME(sys_call_table)
str r4, [sp, #-4]! @ new style: (r0 = arg1, r5 = arg5)
mov lr, pc
ldr pc, [ip, r6, lsl #2] @ call sys routine
add sp, sp, #4
str r0, [sp, #S_R0] @ returned r0
b ret_from_sys_call
1: ldr r7, [sp, #S_IP] @ save old IP
mov r0, #0
str r0, [sp, #S_IP] @ trace entry [IP = 0]
bl SYMBOL_NAME(syscall_trace)
str r7, [sp, #S_IP]
ldmia sp, {r0 - r3} @ have to reload r0 - r3
adr ip, SYMBOL_NAME(sys_call_table)
str r4, [sp, #-4]! @ new style: (r0 = arg1, r5 = arg5)
mov lr, pc
ldr pc, [ip, r6, lsl #2] @ call sys routine
add sp, sp, #4
str r0, [sp, #S_R0] @ returned r0
mov r0, #1
str r0, [sp, #S_IP] @ trace exit [IP = 1]
bl SYMBOL_NAME(syscall_trace)
str r7, [sp, #S_IP]
b ret_from_sys_call
2: tst r6, #0x00f00000 @ is it a Unix SWI?
bne 3f
cmp r6, #(KSWI_SYS_BASE - KSWI_BASE)
bcc 4f @ not private func
bic r0, r6, #0x000f0000
mov r1, sp
bl SYMBOL_NAME(arm_syscall)
b ret_from_sys_call
3: eor r0, r6, #OS_NUMBER<<20 @ Put OS number back
mov r1, sp
bl SYMBOL_NAME(deferred)
ldmfd sp, {r0 - r3}
b ret_from_sys_call
4: bl SYMBOL_NAME(sys_ni_syscall)
str r0, [sp, #0] @ returned r0
b ret_from_sys_call
@ r0 = syscall number
@ r1 = syscall r0
@ r5 = syscall r4
@ ip = syscall table
SYMBOL_NAME(sys_syscall):
mov r6, r0
eor r6, r6, #OS_NUMBER << 20
cmp r6, #NR_syscalls @ check range
movgt r0, #-ENOSYS
movgt pc, lr
add sp, sp, #4 @ take of the save of our r4
ldmib sp, {r0 - r4} @ get our args
str r4, [sp, #-4]! @ Put our arg on the stack
ldr pc, [ip, r6, lsl #2]
ENTRY(sys_call_table)
#include "calls.S"
/*============================================================================
* Special system call wrappers
*/
sys_fork_wrapper:
add r0, sp, #4
b SYMBOL_NAME(sys_fork)
sys_execve_wrapper:
add r3, sp, #4
b SYMBOL_NAME(sys_execve)
sys_mount_wrapper:
mov r6, lr
add r5, sp, #4
str r5, [sp]
str r4, [sp, #-4]!
bl SYMBOL_NAME(sys_compat_mount)
add sp, sp, #4
RETINSTR(mov,pc,r6)
sys_clone_wapper:
add r2, sp, #4
b SYMBOL_NAME(sys_clone)
sys_llseek_wrapper:
mov r6, lr
add r5, sp, #4
str r5, [sp]
str r4, [sp, #-4]!
bl SYMBOL_NAME(sys_compat_llseek)
add sp, sp, #4
RETINSTR(mov,pc,r6)
sys_sigsuspend_wrapper:
add r3, sp, #4
b SYMBOL_NAME(sys_sigsuspend)
sys_rt_sigsuspend_wrapper:
add r2, sp, #4
b SYMBOL_NAME(sys_rt_sigsuspend)
sys_sigreturn_wrapper:
add r0, sp, #4
b SYMBOL_NAME(sys_sigreturn)
sys_rt_sigreturn_wrapper:
add r0, sp, #4
b SYMBOL_NAME(sys_rt_sigreturn)
sys_sigaltstack_wrapper:
ldr r2, [sp, #4 + S_SP]
b do_sigaltstack
/*
*=============================================================================
* Low-level interface code
*-----------------------------------------------------------------------------
* Trap initialisation
*-----------------------------------------------------------------------------
*
* Note - FIQ code has changed. The default is a couple of words in 0x1c, 0x20
* that call _unexp_fiq. Nowever, we now copy the FIQ routine to 0x1c (removes
* some excess cycles).
*
* What we need to put into 0-0x1c are ldrs to branch to 0xC0000000
* (the kernel).
* 0x1c onwards is reserved for FIQ, so I think that I will allocate 0xe0 onwards for
* the actual address to jump to.
*/
.section ".text.init",#alloc,#execinstr
#if defined(CONFIG_CPU_32)
/*
* these go into 0x00
*/
.Lbranches: swi SYS_ERROR0
ldr pc, .Lbranches + 0xe4
ldr pc, .Lbranches + 0xe8
ldr pc, .Lbranches + 0xec
ldr pc, .Lbranches + 0xf0
ldr pc, .Lbranches + 0xf4
ldr pc, .Lbranches + 0xf8
ldr pc, .Lbranches + 0xfc
/*
* this is put into 0xe4 and above
*/
.Ljump_addresses:
.word vector_undefinstr @ 0xe4
.word vector_swi @ 0xe8
.word vector_prefetch @ 0xec
.word vector_data @ 0xf0
.word vector_addrexcptn @ 0xf4
.word vector_IRQ @ 0xf8
.word _unexp_fiq @ 0xfc
/*
* initialise the trap system
*/
ENTRY(trap_init)
stmfd sp!, {r4 - r7, lr}
initialise_traps_extra
mov r0, #0xe4
adr r1, .Ljump_addresses
ldmia r1, {r1 - r7}
stmia r0, {r1 - r7}
mov r0, #0
adr r1, .Lbranches
ldmia r1, {r1 - r7}
stmia r0, {r1 - r7}
LOADREGS(fd, sp!, {r4 - r7, pc})
#elif defined(CONFIG_CPU_26)
.Ljump_addresses:
swi SYS_ERROR0
.word vector_undefinstr - 12
.word vector_swi - 16
.word vector_prefetch - 20
.word vector_data - 24
.word vector_addrexcptn - 28
.word vector_IRQ - 32
.word _unexp_fiq - 36
b . + 8
/*
* initialise the trap system
*/
ENTRY(trap_init)
stmfd sp!, {r4 - r7, lr}
adr r1, .Ljump_addresses
ldmia r1, {r1 - r7, ip, lr}
orr r2, lr, r2, lsr #2
orr r3, lr, r3, lsr #2
orr r4, lr, r4, lsr #2
orr r5, lr, r5, lsr #2
orr r6, lr, r6, lsr #2
orr r7, lr, r7, lsr #2
orr ip, lr, ip, lsr #2
mov r0, #0
stmia r0, {r1 - r7, ip}
ldmfd sp!, {r4 - r7, pc}^
#endif
.previous
/*============================================================================
* FP support
*/
.data
ENTRY(fp_enter)
.word fpundefinstr
|