1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * arch/alpha/kernel/entry.S |
4 | * |
5 | * Kernel entry-points. |
6 | */ |
7 | |
8 | #include <asm/asm-offsets.h> |
9 | #include <asm/thread_info.h> |
10 | #include <asm/pal.h> |
11 | #include <asm/errno.h> |
12 | #include <asm/unistd.h> |
13 | |
14 | .text |
15 | .set noat |
16 | .cfi_sections .debug_frame |
17 | |
18 | /* Stack offsets. */ |
19 | #define SP_OFF 184 |
20 | #define SWITCH_STACK_SIZE 64 |
21 | |
22 | .macro CFI_START_OSF_FRAME func |
23 | .align 4 |
24 | .globl \func |
25 | .type \func,@function |
26 | \func: |
27 | .cfi_startproc simple |
28 | .cfi_return_column 64 |
29 | .cfi_def_cfa $sp, 48 |
30 | .cfi_rel_offset 64, 8 |
31 | .cfi_rel_offset $gp, 16 |
32 | .cfi_rel_offset $16, 24 |
33 | .cfi_rel_offset $17, 32 |
34 | .cfi_rel_offset $18, 40 |
35 | .endm |
36 | |
37 | .macro CFI_END_OSF_FRAME func |
38 | .cfi_endproc |
39 | .size \func, . - \func |
40 | .endm |
41 | |
42 | /* |
43 | * This defines the normal kernel pt-regs layout. |
44 | * |
45 | * regs 9-15 preserved by C code |
46 | * regs 16-18 saved by PAL-code |
47 | * regs 29-30 saved and set up by PAL-code |
48 | * JRP - Save regs 16-18 in a special area of the stack, so that |
49 | * the palcode-provided values are available to the signal handler. |
50 | */ |
51 | |
52 | .macro SAVE_ALL |
53 | subq $sp, SP_OFF, $sp |
54 | .cfi_adjust_cfa_offset SP_OFF |
55 | stq $0, 0($sp) |
56 | stq $1, 8($sp) |
57 | stq $2, 16($sp) |
58 | stq $3, 24($sp) |
59 | stq $4, 32($sp) |
60 | stq $28, 144($sp) |
61 | .cfi_rel_offset $0, 0 |
62 | .cfi_rel_offset $1, 8 |
63 | .cfi_rel_offset $2, 16 |
64 | .cfi_rel_offset $3, 24 |
65 | .cfi_rel_offset $4, 32 |
66 | .cfi_rel_offset $28, 144 |
67 | lda $2, alpha_mv |
68 | stq $5, 40($sp) |
69 | stq $6, 48($sp) |
70 | stq $7, 56($sp) |
71 | stq $8, 64($sp) |
72 | stq $19, 72($sp) |
73 | stq $20, 80($sp) |
74 | stq $21, 88($sp) |
75 | ldq $2, HAE_CACHE($2) |
76 | stq $22, 96($sp) |
77 | stq $23, 104($sp) |
78 | stq $24, 112($sp) |
79 | stq $25, 120($sp) |
80 | stq $26, 128($sp) |
81 | stq $27, 136($sp) |
82 | stq $2, 152($sp) |
83 | stq $16, 160($sp) |
84 | stq $17, 168($sp) |
85 | stq $18, 176($sp) |
86 | .cfi_rel_offset $5, 40 |
87 | .cfi_rel_offset $6, 48 |
88 | .cfi_rel_offset $7, 56 |
89 | .cfi_rel_offset $8, 64 |
90 | .cfi_rel_offset $19, 72 |
91 | .cfi_rel_offset $20, 80 |
92 | .cfi_rel_offset $21, 88 |
93 | .cfi_rel_offset $22, 96 |
94 | .cfi_rel_offset $23, 104 |
95 | .cfi_rel_offset $24, 112 |
96 | .cfi_rel_offset $25, 120 |
97 | .cfi_rel_offset $26, 128 |
98 | .cfi_rel_offset $27, 136 |
99 | .endm |
100 | |
101 | .macro RESTORE_ALL |
102 | lda $19, alpha_mv |
103 | ldq $0, 0($sp) |
104 | ldq $1, 8($sp) |
105 | ldq $2, 16($sp) |
106 | ldq $3, 24($sp) |
107 | ldq $21, 152($sp) |
108 | ldq $20, HAE_CACHE($19) |
109 | ldq $4, 32($sp) |
110 | ldq $5, 40($sp) |
111 | ldq $6, 48($sp) |
112 | ldq $7, 56($sp) |
113 | subq $20, $21, $20 |
114 | ldq $8, 64($sp) |
115 | beq $20, 99f |
116 | ldq $20, HAE_REG($19) |
117 | stq $21, HAE_CACHE($19) |
118 | stq $21, 0($20) |
119 | 99: ldq $19, 72($sp) |
120 | ldq $20, 80($sp) |
121 | ldq $21, 88($sp) |
122 | ldq $22, 96($sp) |
123 | ldq $23, 104($sp) |
124 | ldq $24, 112($sp) |
125 | ldq $25, 120($sp) |
126 | ldq $26, 128($sp) |
127 | ldq $27, 136($sp) |
128 | ldq $28, 144($sp) |
129 | addq $sp, SP_OFF, $sp |
130 | .cfi_restore $0 |
131 | .cfi_restore $1 |
132 | .cfi_restore $2 |
133 | .cfi_restore $3 |
134 | .cfi_restore $4 |
135 | .cfi_restore $5 |
136 | .cfi_restore $6 |
137 | .cfi_restore $7 |
138 | .cfi_restore $8 |
139 | .cfi_restore $19 |
140 | .cfi_restore $20 |
141 | .cfi_restore $21 |
142 | .cfi_restore $22 |
143 | .cfi_restore $23 |
144 | .cfi_restore $24 |
145 | .cfi_restore $25 |
146 | .cfi_restore $26 |
147 | .cfi_restore $27 |
148 | .cfi_restore $28 |
149 | .cfi_adjust_cfa_offset -SP_OFF |
150 | .endm |
151 | |
152 | .macro DO_SWITCH_STACK |
153 | bsr $1, do_switch_stack |
154 | .cfi_adjust_cfa_offset SWITCH_STACK_SIZE |
155 | .cfi_rel_offset $9, 0 |
156 | .cfi_rel_offset $10, 8 |
157 | .cfi_rel_offset $11, 16 |
158 | .cfi_rel_offset $12, 24 |
159 | .cfi_rel_offset $13, 32 |
160 | .cfi_rel_offset $14, 40 |
161 | .cfi_rel_offset $15, 48 |
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 |
175 | |
176 | /* |
177 | * Non-syscall kernel entry points. |
178 | */ |
179 | |
180 | CFI_START_OSF_FRAME entInt |
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 |
187 | CFI_END_OSF_FRAME entInt |
188 | |
189 | CFI_START_OSF_FRAME entArith |
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 |
196 | CFI_END_OSF_FRAME entArith |
197 | |
198 | CFI_START_OSF_FRAME entMM |
199 | SAVE_ALL |
200 | /* save $9 - $15 so the inline exception code can manipulate them. */ |
201 | subq $sp, 56, $sp |
202 | .cfi_adjust_cfa_offset 56 |
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) |
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 |
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 |
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 |
239 | /* finish up the syscall as normal. */ |
240 | br ret_from_sys_call |
241 | CFI_END_OSF_FRAME entMM |
242 | |
243 | CFI_START_OSF_FRAME entIF |
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 |
250 | CFI_END_OSF_FRAME entIF |
251 | |
252 | CFI_START_OSF_FRAME entUna |
253 | lda $sp, -256($sp) |
254 | .cfi_adjust_cfa_offset 256 |
255 | stq $0, 0($sp) |
256 | .cfi_rel_offset $0, 0 |
257 | .cfi_remember_state |
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) |
287 | mov $sp, $19 |
288 | stq $gp, 232($sp) |
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 |
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) |
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 |
375 | call_pal PAL_rti |
376 | |
377 | .align 4 |
378 | entUnaUser: |
379 | .cfi_restore_state |
380 | ldq $0, 0($sp) /* restore original $0 */ |
381 | lda $sp, 256($sp) /* pop entUna's stack frame */ |
382 | .cfi_restore $0 |
383 | .cfi_adjust_cfa_offset -256 |
384 | SAVE_ALL /* setup normal kernel stack */ |
385 | lda $sp, -56($sp) |
386 | .cfi_adjust_cfa_offset 56 |
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) |
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 |
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) |
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 |
421 | br ret_from_sys_call |
422 | CFI_END_OSF_FRAME entUna |
423 | |
424 | CFI_START_OSF_FRAME entDbg |
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 |
431 | CFI_END_OSF_FRAME entDbg |
432 | |
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 |
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 |
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) |
465 | .cfi_rel_offset $16, SP_OFF+24 |
466 | .cfi_rel_offset $17, SP_OFF+32 |
467 | .cfi_rel_offset $18, SP_OFF+40 |
468 | #ifdef CONFIG_AUDITSYSCALL |
469 | lda $6, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT |
470 | and $3, $6, $3 |
471 | bne $3, strace |
472 | #else |
473 | blbs $3, strace /* check for SYSCALL_TRACE in disguise */ |
474 | #endif |
475 | beq $4, 1f |
476 | ldq $27, 0($5) |
477 | 1: jsr $26, ($27), sys_ni_syscall |
478 | ldgp $gp, 0($26) |
479 | blt $0, $syscall_error /* the call failed */ |
480 | $ret_success: |
481 | stq $0, 0($sp) |
482 | stq $31, 72($sp) /* a3=0 => no error */ |
483 | |
484 | .align 4 |
485 | .globl ret_from_sys_call |
486 | ret_from_sys_call: |
487 | cmovne $26, 0, $18 /* $18 = 0 => non-restartable */ |
488 | ldq $0, SP_OFF($sp) |
489 | and $0, 8, $0 |
490 | beq $0, ret_to_kernel |
491 | ret_to_user: |
492 | /* Make sure need_resched and sigpending don't change between |
493 | sampling and the rti. */ |
494 | lda $16, 7 |
495 | call_pal PAL_swpipl |
496 | ldl $17, TI_FLAGS($8) |
497 | and $17, _TIF_WORK_MASK, $2 |
498 | bne $2, work_pending |
499 | restore_all: |
500 | ldl $2, TI_STATUS($8) |
501 | and $2, TS_SAVED_FP | TS_RESTORE_FP, $3 |
502 | bne $3, restore_fpu |
503 | restore_other: |
504 | .cfi_remember_state |
505 | RESTORE_ALL |
506 | call_pal PAL_rti |
507 | |
508 | ret_to_kernel: |
509 | .cfi_restore_state |
510 | lda $16, 7 |
511 | call_pal PAL_swpipl |
512 | br restore_other |
513 | |
514 | .align 3 |
515 | $syscall_error: |
516 | /* |
517 | * Some system calls (e.g., ptrace) can return arbitrary |
518 | * values which might normally be mistaken as error numbers. |
519 | * Those functions must zero $0 (v0) directly in the stack |
520 | * frame to indicate that a negative return value wasn't an |
521 | * error number.. |
522 | */ |
523 | ldq $18, 0($sp) /* old syscall nr (zero if success) */ |
524 | beq $18, $ret_success |
525 | |
526 | ldq $19, 72($sp) /* .. and this a3 */ |
527 | subq $31, $0, $0 /* with error in v0 */ |
528 | addq $31, 1, $1 /* set a3 for errno return */ |
529 | stq $0, 0($sp) |
530 | mov $31, $26 /* tell "ret_from_sys_call" we can restart */ |
531 | stq $1, 72($sp) /* a3 for return */ |
532 | br ret_from_sys_call |
533 | |
534 | /* |
535 | * Do all cleanup when returning from all interrupts and system calls. |
536 | * |
537 | * Arguments: |
538 | * $8: current. |
539 | * $17: TI_FLAGS. |
540 | * $18: The old syscall number, or zero if this is not a return |
541 | * from a syscall that errored and is possibly restartable. |
542 | * $19: The old a3 value |
543 | */ |
544 | |
545 | .align 4 |
546 | .type work_pending, @function |
547 | work_pending: |
548 | and $17, _TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL, $2 |
549 | bne $2, $work_notifysig |
550 | |
551 | $work_resched: |
552 | /* |
553 | * We can get here only if we returned from syscall without SIGPENDING |
554 | * or got through work_notifysig already. Either case means no syscall |
555 | * restarts for us, so let $18 and $19 burn. |
556 | */ |
557 | jsr $26, schedule |
558 | mov 0, $18 |
559 | br ret_to_user |
560 | |
561 | $work_notifysig: |
562 | mov $sp, $16 |
563 | DO_SWITCH_STACK |
564 | jsr $26, do_work_pending |
565 | UNDO_SWITCH_STACK |
566 | br restore_all |
567 | |
568 | /* |
569 | * PTRACE syscall handler |
570 | */ |
571 | |
572 | .align 4 |
573 | .type strace, @function |
574 | strace: |
575 | /* set up signal stack, call syscall_trace */ |
576 | // NB: if anyone adds preemption, this block will need to be protected |
577 | ldl $1, TI_STATUS($8) |
578 | and $1, TS_SAVED_FP, $3 |
579 | or $1, TS_SAVED_FP, $2 |
580 | bne $3, 1f |
581 | stl $2, TI_STATUS($8) |
582 | bsr $26, __save_fpu |
583 | 1: |
584 | DO_SWITCH_STACK |
585 | jsr $26, syscall_trace_enter /* returns the syscall number */ |
586 | UNDO_SWITCH_STACK |
587 | |
588 | /* get the arguments back.. */ |
589 | ldq $16, SP_OFF+24($sp) |
590 | ldq $17, SP_OFF+32($sp) |
591 | ldq $18, SP_OFF+40($sp) |
592 | ldq $19, 72($sp) |
593 | ldq $20, 80($sp) |
594 | ldq $21, 88($sp) |
595 | |
596 | /* get the system call pointer.. */ |
597 | lda $1, NR_syscalls($31) |
598 | lda $2, sys_call_table |
599 | lda $27, sys_ni_syscall |
600 | cmpult $0, $1, $1 |
601 | s8addq $0, $2, $2 |
602 | beq $1, 1f |
603 | ldq $27, 0($2) |
604 | 1: jsr $26, ($27), sys_gettimeofday |
605 | ret_from_straced: |
606 | ldgp $gp, 0($26) |
607 | |
608 | /* check return.. */ |
609 | blt $0, $strace_error /* the call failed */ |
610 | $strace_success: |
611 | stq $31, 72($sp) /* a3=0 => no error */ |
612 | stq $0, 0($sp) /* save return value */ |
613 | |
614 | DO_SWITCH_STACK |
615 | jsr $26, syscall_trace_leave |
616 | UNDO_SWITCH_STACK |
617 | br $31, ret_from_sys_call |
618 | |
619 | .align 3 |
620 | $strace_error: |
621 | ldq $18, 0($sp) /* old syscall nr (zero if success) */ |
622 | beq $18, $strace_success |
623 | ldq $19, 72($sp) /* .. and this a3 */ |
624 | |
625 | subq $31, $0, $0 /* with error in v0 */ |
626 | addq $31, 1, $1 /* set a3 for errno return */ |
627 | stq $0, 0($sp) |
628 | stq $1, 72($sp) /* a3 for return */ |
629 | |
630 | DO_SWITCH_STACK |
631 | mov $18, $9 /* save old syscall number */ |
632 | mov $19, $10 /* save old a3 */ |
633 | jsr $26, syscall_trace_leave |
634 | mov $9, $18 |
635 | mov $10, $19 |
636 | UNDO_SWITCH_STACK |
637 | |
638 | mov $31, $26 /* tell "ret_from_sys_call" we can restart */ |
639 | br ret_from_sys_call |
640 | CFI_END_OSF_FRAME entSys |
641 | |
642 | /* |
643 | * Save and restore the switch stack -- aka the balance of the user context. |
644 | */ |
645 | |
646 | .align 4 |
647 | .type do_switch_stack, @function |
648 | .cfi_startproc simple |
649 | .cfi_return_column 64 |
650 | .cfi_def_cfa $sp, 0 |
651 | .cfi_register 64, $1 |
652 | do_switch_stack: |
653 | lda $sp, -SWITCH_STACK_SIZE($sp) |
654 | .cfi_adjust_cfa_offset SWITCH_STACK_SIZE |
655 | stq $9, 0($sp) |
656 | stq $10, 8($sp) |
657 | stq $11, 16($sp) |
658 | stq $12, 24($sp) |
659 | stq $13, 32($sp) |
660 | stq $14, 40($sp) |
661 | stq $15, 48($sp) |
662 | stq $26, 56($sp) |
663 | ret $31, ($1), 1 |
664 | .cfi_endproc |
665 | .size do_switch_stack, .-do_switch_stack |
666 | |
667 | .align 4 |
668 | .type undo_switch_stack, @function |
669 | .cfi_startproc simple |
670 | .cfi_def_cfa $sp, 0 |
671 | .cfi_register 64, $1 |
672 | undo_switch_stack: |
673 | ldq $9, 0($sp) |
674 | ldq $10, 8($sp) |
675 | ldq $11, 16($sp) |
676 | ldq $12, 24($sp) |
677 | ldq $13, 32($sp) |
678 | ldq $14, 40($sp) |
679 | ldq $15, 48($sp) |
680 | ldq $26, 56($sp) |
681 | lda $sp, SWITCH_STACK_SIZE($sp) |
682 | ret $31, ($1), 1 |
683 | .cfi_endproc |
684 | .size undo_switch_stack, .-undo_switch_stack |
685 | |
686 | #define FR(n) n * 8 + TI_FP($8) |
687 | .align 4 |
688 | .globl __save_fpu |
689 | .type __save_fpu, @function |
690 | __save_fpu: |
691 | #define V(n) stt $f##n, FR(n) |
692 | V( 0); V( 1); V( 2); V( 3) |
693 | V( 4); V( 5); V( 6); V( 7) |
694 | V( 8); V( 9); V(10); V(11) |
695 | V(12); V(13); V(14); V(15) |
696 | V(16); V(17); V(18); V(19) |
697 | V(20); V(21); V(22); V(23) |
698 | V(24); V(25); V(26); V(27) |
699 | mf_fpcr $f0 # get fpcr |
700 | V(28); V(29); V(30) |
701 | stt $f0, FR(31) # save fpcr in slot of $f31 |
702 | ldt $f0, FR(0) # don't let "__save_fpu" change fp state. |
703 | ret |
704 | #undef V |
705 | .size __save_fpu, .-__save_fpu |
706 | |
707 | .align 4 |
708 | restore_fpu: |
709 | and $3, TS_RESTORE_FP, $3 |
710 | bic $2, TS_SAVED_FP | TS_RESTORE_FP, $2 |
711 | beq $3, 1f |
712 | #define V(n) ldt $f##n, FR(n) |
713 | ldt $f30, FR(31) # get saved fpcr |
714 | V( 0); V( 1); V( 2); V( 3) |
715 | mt_fpcr $f30 # install saved fpcr |
716 | V( 4); V( 5); V( 6); V( 7) |
717 | V( 8); V( 9); V(10); V(11) |
718 | V(12); V(13); V(14); V(15) |
719 | V(16); V(17); V(18); V(19) |
720 | V(20); V(21); V(22); V(23) |
721 | V(24); V(25); V(26); V(27) |
722 | V(28); V(29); V(30) |
723 | 1: stl $2, TI_STATUS($8) |
724 | br restore_other |
725 | #undef V |
726 | |
727 | |
728 | /* |
729 | * The meat of the context switch code. |
730 | */ |
731 | .align 4 |
732 | .globl alpha_switch_to |
733 | .type alpha_switch_to, @function |
734 | .cfi_startproc |
735 | alpha_switch_to: |
736 | DO_SWITCH_STACK |
737 | ldl $1, TI_STATUS($8) |
738 | and $1, TS_RESTORE_FP, $3 |
739 | bne $3, 1f |
740 | or $1, TS_RESTORE_FP | TS_SAVED_FP, $2 |
741 | and $1, TS_SAVED_FP, $3 |
742 | stl $2, TI_STATUS($8) |
743 | bne $3, 1f |
744 | bsr $26, __save_fpu |
745 | 1: |
746 | call_pal PAL_swpctx |
747 | lda $8, 0x3fff |
748 | UNDO_SWITCH_STACK |
749 | bic $sp, $8, $8 |
750 | mov $17, $0 |
751 | ret |
752 | .cfi_endproc |
753 | .size alpha_switch_to, .-alpha_switch_to |
754 | |
755 | /* |
756 | * New processes begin life here. |
757 | */ |
758 | |
759 | .globl ret_from_fork |
760 | .align 4 |
761 | .ent ret_from_fork |
762 | ret_from_fork: |
763 | lda $26, ret_to_user |
764 | mov $17, $16 |
765 | jmp $31, schedule_tail |
766 | .end ret_from_fork |
767 | |
768 | /* |
769 | * ... and new kernel threads - here |
770 | */ |
771 | .align 4 |
772 | .globl ret_from_kernel_thread |
773 | .ent ret_from_kernel_thread |
774 | ret_from_kernel_thread: |
775 | mov $17, $16 |
776 | jsr $26, schedule_tail |
777 | mov $9, $27 |
778 | mov $10, $16 |
779 | jsr $26, ($9) |
780 | br $31, ret_to_user |
781 | .end ret_from_kernel_thread |
782 | |
783 | |
784 | /* |
785 | * Special system calls. Most of these are special in that they either |
786 | * have to play switch_stack games. |
787 | */ |
788 | |
789 | .macro fork_like name |
790 | .align 4 |
791 | .globl alpha_\name |
792 | .ent alpha_\name |
793 | alpha_\name: |
794 | .prologue 0 |
795 | bsr $1, do_switch_stack |
796 | // NB: if anyone adds preemption, this block will need to be protected |
797 | ldl $1, TI_STATUS($8) |
798 | and $1, TS_SAVED_FP, $3 |
799 | or $1, TS_SAVED_FP, $2 |
800 | bne $3, 1f |
801 | stl $2, TI_STATUS($8) |
802 | bsr $26, __save_fpu |
803 | 1: |
804 | jsr $26, sys_\name |
805 | ldq $26, 56($sp) |
806 | lda $sp, SWITCH_STACK_SIZE($sp) |
807 | ret |
808 | .end alpha_\name |
809 | .endm |
810 | |
811 | fork_like fork |
812 | fork_like vfork |
813 | fork_like clone |
814 | |
815 | .macro sigreturn_like name |
816 | .align 4 |
817 | .globl sys_\name |
818 | .ent sys_\name |
819 | sys_\name: |
820 | .prologue 0 |
821 | lda $9, ret_from_straced |
822 | cmpult $26, $9, $9 |
823 | lda $sp, -SWITCH_STACK_SIZE($sp) |
824 | jsr $26, do_\name |
825 | bne $9, 1f |
826 | jsr $26, syscall_trace_leave |
827 | 1: br $1, undo_switch_stack |
828 | br ret_from_sys_call |
829 | .end sys_\name |
830 | .endm |
831 | |
832 | sigreturn_like sigreturn |
833 | sigreturn_like rt_sigreturn |
834 | |
835 | .align 4 |
836 | .globl alpha_syscall_zero |
837 | .ent alpha_syscall_zero |
838 | alpha_syscall_zero: |
839 | .prologue 0 |
840 | /* Special because it needs to do something opposite to |
841 | force_successful_syscall_return(). We use the saved |
842 | syscall number for that, zero meaning "not an error". |
843 | That works nicely, but for real syscall 0 we need to |
844 | make sure that this logics doesn't get confused. |
845 | Store a non-zero there - -ENOSYS we need in register |
846 | for our return value will do just fine. |
847 | */ |
848 | lda $0, -ENOSYS |
849 | unop |
850 | stq $0, 0($sp) |
851 | ret |
852 | .end alpha_syscall_zero |
853 | |