projects/linux·blob master · refs

791 lines · 15.7 KiB

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#include <linux/errno.h>
14
15 .text
16 .set noat
17 .cfi_sections .debug_frame
18
19.macro CFI_START_OSF_FRAME func
20 .align 4
21 .globl \func
22 .type \func,@function
23\func:
24 .cfi_startproc simple
25 .cfi_return_column 64
26 .cfi_def_cfa $sp, 48
27 .cfi_rel_offset 64, 8
28 .cfi_rel_offset $gp, 16
29 .cfi_rel_offset $16, 24
30 .cfi_rel_offset $17, 32
31 .cfi_rel_offset $18, 40
32.endm
33
34.macro CFI_END_OSF_FRAME func
35 .cfi_endproc
36 .size \func, . - \func
37.endm
38
39.macro LOCKDEP_HARDIRQS_ON_RESTORE psreg
40#ifdef CONFIG_PROVE_LOCKING
41 /* a0 = saved PS */
42 ldq $16, \psreg
43
44 /* a1 = callsite IP for lockdep */
45 lda $17, 1f
46
47 jsr $26, lockdep_on_restore
48 ldgp $gp, 0($26)
491:
50#endif
51.endm
52
53/*
54 * This defines the normal kernel pt-regs layout.
55 *
56 * regs 9-15 preserved by C code
57 * regs 16-18 saved by PAL-code
58 * regs 29-30 saved and set up by PAL-code
59 * JRP - Save regs 16-18 in a special area of the stack, so that
60 * the palcode-provided values are available to the signal handler.
61 */
62
63.macro SAVE_ALL
64 subq $sp, SP_OFF, $sp
65 .cfi_adjust_cfa_offset SP_OFF
66 stq $0, 0($sp)
67 stq $1, 8($sp)
68 stq $2, 16($sp)
69 stq $3, 24($sp)
70 stq $4, 32($sp)
71 stq $28, 144($sp)
72 .cfi_rel_offset $0, 0
73 .cfi_rel_offset $1, 8
74 .cfi_rel_offset $2, 16
75 .cfi_rel_offset $3, 24
76 .cfi_rel_offset $4, 32
77 .cfi_rel_offset $28, 144
78 lda $2, alpha_mv
79 stq $5, 40($sp)
80 stq $6, 48($sp)
81 stq $7, 56($sp)
82 stq $8, 64($sp)
83 stq $19, 72($sp)
84 stq $20, 80($sp)
85 stq $21, 88($sp)
86 ldq $2, HAE_CACHE($2)
87 stq $22, 96($sp)
88 stq $23, 104($sp)
89 stq $24, 112($sp)
90 stq $25, 120($sp)
91 stq $26, 128($sp)
92 stq $27, 136($sp)
93 stq $2, 152($sp)
94 stq $16, 160($sp)
95 stq $17, 168($sp)
96 stq $18, 176($sp)
97 .cfi_rel_offset $5, 40
98 .cfi_rel_offset $6, 48
99 .cfi_rel_offset $7, 56
100 .cfi_rel_offset $8, 64
101 .cfi_rel_offset $19, 72
102 .cfi_rel_offset $20, 80
103 .cfi_rel_offset $21, 88
104 .cfi_rel_offset $22, 96
105 .cfi_rel_offset $23, 104
106 .cfi_rel_offset $24, 112
107 .cfi_rel_offset $25, 120
108 .cfi_rel_offset $26, 128
109 .cfi_rel_offset $27, 136
110.endm
111
112.macro RESTORE_ALL
113 lda $19, alpha_mv
114 ldq $0, 0($sp)
115 ldq $1, 8($sp)
116 ldq $2, 16($sp)
117 ldq $3, 24($sp)
118 ldq $21, 152($sp)
119 ldq $20, HAE_CACHE($19)
120 ldq $4, 32($sp)
121 ldq $5, 40($sp)
122 ldq $6, 48($sp)
123 ldq $7, 56($sp)
124 subq $20, $21, $20
125 ldq $8, 64($sp)
126 beq $20, 99f
127 ldq $20, HAE_REG($19)
128 stq $21, HAE_CACHE($19)
129 stq $21, 0($20)
13099: ldq $19, 72($sp)
131 ldq $20, 80($sp)
132 ldq $21, 88($sp)
133 ldq $22, 96($sp)
134 ldq $23, 104($sp)
135 ldq $24, 112($sp)
136 ldq $25, 120($sp)
137 ldq $26, 128($sp)
138 ldq $27, 136($sp)
139 ldq $28, 144($sp)
140 addq $sp, SP_OFF, $sp
141 .cfi_restore $0
142 .cfi_restore $1
143 .cfi_restore $2
144 .cfi_restore $3
145 .cfi_restore $4
146 .cfi_restore $5
147 .cfi_restore $6
148 .cfi_restore $7
149 .cfi_restore $8
150 .cfi_restore $19
151 .cfi_restore $20
152 .cfi_restore $21
153 .cfi_restore $22
154 .cfi_restore $23
155 .cfi_restore $24
156 .cfi_restore $25
157 .cfi_restore $26
158 .cfi_restore $27
159 .cfi_restore $28
160 .cfi_adjust_cfa_offset -SP_OFF
161.endm
162
163.macro DO_SWITCH_STACK
164 bsr $1, do_switch_stack
165 .cfi_adjust_cfa_offset SWITCH_STACK_SIZE
166 .cfi_rel_offset $9, 0
167 .cfi_rel_offset $10, 8
168 .cfi_rel_offset $11, 16
169 .cfi_rel_offset $12, 24
170 .cfi_rel_offset $13, 32
171 .cfi_rel_offset $14, 40
172 .cfi_rel_offset $15, 48
173.endm
174
175.macro UNDO_SWITCH_STACK
176 bsr $1, undo_switch_stack
177 .cfi_restore $9
178 .cfi_restore $10
179 .cfi_restore $11
180 .cfi_restore $12
181 .cfi_restore $13
182 .cfi_restore $14
183 .cfi_restore $15
184 .cfi_adjust_cfa_offset -SWITCH_STACK_SIZE
185.endm
186
187/*
188 * Non-syscall kernel entry points.
189 */
190
191CFI_START_OSF_FRAME entInt
192 SAVE_ALL
193 lda $8, 0x3fff
194 lda $26, ret_from_exception
195 bic $sp, $8, $8
196 mov $sp, $19
197 jsr $31, do_entInt
198CFI_END_OSF_FRAME entInt
199
200CFI_START_OSF_FRAME entArith
201 SAVE_ALL
202 lda $8, 0x3fff
203 lda $26, ret_from_exception
204 bic $sp, $8, $8
205 mov $sp, $18
206 jsr $31, do_entArith
207CFI_END_OSF_FRAME entArith
208
209CFI_START_OSF_FRAME entMM
210 SAVE_ALL
211/* save $9 - $15 so the inline exception code can manipulate them. */
212 subq $sp, 64, $sp
213 .cfi_adjust_cfa_offset 64
214 stq $9, 0($sp)
215 stq $10, 8($sp)
216 stq $11, 16($sp)
217 stq $12, 24($sp)
218 stq $13, 32($sp)
219 stq $14, 40($sp)
220 stq $15, 48($sp)
221 .cfi_rel_offset $9, 0
222 .cfi_rel_offset $10, 8
223 .cfi_rel_offset $11, 16
224 .cfi_rel_offset $12, 24
225 .cfi_rel_offset $13, 32
226 .cfi_rel_offset $14, 40
227 .cfi_rel_offset $15, 48
228 addq $sp, 64, $19
229/* handle the fault */
230 lda $8, 0x3fff
231 bic $sp, $8, $8
232 jsr $26, do_page_fault
233/* reload the registers after the exception code played. */
234 ldq $9, 0($sp)
235 ldq $10, 8($sp)
236 ldq $11, 16($sp)
237 ldq $12, 24($sp)
238 ldq $13, 32($sp)
239 ldq $14, 40($sp)
240 ldq $15, 48($sp)
241 addq $sp, 64, $sp
242 .cfi_restore $9
243 .cfi_restore $10
244 .cfi_restore $11
245 .cfi_restore $12
246 .cfi_restore $13
247 .cfi_restore $14
248 .cfi_restore $15
249 .cfi_adjust_cfa_offset -64
250/* finish up the syscall as normal. */
251 br ret_from_exception
252CFI_END_OSF_FRAME entMM
253
254CFI_START_OSF_FRAME entIF
255 SAVE_ALL
256 lda $8, 0x3fff
257 lda $26, ret_from_exception
258 bic $sp, $8, $8
259 mov $sp, $17
260 jsr $31, do_entIF
261CFI_END_OSF_FRAME entIF
262
263CFI_START_OSF_FRAME entUna
264 lda $sp, -256($sp)
265 .cfi_adjust_cfa_offset 256
266 stq $0, 0($sp)
267 .cfi_rel_offset $0, 0
268 .cfi_remember_state
269 ldq $0, 256($sp) /* get PS */
270 stq $1, 8($sp)
271 stq $2, 16($sp)
272 stq $3, 24($sp)
273 and $0, 8, $0 /* user mode? */
274 stq $4, 32($sp)
275 bne $0, entUnaUser /* yup -> do user-level unaligned fault */
276 stq $5, 40($sp)
277 stq $6, 48($sp)
278 stq $7, 56($sp)
279 stq $8, 64($sp)
280 stq $9, 72($sp)
281 stq $10, 80($sp)
282 stq $11, 88($sp)
283 stq $12, 96($sp)
284 stq $13, 104($sp)
285 stq $14, 112($sp)
286 stq $15, 120($sp)
287 /* 16-18 PAL-saved */
288 stq $19, 152($sp)
289 stq $20, 160($sp)
290 stq $21, 168($sp)
291 stq $22, 176($sp)
292 stq $23, 184($sp)
293 stq $24, 192($sp)
294 stq $25, 200($sp)
295 stq $26, 208($sp)
296 stq $27, 216($sp)
297 stq $28, 224($sp)
298 mov $sp, $19
299 stq $gp, 232($sp)
300 .cfi_rel_offset $1, 1*8
301 .cfi_rel_offset $2, 2*8
302 .cfi_rel_offset $3, 3*8
303 .cfi_rel_offset $4, 4*8
304 .cfi_rel_offset $5, 5*8
305 .cfi_rel_offset $6, 6*8
306 .cfi_rel_offset $7, 7*8
307 .cfi_rel_offset $8, 8*8
308 .cfi_rel_offset $9, 9*8
309 .cfi_rel_offset $10, 10*8
310 .cfi_rel_offset $11, 11*8
311 .cfi_rel_offset $12, 12*8
312 .cfi_rel_offset $13, 13*8
313 .cfi_rel_offset $14, 14*8
314 .cfi_rel_offset $15, 15*8
315 .cfi_rel_offset $19, 19*8
316 .cfi_rel_offset $20, 20*8
317 .cfi_rel_offset $21, 21*8
318 .cfi_rel_offset $22, 22*8
319 .cfi_rel_offset $23, 23*8
320 .cfi_rel_offset $24, 24*8
321 .cfi_rel_offset $25, 25*8
322 .cfi_rel_offset $26, 26*8
323 .cfi_rel_offset $27, 27*8
324 .cfi_rel_offset $28, 28*8
325 .cfi_rel_offset $29, 29*8
326 lda $8, 0x3fff
327 stq $31, 248($sp)
328 bic $sp, $8, $8
329 jsr $26, do_entUna
330 ldq $0, 0($sp)
331 ldq $1, 8($sp)
332 ldq $2, 16($sp)
333 ldq $3, 24($sp)
334 ldq $4, 32($sp)
335 ldq $5, 40($sp)
336 ldq $6, 48($sp)
337 ldq $7, 56($sp)
338 ldq $8, 64($sp)
339 ldq $9, 72($sp)
340 ldq $10, 80($sp)
341 ldq $11, 88($sp)
342 ldq $12, 96($sp)
343 ldq $13, 104($sp)
344 ldq $14, 112($sp)
345 ldq $15, 120($sp)
346 /* 16-18 PAL-saved */
347 ldq $19, 152($sp)
348 ldq $20, 160($sp)
349 ldq $21, 168($sp)
350 ldq $22, 176($sp)
351 ldq $23, 184($sp)
352 ldq $24, 192($sp)
353 ldq $25, 200($sp)
354 ldq $26, 208($sp)
355 ldq $27, 216($sp)
356 ldq $28, 224($sp)
357 ldq $gp, 232($sp)
358 lda $sp, 256($sp)
359 .cfi_restore $1
360 .cfi_restore $2
361 .cfi_restore $3
362 .cfi_restore $4
363 .cfi_restore $5
364 .cfi_restore $6
365 .cfi_restore $7
366 .cfi_restore $8
367 .cfi_restore $9
368 .cfi_restore $10
369 .cfi_restore $11
370 .cfi_restore $12
371 .cfi_restore $13
372 .cfi_restore $14
373 .cfi_restore $15
374 .cfi_restore $19
375 .cfi_restore $20
376 .cfi_restore $21
377 .cfi_restore $22
378 .cfi_restore $23
379 .cfi_restore $24
380 .cfi_restore $25
381 .cfi_restore $26
382 .cfi_restore $27
383 .cfi_restore $28
384 .cfi_restore $29
385 .cfi_adjust_cfa_offset -256
386 LOCKDEP_HARDIRQS_ON_RESTORE SP_OFF($sp)
387 call_pal PAL_rti
388
389 .align 4
390entUnaUser:
391 .cfi_restore_state
392 ldq $0, 0($sp) /* restore original $0 */
393 lda $sp, 256($sp) /* pop entUna's stack frame */
394 .cfi_restore $0
395 .cfi_adjust_cfa_offset -256
396 SAVE_ALL /* setup normal kernel stack */
397 lda $sp, -64($sp)
398 .cfi_adjust_cfa_offset 64
399 stq $9, 0($sp)
400 stq $10, 8($sp)
401 stq $11, 16($sp)
402 stq $12, 24($sp)
403 stq $13, 32($sp)
404 stq $14, 40($sp)
405 stq $15, 48($sp)
406 .cfi_rel_offset $9, 0
407 .cfi_rel_offset $10, 8
408 .cfi_rel_offset $11, 16
409 .cfi_rel_offset $12, 24
410 .cfi_rel_offset $13, 32
411 .cfi_rel_offset $14, 40
412 .cfi_rel_offset $15, 48
413 lda $8, 0x3fff
414 addq $sp, 64, $19
415 bic $sp, $8, $8
416 jsr $26, do_entUnaUser
417 ldq $9, 0($sp)
418 ldq $10, 8($sp)
419 ldq $11, 16($sp)
420 ldq $12, 24($sp)
421 ldq $13, 32($sp)
422 ldq $14, 40($sp)
423 ldq $15, 48($sp)
424 lda $sp, 64($sp)
425 .cfi_restore $9
426 .cfi_restore $10
427 .cfi_restore $11
428 .cfi_restore $12
429 .cfi_restore $13
430 .cfi_restore $14
431 .cfi_restore $15
432 .cfi_adjust_cfa_offset -64
433 br ret_from_exception
434CFI_END_OSF_FRAME entUna
435
436CFI_START_OSF_FRAME entDbg
437 SAVE_ALL
438 lda $8, 0x3fff
439 lda $26, ret_from_exception
440 bic $sp, $8, $8
441 mov $sp, $16
442 jsr $31, do_entDbg
443CFI_END_OSF_FRAME entDbg
444
445
446/*
447 * The system call entry point is special. Most importantly, it looks
448 * like a function call to userspace as far as clobbered registers. We
449 * do preserve the argument registers (for syscall restarts) and $26
450 * (for leaf syscall functions).
451 *
452 * So much for theory. We don't take advantage of this yet.
453 *
454 * Note that a0-a2 are not saved by PALcode as with the other entry points.
455 *
456 * Alpha syscall ABI uses:
457 * - r0 for return value
458 * - r19 ("a3") as error indicator (0=success, 1=error; r0 holds errno)
459 *
460 * For seccomp/ptrace/generic syscall helpers we track the syscall
461 * number separately:
462 * - regs->r1: current (mutable) syscall number (may be changed or set to -1)
463 *
464 */
465
466 .align 4
467 .globl entSys
468 .type entSys, @function
469 .cfi_startproc simple
470 .cfi_return_column 64
471 .cfi_def_cfa $sp, 48
472 .cfi_rel_offset 64, 8
473 .cfi_rel_offset $gp, 16
474entSys:
475 SAVE_ALL
476 ldq $1, 0($sp) /* syscall nr from saved r0 */
477 stq $1, 8($sp) /* regs->r1 = shadow syscall nr */
478
479 lda $8, 0x3fff
480 bic $sp, $8, $8
481
482 stq $16, SP_OFF+24($sp)
483 stq $17, SP_OFF+32($sp)
484 stq $18, SP_OFF+40($sp)
485
486 mov $0, $1
487 lda $16, 7
488 call_pal PAL_swpipl
489 mov $1, $0
490 mov $sp, $16
491 mov $0, $17 /* pv = selected syscall function */
492
493 DO_SWITCH_STACK
494 jsr $26, alpha_syscall_enter_select
495 ldgp $gp, 0($26)
496 UNDO_SWITCH_STACK
497
498 /*
499 * C returned syscall function pointer in $0.
500 * It also stored SKIP in TI_SYSCALL_META if dispatch is skipped.
501 */
502 lda $8, 0x3fff
503 bic $sp, $8, $8
504 ldq $3, TI_SYSCALL_META($8)
505 lda $6, ALPHA_SYSCALL_META_SKIP
506 and $3, $6, $6
507 bne $6, skip_dispatch
508
509
510 mov $0, $27
511 ldq $16, SP_OFF+24($sp)
512 ldq $17, SP_OFF+32($sp)
513 ldq $18, SP_OFF+40($sp)
514 ldq $19, 72($sp)
515 ldq $20, 80($sp)
516 ldq $21, 88($sp)
517
518 jsr $26, ($27), sys_ni_syscall
519 ldgp $gp, 0($26)
520
521skip_dispatch:
522 mov $0, $17 /* raw ret; ignored if SKIP is set */
523 mov $sp, $16 /* regs */
524
525 DO_SWITCH_STACK
526 jsr $26, alpha_finish_syscall_to_user_mode
527 ldgp $gp, 0($26)
528 UNDO_SWITCH_STACK
529
530restore_all:
531 lda $8, 0x3fff
532 bic $sp, $8, $8
533 ldl $2, TI_STATUS($8)
534 and $2, TS_SAVED_FP | TS_RESTORE_FP, $3
535 bne $3, restore_fpu
536restore_other:
537 .cfi_remember_state
538 RESTORE_ALL
539 call_pal PAL_rti
540
541ret_to_user_from_syscall:
542 lda $8, 0x3fff
543 bic $sp, $8, $8
544
545 mov $sp, $16
546 DO_SWITCH_STACK
547 jsr $26, alpha_syscall_exit_to_user_mode
548 ldgp $gp, 0($26)
549 UNDO_SWITCH_STACK
550 br restore_all
551
552 .align 4
553 .globl ret_from_sys_call
554ret_from_sys_call:
555 ldq $0, SP_OFF($sp)
556 and $0, 8, $0
557 beq $0, ret_to_kernel
558 br ret_to_user_from_syscall
559
560ret_from_exception:
561 ldq $0, SP_OFF($sp)
562 and $0, 8, $0
563 beq $0, ret_to_kernel
564 br ret_to_user_from_exception
565
566ret_to_user_from_exception:
567
568 mov $sp, $16
569 DO_SWITCH_STACK
570 jsr $26, alpha_exit_to_user_mode
571 ldgp $gp, 0($26)
572 UNDO_SWITCH_STACK
573 br restore_all
574
575ret_to_kernel:
576 .cfi_restore_state
577 lda $16, 7
578 call_pal PAL_swpipl
579 LOCKDEP_HARDIRQS_ON_RESTORE SP_OFF($sp)
580 br restore_other
581
582CFI_END_OSF_FRAME entSys
583
584/*
585 * Save and restore the switch stack -- aka the balance of the user context.
586 */
587
588 .align 4
589 .type do_switch_stack, @function
590 .cfi_startproc simple
591 .cfi_return_column 64
592 .cfi_def_cfa $sp, 0
593 .cfi_register 64, $1
594do_switch_stack:
595 lda $sp, -SWITCH_STACK_SIZE($sp)
596 .cfi_adjust_cfa_offset SWITCH_STACK_SIZE
597 stq $9, 0($sp)
598 stq $10, 8($sp)
599 stq $11, 16($sp)
600 stq $12, 24($sp)
601 stq $13, 32($sp)
602 stq $14, 40($sp)
603 stq $15, 48($sp)
604 stq $26, 56($sp)
605 ret $31, ($1), 1
606 .cfi_endproc
607 .size do_switch_stack, .-do_switch_stack
608
609 .align 4
610 .type undo_switch_stack, @function
611 .cfi_startproc simple
612 .cfi_def_cfa $sp, 0
613 .cfi_register 64, $1
614undo_switch_stack:
615 ldq $9, 0($sp)
616 ldq $10, 8($sp)
617 ldq $11, 16($sp)
618 ldq $12, 24($sp)
619 ldq $13, 32($sp)
620 ldq $14, 40($sp)
621 ldq $15, 48($sp)
622 ldq $26, 56($sp)
623 lda $sp, SWITCH_STACK_SIZE($sp)
624 ret $31, ($1), 1
625 .cfi_endproc
626 .size undo_switch_stack, .-undo_switch_stack
627
628#define FR(n) n * 8 + TI_FP($8)
629 .align 4
630 .globl __save_fpu
631 .type __save_fpu, @function
632__save_fpu:
633#define V(n) stt $f##n, FR(n)
634 V( 0); V( 1); V( 2); V( 3)
635 V( 4); V( 5); V( 6); V( 7)
636 V( 8); V( 9); V(10); V(11)
637 V(12); V(13); V(14); V(15)
638 V(16); V(17); V(18); V(19)
639 V(20); V(21); V(22); V(23)
640 V(24); V(25); V(26); V(27)
641 mf_fpcr $f0 # get fpcr
642 V(28); V(29); V(30)
643 stt $f0, FR(31) # save fpcr in slot of $f31
644 ldt $f0, FR(0) # don't let "__save_fpu" change fp state.
645 ret
646#undef V
647 .size __save_fpu, .-__save_fpu
648
649 .align 4
650restore_fpu:
651 and $3, TS_RESTORE_FP, $3
652 bic $2, TS_SAVED_FP | TS_RESTORE_FP, $2
653 beq $3, 1f
654#define V(n) ldt $f##n, FR(n)
655 ldt $f30, FR(31) # get saved fpcr
656 V( 0); V( 1); V( 2); V( 3)
657 mt_fpcr $f30 # install saved fpcr
658 V( 4); V( 5); V( 6); V( 7)
659 V( 8); V( 9); V(10); V(11)
660 V(12); V(13); V(14); V(15)
661 V(16); V(17); V(18); V(19)
662 V(20); V(21); V(22); V(23)
663 V(24); V(25); V(26); V(27)
664 V(28); V(29); V(30)
6651: stl $2, TI_STATUS($8)
666 br restore_other
667#undef V
668
669/*
670 * The meat of the context switch code.
671 */
672 .align 4
673 .globl alpha_switch_to
674 .type alpha_switch_to, @function
675 .cfi_startproc
676alpha_switch_to:
677 DO_SWITCH_STACK
678 ldl $1, TI_STATUS($8)
679 and $1, TS_RESTORE_FP, $3
680 bne $3, 1f
681 or $1, TS_RESTORE_FP | TS_SAVED_FP, $2
682 and $1, TS_SAVED_FP, $3
683 stl $2, TI_STATUS($8)
684 bne $3, 1f
685 bsr $26, __save_fpu
6861:
687 call_pal PAL_swpctx
688 lda $8, 0x3fff
689 UNDO_SWITCH_STACK
690 bic $sp, $8, $8
691 mov $17, $0
692 ret
693 .cfi_endproc
694 .size alpha_switch_to, .-alpha_switch_to
695
696/*
697 * New processes begin life here.
698 */
699
700 .globl ret_from_fork
701 .align 4
702 .ent ret_from_fork
703ret_from_fork:
704 lda $26, ret_to_user_from_exception
705 mov $17, $16
706 jmp $31, schedule_tail
707.end ret_from_fork
708
709/*
710 * ... and new kernel threads - here
711 */
712 .align 4
713 .globl ret_from_kernel_thread
714 .ent ret_from_kernel_thread
715ret_from_kernel_thread:
716 mov $17, $16
717 jsr $26, schedule_tail
718 mov $9, $27
719 mov $10, $16
720 jsr $26, ($9)
721 br $31, ret_to_user_from_exception
722.end ret_from_kernel_thread
723
724
725/*
726 * Special system calls. Most of these are special in that they either
727 * have to play switch_stack games.
728 */
729
730.macro fork_like name
731 .align 4
732 .globl alpha_\name
733 .ent alpha_\name
734alpha_\name:
735 .prologue 0
736 bsr $1, do_switch_stack
737 // NB: if anyone adds preemption, this block will need to be protected
738 ldl $1, TI_STATUS($8)
739 and $1, TS_SAVED_FP, $3
740 or $1, TS_SAVED_FP, $2
741 bne $3, 1f
742 stl $2, TI_STATUS($8)
743 bsr $26, __save_fpu
7441:
745 jsr $26, sys_\name
746 ldq $26, 56($sp)
747 lda $sp, SWITCH_STACK_SIZE($sp)
748 ret
749.end alpha_\name
750.endm
751
752fork_like fork
753fork_like vfork
754fork_like clone
755fork_like clone3
756
757.macro sigreturn_like name
758 .align 4
759 .globl sys_\name
760 .ent sys_\name
761sys_\name:
762 .prologue 0
763 mov $sp, $10
764 lda $sp, -SWITCH_STACK_SIZE($sp)
765 jsr $26, do_\name
7661: br $1, undo_switch_stack
767 br ret_from_sys_call
768.end sys_\name
769.endm
770
771sigreturn_like sigreturn
772sigreturn_like rt_sigreturn
773
774 .align 4
775 .globl alpha_syscall_zero
776 .ent alpha_syscall_zero
777alpha_syscall_zero:
778 .prologue 0
779 /* Special because it needs to do something opposite to
780 force_successful_syscall_return(). We use the saved
781 syscall number for that, zero meaning "not an error".
782 That works nicely, but for real syscall 0 we need to
783 make sure that this logics doesn't get confused.
784 Store a non-zero there - -ENOSYS we need in register
785 for our return value will do just fine.
786 */
787 lda $0, -ENOSYS
788 unop
789 stq $0, 0($sp)
790 ret
791.end alpha_syscall_zero