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