Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * arch/alpha/kernel/entry.S | |
3 | * | |
4 | * Kernel entry-points. | |
5 | */ | |
6 | ||
e2d5df93 | 7 | #include <asm/asm-offsets.h> |
1da177e4 LT |
8 | #include <asm/thread_info.h> |
9 | #include <asm/pal.h> | |
10 | #include <asm/errno.h> | |
11 | #include <asm/unistd.h> | |
12 | ||
13 | .text | |
14 | .set noat | |
231b0bed | 15 | .cfi_sections .debug_frame |
1da177e4 LT |
16 | |
17 | /* Stack offsets. */ | |
18 | #define SP_OFF 184 | |
19 | #define SWITCH_STACK_SIZE 320 | |
20 | ||
231b0bed RH |
21 | .macro CFI_START_OSF_FRAME func |
22 | .align 4 | |
23 | .globl \func | |
24 | .type \func,@function | |
25 | \func: | |
26 | .cfi_startproc simple | |
27 | .cfi_return_column 64 | |
28 | .cfi_def_cfa $sp, 48 | |
29 | .cfi_rel_offset 64, 8 | |
30 | .cfi_rel_offset $gp, 16 | |
31 | .cfi_rel_offset $16, 24 | |
32 | .cfi_rel_offset $17, 32 | |
33 | .cfi_rel_offset $18, 40 | |
34 | .endm | |
35 | ||
36 | .macro CFI_END_OSF_FRAME func | |
37 | .cfi_endproc | |
38 | .size \func, . - \func | |
39 | .endm | |
40 | ||
1da177e4 LT |
41 | /* |
42 | * This defines the normal kernel pt-regs layout. | |
43 | * | |
44 | * regs 9-15 preserved by C code | |
45 | * regs 16-18 saved by PAL-code | |
46 | * regs 29-30 saved and set up by PAL-code | |
47 | * JRP - Save regs 16-18 in a special area of the stack, so that | |
48 | * the palcode-provided values are available to the signal handler. | |
49 | */ | |
50 | ||
231b0bed RH |
51 | .macro SAVE_ALL |
52 | subq $sp, SP_OFF, $sp | |
53 | .cfi_adjust_cfa_offset SP_OFF | |
54 | stq $0, 0($sp) | |
55 | stq $1, 8($sp) | |
56 | stq $2, 16($sp) | |
57 | stq $3, 24($sp) | |
58 | stq $4, 32($sp) | |
59 | stq $28, 144($sp) | |
60 | .cfi_rel_offset $0, 0 | |
61 | .cfi_rel_offset $1, 8 | |
62 | .cfi_rel_offset $2, 16 | |
63 | .cfi_rel_offset $3, 24 | |
64 | .cfi_rel_offset $4, 32 | |
65 | .cfi_rel_offset $28, 144 | |
66 | lda $2, alpha_mv | |
67 | stq $5, 40($sp) | |
68 | stq $6, 48($sp) | |
69 | stq $7, 56($sp) | |
70 | stq $8, 64($sp) | |
71 | stq $19, 72($sp) | |
72 | stq $20, 80($sp) | |
73 | stq $21, 88($sp) | |
74 | ldq $2, HAE_CACHE($2) | |
75 | stq $22, 96($sp) | |
76 | stq $23, 104($sp) | |
77 | stq $24, 112($sp) | |
78 | stq $25, 120($sp) | |
79 | stq $26, 128($sp) | |
80 | stq $27, 136($sp) | |
81 | stq $2, 152($sp) | |
82 | stq $16, 160($sp) | |
83 | stq $17, 168($sp) | |
1da177e4 | 84 | stq $18, 176($sp) |
231b0bed RH |
85 | .cfi_rel_offset $5, 40 |
86 | .cfi_rel_offset $6, 48 | |
87 | .cfi_rel_offset $7, 56 | |
88 | .cfi_rel_offset $8, 64 | |
89 | .cfi_rel_offset $19, 72 | |
90 | .cfi_rel_offset $20, 80 | |
91 | .cfi_rel_offset $21, 88 | |
92 | .cfi_rel_offset $22, 96 | |
93 | .cfi_rel_offset $23, 104 | |
94 | .cfi_rel_offset $24, 112 | |
95 | .cfi_rel_offset $25, 120 | |
96 | .cfi_rel_offset $26, 128 | |
97 | .cfi_rel_offset $27, 136 | |
98 | .endm | |
99 | ||
100 | .macro RESTORE_ALL | |
101 | lda $19, alpha_mv | |
102 | ldq $0, 0($sp) | |
103 | ldq $1, 8($sp) | |
104 | ldq $2, 16($sp) | |
105 | ldq $3, 24($sp) | |
106 | ldq $21, 152($sp) | |
107 | ldq $20, HAE_CACHE($19) | |
108 | ldq $4, 32($sp) | |
109 | ldq $5, 40($sp) | |
110 | ldq $6, 48($sp) | |
111 | ldq $7, 56($sp) | |
112 | subq $20, $21, $20 | |
113 | ldq $8, 64($sp) | |
114 | beq $20, 99f | |
115 | ldq $20, HAE_REG($19) | |
116 | stq $21, HAE_CACHE($19) | |
117 | stq $21, 0($20) | |
118 | 99: ldq $19, 72($sp) | |
119 | ldq $20, 80($sp) | |
120 | ldq $21, 88($sp) | |
121 | ldq $22, 96($sp) | |
122 | ldq $23, 104($sp) | |
123 | ldq $24, 112($sp) | |
124 | ldq $25, 120($sp) | |
125 | ldq $26, 128($sp) | |
126 | ldq $27, 136($sp) | |
127 | ldq $28, 144($sp) | |
1da177e4 | 128 | addq $sp, SP_OFF, $sp |
231b0bed RH |
129 | .cfi_restore $0 |
130 | .cfi_restore $1 | |
131 | .cfi_restore $2 | |
132 | .cfi_restore $3 | |
133 | .cfi_restore $4 | |
134 | .cfi_restore $5 | |
135 | .cfi_restore $6 | |
136 | .cfi_restore $7 | |
137 | .cfi_restore $8 | |
138 | .cfi_restore $19 | |
139 | .cfi_restore $20 | |
140 | .cfi_restore $21 | |
141 | .cfi_restore $22 | |
142 | .cfi_restore $23 | |
143 | .cfi_restore $24 | |
144 | .cfi_restore $25 | |
145 | .cfi_restore $26 | |
146 | .cfi_restore $27 | |
147 | .cfi_restore $28 | |
148 | .cfi_adjust_cfa_offset -SP_OFF | |
149 | .endm | |
150 | ||
151 | .macro DO_SWITCH_STACK | |
152 | bsr $1, do_switch_stack | |
153 | .cfi_adjust_cfa_offset SWITCH_STACK_SIZE | |
154 | .cfi_rel_offset $9, 0 | |
155 | .cfi_rel_offset $10, 8 | |
156 | .cfi_rel_offset $11, 16 | |
157 | .cfi_rel_offset $12, 24 | |
158 | .cfi_rel_offset $13, 32 | |
159 | .cfi_rel_offset $14, 40 | |
160 | .cfi_rel_offset $15, 48 | |
161 | /* We don't really care about the FP registers for debugging. */ | |
162 | .endm | |
163 | ||
164 | .macro UNDO_SWITCH_STACK | |
165 | bsr $1, undo_switch_stack | |
166 | .cfi_restore $9 | |
167 | .cfi_restore $10 | |
168 | .cfi_restore $11 | |
169 | .cfi_restore $12 | |
170 | .cfi_restore $13 | |
171 | .cfi_restore $14 | |
172 | .cfi_restore $15 | |
173 | .cfi_adjust_cfa_offset -SWITCH_STACK_SIZE | |
174 | .endm | |
1da177e4 LT |
175 | |
176 | /* | |
177 | * Non-syscall kernel entry points. | |
178 | */ | |
179 | ||
231b0bed | 180 | CFI_START_OSF_FRAME entInt |
1da177e4 LT |
181 | SAVE_ALL |
182 | lda $8, 0x3fff | |
183 | lda $26, ret_from_sys_call | |
184 | bic $sp, $8, $8 | |
185 | mov $sp, $19 | |
186 | jsr $31, do_entInt | |
231b0bed | 187 | CFI_END_OSF_FRAME entInt |
1da177e4 | 188 | |
231b0bed | 189 | CFI_START_OSF_FRAME entArith |
1da177e4 LT |
190 | SAVE_ALL |
191 | lda $8, 0x3fff | |
192 | lda $26, ret_from_sys_call | |
193 | bic $sp, $8, $8 | |
194 | mov $sp, $18 | |
195 | jsr $31, do_entArith | |
231b0bed | 196 | CFI_END_OSF_FRAME entArith |
1da177e4 | 197 | |
231b0bed | 198 | CFI_START_OSF_FRAME entMM |
1da177e4 LT |
199 | SAVE_ALL |
200 | /* save $9 - $15 so the inline exception code can manipulate them. */ | |
201 | subq $sp, 56, $sp | |
231b0bed | 202 | .cfi_adjust_cfa_offset 56 |
1da177e4 LT |
203 | stq $9, 0($sp) |
204 | stq $10, 8($sp) | |
205 | stq $11, 16($sp) | |
206 | stq $12, 24($sp) | |
207 | stq $13, 32($sp) | |
208 | stq $14, 40($sp) | |
209 | stq $15, 48($sp) | |
231b0bed RH |
210 | .cfi_rel_offset $9, 0 |
211 | .cfi_rel_offset $10, 8 | |
212 | .cfi_rel_offset $11, 16 | |
213 | .cfi_rel_offset $12, 24 | |
214 | .cfi_rel_offset $13, 32 | |
215 | .cfi_rel_offset $14, 40 | |
216 | .cfi_rel_offset $15, 48 | |
1da177e4 LT |
217 | addq $sp, 56, $19 |
218 | /* handle the fault */ | |
219 | lda $8, 0x3fff | |
220 | bic $sp, $8, $8 | |
221 | jsr $26, do_page_fault | |
222 | /* reload the registers after the exception code played. */ | |
223 | ldq $9, 0($sp) | |
224 | ldq $10, 8($sp) | |
225 | ldq $11, 16($sp) | |
226 | ldq $12, 24($sp) | |
227 | ldq $13, 32($sp) | |
228 | ldq $14, 40($sp) | |
229 | ldq $15, 48($sp) | |
230 | addq $sp, 56, $sp | |
231b0bed RH |
231 | .cfi_restore $9 |
232 | .cfi_restore $10 | |
233 | .cfi_restore $11 | |
234 | .cfi_restore $12 | |
235 | .cfi_restore $13 | |
236 | .cfi_restore $14 | |
237 | .cfi_restore $15 | |
238 | .cfi_adjust_cfa_offset -56 | |
1da177e4 LT |
239 | /* finish up the syscall as normal. */ |
240 | br ret_from_sys_call | |
231b0bed | 241 | CFI_END_OSF_FRAME entMM |
1da177e4 | 242 | |
231b0bed | 243 | CFI_START_OSF_FRAME entIF |
1da177e4 LT |
244 | SAVE_ALL |
245 | lda $8, 0x3fff | |
246 | lda $26, ret_from_sys_call | |
247 | bic $sp, $8, $8 | |
248 | mov $sp, $17 | |
249 | jsr $31, do_entIF | |
231b0bed | 250 | CFI_END_OSF_FRAME entIF |
1da177e4 | 251 | |
231b0bed | 252 | CFI_START_OSF_FRAME entUna |
1da177e4 | 253 | lda $sp, -256($sp) |
231b0bed | 254 | .cfi_adjust_cfa_offset 256 |
1da177e4 | 255 | stq $0, 0($sp) |
231b0bed RH |
256 | .cfi_rel_offset $0, 0 |
257 | .cfi_remember_state | |
1da177e4 LT |
258 | ldq $0, 256($sp) /* get PS */ |
259 | stq $1, 8($sp) | |
260 | stq $2, 16($sp) | |
261 | stq $3, 24($sp) | |
262 | and $0, 8, $0 /* user mode? */ | |
263 | stq $4, 32($sp) | |
264 | bne $0, entUnaUser /* yup -> do user-level unaligned fault */ | |
265 | stq $5, 40($sp) | |
266 | stq $6, 48($sp) | |
267 | stq $7, 56($sp) | |
268 | stq $8, 64($sp) | |
269 | stq $9, 72($sp) | |
270 | stq $10, 80($sp) | |
271 | stq $11, 88($sp) | |
272 | stq $12, 96($sp) | |
273 | stq $13, 104($sp) | |
274 | stq $14, 112($sp) | |
275 | stq $15, 120($sp) | |
276 | /* 16-18 PAL-saved */ | |
277 | stq $19, 152($sp) | |
278 | stq $20, 160($sp) | |
279 | stq $21, 168($sp) | |
280 | stq $22, 176($sp) | |
281 | stq $23, 184($sp) | |
282 | stq $24, 192($sp) | |
283 | stq $25, 200($sp) | |
284 | stq $26, 208($sp) | |
285 | stq $27, 216($sp) | |
286 | stq $28, 224($sp) | |
d70ddac1 | 287 | mov $sp, $19 |
1da177e4 | 288 | stq $gp, 232($sp) |
231b0bed RH |
289 | .cfi_rel_offset $1, 1*8 |
290 | .cfi_rel_offset $2, 2*8 | |
291 | .cfi_rel_offset $3, 3*8 | |
292 | .cfi_rel_offset $4, 4*8 | |
293 | .cfi_rel_offset $5, 5*8 | |
294 | .cfi_rel_offset $6, 6*8 | |
295 | .cfi_rel_offset $7, 7*8 | |
296 | .cfi_rel_offset $8, 8*8 | |
297 | .cfi_rel_offset $9, 9*8 | |
298 | .cfi_rel_offset $10, 10*8 | |
299 | .cfi_rel_offset $11, 11*8 | |
300 | .cfi_rel_offset $12, 12*8 | |
301 | .cfi_rel_offset $13, 13*8 | |
302 | .cfi_rel_offset $14, 14*8 | |
303 | .cfi_rel_offset $15, 15*8 | |
304 | .cfi_rel_offset $19, 19*8 | |
305 | .cfi_rel_offset $20, 20*8 | |
306 | .cfi_rel_offset $21, 21*8 | |
307 | .cfi_rel_offset $22, 22*8 | |
308 | .cfi_rel_offset $23, 23*8 | |
309 | .cfi_rel_offset $24, 24*8 | |
310 | .cfi_rel_offset $25, 25*8 | |
311 | .cfi_rel_offset $26, 26*8 | |
312 | .cfi_rel_offset $27, 27*8 | |
313 | .cfi_rel_offset $28, 28*8 | |
314 | .cfi_rel_offset $29, 29*8 | |
1da177e4 LT |
315 | lda $8, 0x3fff |
316 | stq $31, 248($sp) | |
317 | bic $sp, $8, $8 | |
318 | jsr $26, do_entUna | |
319 | ldq $0, 0($sp) | |
320 | ldq $1, 8($sp) | |
321 | ldq $2, 16($sp) | |
322 | ldq $3, 24($sp) | |
323 | ldq $4, 32($sp) | |
324 | ldq $5, 40($sp) | |
325 | ldq $6, 48($sp) | |
326 | ldq $7, 56($sp) | |
327 | ldq $8, 64($sp) | |
328 | ldq $9, 72($sp) | |
329 | ldq $10, 80($sp) | |
330 | ldq $11, 88($sp) | |
331 | ldq $12, 96($sp) | |
332 | ldq $13, 104($sp) | |
333 | ldq $14, 112($sp) | |
334 | ldq $15, 120($sp) | |
335 | /* 16-18 PAL-saved */ | |
336 | ldq $19, 152($sp) | |
337 | ldq $20, 160($sp) | |
338 | ldq $21, 168($sp) | |
339 | ldq $22, 176($sp) | |
340 | ldq $23, 184($sp) | |
341 | ldq $24, 192($sp) | |
342 | ldq $25, 200($sp) | |
343 | ldq $26, 208($sp) | |
344 | ldq $27, 216($sp) | |
345 | ldq $28, 224($sp) | |
346 | ldq $gp, 232($sp) | |
347 | lda $sp, 256($sp) | |
231b0bed RH |
348 | .cfi_restore $1 |
349 | .cfi_restore $2 | |
350 | .cfi_restore $3 | |
351 | .cfi_restore $4 | |
352 | .cfi_restore $5 | |
353 | .cfi_restore $6 | |
354 | .cfi_restore $7 | |
355 | .cfi_restore $8 | |
356 | .cfi_restore $9 | |
357 | .cfi_restore $10 | |
358 | .cfi_restore $11 | |
359 | .cfi_restore $12 | |
360 | .cfi_restore $13 | |
361 | .cfi_restore $14 | |
362 | .cfi_restore $15 | |
363 | .cfi_restore $19 | |
364 | .cfi_restore $20 | |
365 | .cfi_restore $21 | |
366 | .cfi_restore $22 | |
367 | .cfi_restore $23 | |
368 | .cfi_restore $24 | |
369 | .cfi_restore $25 | |
370 | .cfi_restore $26 | |
371 | .cfi_restore $27 | |
372 | .cfi_restore $28 | |
373 | .cfi_restore $29 | |
374 | .cfi_adjust_cfa_offset -256 | |
1da177e4 | 375 | call_pal PAL_rti |
1da177e4 LT |
376 | |
377 | .align 4 | |
1da177e4 | 378 | entUnaUser: |
231b0bed | 379 | .cfi_restore_state |
1da177e4 LT |
380 | ldq $0, 0($sp) /* restore original $0 */ |
381 | lda $sp, 256($sp) /* pop entUna's stack frame */ | |
231b0bed RH |
382 | .cfi_restore $0 |
383 | .cfi_adjust_cfa_offset -256 | |
1da177e4 LT |
384 | SAVE_ALL /* setup normal kernel stack */ |
385 | lda $sp, -56($sp) | |
231b0bed | 386 | .cfi_adjust_cfa_offset 56 |
1da177e4 LT |
387 | stq $9, 0($sp) |
388 | stq $10, 8($sp) | |
389 | stq $11, 16($sp) | |
390 | stq $12, 24($sp) | |
391 | stq $13, 32($sp) | |
392 | stq $14, 40($sp) | |
393 | stq $15, 48($sp) | |
231b0bed RH |
394 | .cfi_rel_offset $9, 0 |
395 | .cfi_rel_offset $10, 8 | |
396 | .cfi_rel_offset $11, 16 | |
397 | .cfi_rel_offset $12, 24 | |
398 | .cfi_rel_offset $13, 32 | |
399 | .cfi_rel_offset $14, 40 | |
400 | .cfi_rel_offset $15, 48 | |
1da177e4 LT |
401 | lda $8, 0x3fff |
402 | addq $sp, 56, $19 | |
403 | bic $sp, $8, $8 | |
404 | jsr $26, do_entUnaUser | |
405 | ldq $9, 0($sp) | |
406 | ldq $10, 8($sp) | |
407 | ldq $11, 16($sp) | |
408 | ldq $12, 24($sp) | |
409 | ldq $13, 32($sp) | |
410 | ldq $14, 40($sp) | |
411 | ldq $15, 48($sp) | |
412 | lda $sp, 56($sp) | |
231b0bed RH |
413 | .cfi_restore $9 |
414 | .cfi_restore $10 | |
415 | .cfi_restore $11 | |
416 | .cfi_restore $12 | |
417 | .cfi_restore $13 | |
418 | .cfi_restore $14 | |
419 | .cfi_restore $15 | |
420 | .cfi_adjust_cfa_offset -56 | |
1da177e4 | 421 | br ret_from_sys_call |
231b0bed | 422 | CFI_END_OSF_FRAME entUna |
1da177e4 | 423 | |
231b0bed | 424 | CFI_START_OSF_FRAME entDbg |
1da177e4 LT |
425 | SAVE_ALL |
426 | lda $8, 0x3fff | |
427 | lda $26, ret_from_sys_call | |
428 | bic $sp, $8, $8 | |
429 | mov $sp, $16 | |
430 | jsr $31, do_entDbg | |
231b0bed | 431 | CFI_END_OSF_FRAME entDbg |
1da177e4 LT |
432 | \f |
433 | /* | |
434 | * The system call entry point is special. Most importantly, it looks | |
435 | * like a function call to userspace as far as clobbered registers. We | |
436 | * do preserve the argument registers (for syscall restarts) and $26 | |
437 | * (for leaf syscall functions). | |
438 | * | |
439 | * So much for theory. We don't take advantage of this yet. | |
440 | * | |
441 | * Note that a0-a2 are not saved by PALcode as with the other entry points. | |
442 | */ | |
443 | ||
444 | .align 4 | |
445 | .globl entSys | |
231b0bed RH |
446 | .type entSys, @function |
447 | .cfi_startproc simple | |
448 | .cfi_return_column 64 | |
449 | .cfi_def_cfa $sp, 48 | |
450 | .cfi_rel_offset 64, 8 | |
451 | .cfi_rel_offset $gp, 16 | |
1da177e4 LT |
452 | entSys: |
453 | SAVE_ALL | |
454 | lda $8, 0x3fff | |
455 | bic $sp, $8, $8 | |
456 | lda $4, NR_SYSCALLS($31) | |
457 | stq $16, SP_OFF+24($sp) | |
458 | lda $5, sys_call_table | |
459 | lda $27, sys_ni_syscall | |
460 | cmpult $0, $4, $4 | |
461 | ldl $3, TI_FLAGS($8) | |
462 | stq $17, SP_OFF+32($sp) | |
463 | s8addq $0, $5, $5 | |
464 | stq $18, SP_OFF+40($sp) | |
231b0bed RH |
465 | .cfi_rel_offset $16, SP_OFF+24 |
466 | .cfi_rel_offset $17, SP_OFF+32 | |
467 | .cfi_rel_offset $18, SP_OFF+40 | |
a9302e84 | 468 | #ifdef CONFIG_AUDITSYSCALL |
469 | lda $6, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | |
470 | and $3, $6, $3 | |
471 | #endif | |
472 | bne $3, strace | |
1da177e4 LT |
473 | beq $4, 1f |
474 | ldq $27, 0($5) | |
475 | 1: jsr $26, ($27), alpha_ni_syscall | |
476 | ldgp $gp, 0($26) | |
477 | blt $0, $syscall_error /* the call failed */ | |
478 | stq $0, 0($sp) | |
479 | stq $31, 72($sp) /* a3=0 => no error */ | |
480 | ||
481 | .align 4 | |
231b0bed | 482 | .globl ret_from_sys_call |
1da177e4 | 483 | ret_from_sys_call: |
cb450766 | 484 | cmovne $26, 0, $18 /* $18 = 0 => non-restartable */ |
1da177e4 LT |
485 | ldq $0, SP_OFF($sp) |
486 | and $0, 8, $0 | |
77edffb6 | 487 | beq $0, ret_to_kernel |
494486a1 | 488 | ret_to_user: |
1da177e4 LT |
489 | /* Make sure need_resched and sigpending don't change between |
490 | sampling and the rti. */ | |
491 | lda $16, 7 | |
492 | call_pal PAL_swpipl | |
cb450766 AV |
493 | ldl $17, TI_FLAGS($8) |
494 | and $17, _TIF_WORK_MASK, $2 | |
494486a1 | 495 | bne $2, work_pending |
1da177e4 | 496 | restore_all: |
231b0bed | 497 | .cfi_remember_state |
1da177e4 LT |
498 | RESTORE_ALL |
499 | call_pal PAL_rti | |
500 | ||
77edffb6 | 501 | ret_to_kernel: |
231b0bed | 502 | .cfi_restore_state |
77edffb6 AV |
503 | lda $16, 7 |
504 | call_pal PAL_swpipl | |
505 | br restore_all | |
506 | ||
1da177e4 LT |
507 | .align 3 |
508 | $syscall_error: | |
509 | /* | |
510 | * Some system calls (e.g., ptrace) can return arbitrary | |
511 | * values which might normally be mistaken as error numbers. | |
512 | * Those functions must zero $0 (v0) directly in the stack | |
513 | * frame to indicate that a negative return value wasn't an | |
514 | * error number.. | |
515 | */ | |
cb450766 AV |
516 | ldq $18, 0($sp) /* old syscall nr (zero if success) */ |
517 | beq $18, $ret_success | |
1da177e4 | 518 | |
cb450766 | 519 | ldq $19, 72($sp) /* .. and this a3 */ |
1da177e4 LT |
520 | subq $31, $0, $0 /* with error in v0 */ |
521 | addq $31, 1, $1 /* set a3 for errno return */ | |
522 | stq $0, 0($sp) | |
523 | mov $31, $26 /* tell "ret_from_sys_call" we can restart */ | |
524 | stq $1, 72($sp) /* a3 for return */ | |
525 | br ret_from_sys_call | |
526 | ||
527 | $ret_success: | |
528 | stq $0, 0($sp) | |
529 | stq $31, 72($sp) /* a3=0 => no error */ | |
530 | br ret_from_sys_call | |
1da177e4 LT |
531 | |
532 | /* | |
533 | * Do all cleanup when returning from all interrupts and system calls. | |
534 | * | |
535 | * Arguments: | |
1da177e4 | 536 | * $8: current. |
cb450766 AV |
537 | * $17: TI_FLAGS. |
538 | * $18: The old syscall number, or zero if this is not a return | |
1da177e4 | 539 | * from a syscall that errored and is possibly restartable. |
cb450766 | 540 | * $19: The old a3 value |
1da177e4 LT |
541 | */ |
542 | ||
543 | .align 4 | |
231b0bed | 544 | .type work_pending, @function |
1da177e4 | 545 | work_pending: |
cb450766 | 546 | and $17, _TIF_NOTIFY_RESUME | _TIF_SIGPENDING, $2 |
7721d3c2 | 547 | bne $2, $work_notifysig |
1da177e4 LT |
548 | |
549 | $work_resched: | |
7721d3c2 AV |
550 | /* |
551 | * We can get here only if we returned from syscall without SIGPENDING | |
552 | * or got through work_notifysig already. Either case means no syscall | |
cb450766 | 553 | * restarts for us, so let $18 and $19 burn. |
7721d3c2 | 554 | */ |
1da177e4 | 555 | jsr $26, schedule |
cb450766 | 556 | mov 0, $18 |
7721d3c2 | 557 | br ret_to_user |
1da177e4 LT |
558 | |
559 | $work_notifysig: | |
b927b3e2 | 560 | mov $sp, $16 |
231b0bed | 561 | DO_SWITCH_STACK |
6972d6f2 | 562 | jsr $26, do_work_pending |
231b0bed | 563 | UNDO_SWITCH_STACK |
6972d6f2 | 564 | br restore_all |
1da177e4 LT |
565 | |
566 | /* | |
567 | * PTRACE syscall handler | |
568 | */ | |
569 | ||
570 | .align 4 | |
231b0bed | 571 | .type strace, @function |
1da177e4 LT |
572 | strace: |
573 | /* set up signal stack, call syscall_trace */ | |
231b0bed | 574 | DO_SWITCH_STACK |
12f79be9 | 575 | jsr $26, syscall_trace_enter /* returns the syscall number */ |
231b0bed | 576 | UNDO_SWITCH_STACK |
1da177e4 | 577 | |
12f79be9 | 578 | /* get the arguments back.. */ |
1da177e4 LT |
579 | ldq $16, SP_OFF+24($sp) |
580 | ldq $17, SP_OFF+32($sp) | |
581 | ldq $18, SP_OFF+40($sp) | |
582 | ldq $19, 72($sp) | |
583 | ldq $20, 80($sp) | |
584 | ldq $21, 88($sp) | |
585 | ||
586 | /* get the system call pointer.. */ | |
587 | lda $1, NR_SYSCALLS($31) | |
588 | lda $2, sys_call_table | |
589 | lda $27, alpha_ni_syscall | |
590 | cmpult $0, $1, $1 | |
591 | s8addq $0, $2, $2 | |
592 | beq $1, 1f | |
593 | ldq $27, 0($2) | |
594 | 1: jsr $26, ($27), sys_gettimeofday | |
53293638 | 595 | ret_from_straced: |
1da177e4 LT |
596 | ldgp $gp, 0($26) |
597 | ||
598 | /* check return.. */ | |
599 | blt $0, $strace_error /* the call failed */ | |
600 | stq $31, 72($sp) /* a3=0 => no error */ | |
601 | $strace_success: | |
602 | stq $0, 0($sp) /* save return value */ | |
603 | ||
231b0bed | 604 | DO_SWITCH_STACK |
12f79be9 | 605 | jsr $26, syscall_trace_leave |
231b0bed | 606 | UNDO_SWITCH_STACK |
1da177e4 LT |
607 | br $31, ret_from_sys_call |
608 | ||
609 | .align 3 | |
610 | $strace_error: | |
cb450766 AV |
611 | ldq $18, 0($sp) /* old syscall nr (zero if success) */ |
612 | beq $18, $strace_success | |
613 | ldq $19, 72($sp) /* .. and this a3 */ | |
1da177e4 LT |
614 | |
615 | subq $31, $0, $0 /* with error in v0 */ | |
616 | addq $31, 1, $1 /* set a3 for errno return */ | |
617 | stq $0, 0($sp) | |
618 | stq $1, 72($sp) /* a3 for return */ | |
619 | ||
231b0bed | 620 | DO_SWITCH_STACK |
cb450766 AV |
621 | mov $18, $9 /* save old syscall number */ |
622 | mov $19, $10 /* save old a3 */ | |
12f79be9 | 623 | jsr $26, syscall_trace_leave |
cb450766 AV |
624 | mov $9, $18 |
625 | mov $10, $19 | |
231b0bed | 626 | UNDO_SWITCH_STACK |
1da177e4 LT |
627 | |
628 | mov $31, $26 /* tell "ret_from_sys_call" we can restart */ | |
629 | br ret_from_sys_call | |
231b0bed | 630 | CFI_END_OSF_FRAME entSys |
1da177e4 LT |
631 | \f |
632 | /* | |
633 | * Save and restore the switch stack -- aka the balance of the user context. | |
634 | */ | |
635 | ||
636 | .align 4 | |
231b0bed RH |
637 | .type do_switch_stack, @function |
638 | .cfi_startproc simple | |
639 | .cfi_return_column 64 | |
640 | .cfi_def_cfa $sp, 0 | |
641 | .cfi_register 64, $1 | |
1da177e4 LT |
642 | do_switch_stack: |
643 | lda $sp, -SWITCH_STACK_SIZE($sp) | |
231b0bed | 644 | .cfi_adjust_cfa_offset SWITCH_STACK_SIZE |
1da177e4 LT |
645 | stq $9, 0($sp) |
646 | stq $10, 8($sp) | |
647 | stq $11, 16($sp) | |
648 | stq $12, 24($sp) | |
649 | stq $13, 32($sp) | |
650 | stq $14, 40($sp) | |
651 | stq $15, 48($sp) | |
652 | stq $26, 56($sp) | |
653 | stt $f0, 64($sp) | |
654 | stt $f1, 72($sp) | |
655 | stt $f2, 80($sp) | |
656 | stt $f3, 88($sp) | |
657 | stt $f4, 96($sp) | |
658 | stt $f5, 104($sp) | |
659 | stt $f6, 112($sp) | |
660 | stt $f7, 120($sp) | |
661 | stt $f8, 128($sp) | |
662 | stt $f9, 136($sp) | |
663 | stt $f10, 144($sp) | |
664 | stt $f11, 152($sp) | |
665 | stt $f12, 160($sp) | |
666 | stt $f13, 168($sp) | |
667 | stt $f14, 176($sp) | |
668 | stt $f15, 184($sp) | |
669 | stt $f16, 192($sp) | |
670 | stt $f17, 200($sp) | |
671 | stt $f18, 208($sp) | |
672 | stt $f19, 216($sp) | |
673 | stt $f20, 224($sp) | |
674 | stt $f21, 232($sp) | |
675 | stt $f22, 240($sp) | |
676 | stt $f23, 248($sp) | |
677 | stt $f24, 256($sp) | |
678 | stt $f25, 264($sp) | |
679 | stt $f26, 272($sp) | |
680 | stt $f27, 280($sp) | |
681 | mf_fpcr $f0 # get fpcr | |
682 | stt $f28, 288($sp) | |
683 | stt $f29, 296($sp) | |
684 | stt $f30, 304($sp) | |
685 | stt $f0, 312($sp) # save fpcr in slot of $f31 | |
686 | ldt $f0, 64($sp) # dont let "do_switch_stack" change fp state. | |
687 | ret $31, ($1), 1 | |
231b0bed RH |
688 | .cfi_endproc |
689 | .size do_switch_stack, .-do_switch_stack | |
1da177e4 LT |
690 | |
691 | .align 4 | |
231b0bed RH |
692 | .type undo_switch_stack, @function |
693 | .cfi_startproc simple | |
694 | .cfi_def_cfa $sp, 0 | |
695 | .cfi_register 64, $1 | |
1da177e4 LT |
696 | undo_switch_stack: |
697 | ldq $9, 0($sp) | |
698 | ldq $10, 8($sp) | |
699 | ldq $11, 16($sp) | |
700 | ldq $12, 24($sp) | |
701 | ldq $13, 32($sp) | |
702 | ldq $14, 40($sp) | |
703 | ldq $15, 48($sp) | |
704 | ldq $26, 56($sp) | |
705 | ldt $f30, 312($sp) # get saved fpcr | |
706 | ldt $f0, 64($sp) | |
707 | ldt $f1, 72($sp) | |
708 | ldt $f2, 80($sp) | |
709 | ldt $f3, 88($sp) | |
710 | mt_fpcr $f30 # install saved fpcr | |
711 | ldt $f4, 96($sp) | |
712 | ldt $f5, 104($sp) | |
713 | ldt $f6, 112($sp) | |
714 | ldt $f7, 120($sp) | |
715 | ldt $f8, 128($sp) | |
716 | ldt $f9, 136($sp) | |
717 | ldt $f10, 144($sp) | |
718 | ldt $f11, 152($sp) | |
719 | ldt $f12, 160($sp) | |
720 | ldt $f13, 168($sp) | |
721 | ldt $f14, 176($sp) | |
722 | ldt $f15, 184($sp) | |
723 | ldt $f16, 192($sp) | |
724 | ldt $f17, 200($sp) | |
725 | ldt $f18, 208($sp) | |
726 | ldt $f19, 216($sp) | |
727 | ldt $f20, 224($sp) | |
728 | ldt $f21, 232($sp) | |
729 | ldt $f22, 240($sp) | |
730 | ldt $f23, 248($sp) | |
731 | ldt $f24, 256($sp) | |
732 | ldt $f25, 264($sp) | |
733 | ldt $f26, 272($sp) | |
734 | ldt $f27, 280($sp) | |
735 | ldt $f28, 288($sp) | |
736 | ldt $f29, 296($sp) | |
737 | ldt $f30, 304($sp) | |
738 | lda $sp, SWITCH_STACK_SIZE($sp) | |
739 | ret $31, ($1), 1 | |
231b0bed RH |
740 | .cfi_endproc |
741 | .size undo_switch_stack, .-undo_switch_stack | |
1da177e4 LT |
742 | \f |
743 | /* | |
744 | * The meat of the context switch code. | |
745 | */ | |
746 | ||
747 | .align 4 | |
748 | .globl alpha_switch_to | |
231b0bed RH |
749 | .type alpha_switch_to, @function |
750 | .cfi_startproc | |
1da177e4 | 751 | alpha_switch_to: |
231b0bed | 752 | DO_SWITCH_STACK |
1da177e4 LT |
753 | call_pal PAL_swpctx |
754 | lda $8, 0x3fff | |
231b0bed | 755 | UNDO_SWITCH_STACK |
1da177e4 LT |
756 | bic $sp, $8, $8 |
757 | mov $17, $0 | |
758 | ret | |
231b0bed RH |
759 | .cfi_endproc |
760 | .size alpha_switch_to, .-alpha_switch_to | |
1da177e4 LT |
761 | |
762 | /* | |
763 | * New processes begin life here. | |
764 | */ | |
765 | ||
766 | .globl ret_from_fork | |
767 | .align 4 | |
768 | .ent ret_from_fork | |
769 | ret_from_fork: | |
770 | lda $26, ret_from_sys_call | |
771 | mov $17, $16 | |
772 | jmp $31, schedule_tail | |
773 | .end ret_from_fork | |
774 | ||
775 | /* | |
cba1ec7e | 776 | * ... and new kernel threads - here |
1da177e4 LT |
777 | */ |
778 | .align 4 | |
cba1ec7e AV |
779 | .globl ret_from_kernel_thread |
780 | .ent ret_from_kernel_thread | |
781 | ret_from_kernel_thread: | |
782 | mov $17, $16 | |
783 | jsr $26, schedule_tail | |
784 | mov $9, $27 | |
785 | mov $10, $16 | |
786 | jsr $26, ($9) | |
44f4b56b AV |
787 | mov $31, $19 /* to disable syscall restarts */ |
788 | br $31, ret_to_user | |
5522be6a | 789 | .end ret_from_kernel_thread |
44f4b56b | 790 | |
1da177e4 LT |
791 | \f |
792 | /* | |
793 | * Special system calls. Most of these are special in that they either | |
794 | * have to play switch_stack games or in some way use the pt_regs struct. | |
795 | */ | |
dfe09ae0 AV |
796 | |
797 | .macro fork_like name | |
1da177e4 | 798 | .align 4 |
dfe09ae0 AV |
799 | .globl alpha_\name |
800 | .ent alpha_\name | |
801 | alpha_\name: | |
1da177e4 | 802 | .prologue 0 |
1da177e4 | 803 | bsr $1, do_switch_stack |
dfe09ae0 | 804 | jsr $26, sys_\name |
e0e431aa AV |
805 | ldq $26, 56($sp) |
806 | lda $sp, SWITCH_STACK_SIZE($sp) | |
1da177e4 | 807 | ret |
dfe09ae0 AV |
808 | .end alpha_\name |
809 | .endm | |
1da177e4 | 810 | |
dfe09ae0 AV |
811 | fork_like fork |
812 | fork_like vfork | |
813 | fork_like clone | |
1da177e4 LT |
814 | |
815 | .align 4 | |
816 | .globl sys_sigreturn | |
817 | .ent sys_sigreturn | |
818 | sys_sigreturn: | |
819 | .prologue 0 | |
53293638 AV |
820 | lda $9, ret_from_straced |
821 | cmpult $26, $9, $9 | |
1da177e4 LT |
822 | lda $sp, -SWITCH_STACK_SIZE($sp) |
823 | jsr $26, do_sigreturn | |
53293638 | 824 | bne $9, 1f |
12f79be9 | 825 | jsr $26, syscall_trace_leave |
53293638 | 826 | 1: br $1, undo_switch_stack |
1da177e4 LT |
827 | br ret_from_sys_call |
828 | .end sys_sigreturn | |
829 | ||
830 | .align 4 | |
831 | .globl sys_rt_sigreturn | |
832 | .ent sys_rt_sigreturn | |
833 | sys_rt_sigreturn: | |
834 | .prologue 0 | |
53293638 AV |
835 | lda $9, ret_from_straced |
836 | cmpult $26, $9, $9 | |
1da177e4 LT |
837 | lda $sp, -SWITCH_STACK_SIZE($sp) |
838 | jsr $26, do_rt_sigreturn | |
53293638 | 839 | bne $9, 1f |
12f79be9 | 840 | jsr $26, syscall_trace_leave |
53293638 | 841 | 1: br $1, undo_switch_stack |
1da177e4 LT |
842 | br ret_from_sys_call |
843 | .end sys_rt_sigreturn | |
844 | ||
1da177e4 LT |
845 | .align 4 |
846 | .globl alpha_ni_syscall | |
847 | .ent alpha_ni_syscall | |
848 | alpha_ni_syscall: | |
849 | .prologue 0 | |
850 | /* Special because it also implements overflow handling via | |
851 | syscall number 0. And if you recall, zero is a special | |
852 | trigger for "not an error". Store large non-zero there. */ | |
853 | lda $0, -ENOSYS | |
854 | unop | |
855 | stq $0, 0($sp) | |
856 | ret | |
857 | .end alpha_ni_syscall |