alpha: deal with multiple simultaneously pending signals
[linux-2.6.git] / arch / alpha / kernel / entry.S
1 /*
2  * arch/alpha/kernel/entry.S
3  *
4  * Kernel entry-points.
5  */
6
7 #include <asm/asm-offsets.h>
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
15
16 /* Stack offsets.  */
17 #define SP_OFF                  184
18 #define SWITCH_STACK_SIZE       320
19
20 /*
21  * This defines the normal kernel pt-regs layout.
22  *
23  * regs 9-15 preserved by C code
24  * regs 16-18 saved by PAL-code
25  * regs 29-30 saved and set up by PAL-code
26  * JRP - Save regs 16-18 in a special area of the stack, so that
27  * the palcode-provided values are available to the signal handler.
28  */
29
30 #define SAVE_ALL                        \
31         subq    $sp, SP_OFF, $sp;       \
32         stq     $0, 0($sp);             \
33         stq     $1, 8($sp);             \
34         stq     $2, 16($sp);            \
35         stq     $3, 24($sp);            \
36         stq     $4, 32($sp);            \
37         stq     $28, 144($sp);          \
38         lda     $2, alpha_mv;           \
39         stq     $5, 40($sp);            \
40         stq     $6, 48($sp);            \
41         stq     $7, 56($sp);            \
42         stq     $8, 64($sp);            \
43         stq     $19, 72($sp);           \
44         stq     $20, 80($sp);           \
45         stq     $21, 88($sp);           \
46         ldq     $2, HAE_CACHE($2);      \
47         stq     $22, 96($sp);           \
48         stq     $23, 104($sp);          \
49         stq     $24, 112($sp);          \
50         stq     $25, 120($sp);          \
51         stq     $26, 128($sp);          \
52         stq     $27, 136($sp);          \
53         stq     $2, 152($sp);           \
54         stq     $16, 160($sp);          \
55         stq     $17, 168($sp);          \
56         stq     $18, 176($sp)
57
58 #define RESTORE_ALL                     \
59         lda     $19, alpha_mv;          \
60         ldq     $0, 0($sp);             \
61         ldq     $1, 8($sp);             \
62         ldq     $2, 16($sp);            \
63         ldq     $3, 24($sp);            \
64         ldq     $21, 152($sp);          \
65         ldq     $20, HAE_CACHE($19);    \
66         ldq     $4, 32($sp);            \
67         ldq     $5, 40($sp);            \
68         ldq     $6, 48($sp);            \
69         ldq     $7, 56($sp);            \
70         subq    $20, $21, $20;          \
71         ldq     $8, 64($sp);            \
72         beq     $20, 99f;               \
73         ldq     $20, HAE_REG($19);      \
74         stq     $21, HAE_CACHE($19);    \
75         stq     $21, 0($20);            \
76         ldq     $0, 0($sp);             \
77         ldq     $1, 8($sp);             \
78 99:;                                    \
79         ldq     $19, 72($sp);           \
80         ldq     $20, 80($sp);           \
81         ldq     $21, 88($sp);           \
82         ldq     $22, 96($sp);           \
83         ldq     $23, 104($sp);          \
84         ldq     $24, 112($sp);          \
85         ldq     $25, 120($sp);          \
86         ldq     $26, 128($sp);          \
87         ldq     $27, 136($sp);          \
88         ldq     $28, 144($sp);          \
89         addq    $sp, SP_OFF, $sp
90
91 /*
92  * Non-syscall kernel entry points.
93  */
94
95         .align  4
96         .globl  entInt
97         .ent    entInt
98 entInt:
99         SAVE_ALL
100         lda     $8, 0x3fff
101         lda     $26, ret_from_sys_call
102         bic     $sp, $8, $8
103         mov     $sp, $19
104         jsr     $31, do_entInt
105 .end entInt
106
107         .align  4
108         .globl  entArith
109         .ent    entArith
110 entArith:
111         SAVE_ALL
112         lda     $8, 0x3fff
113         lda     $26, ret_from_sys_call
114         bic     $sp, $8, $8
115         mov     $sp, $18
116         jsr     $31, do_entArith
117 .end entArith
118
119         .align  4
120         .globl  entMM
121         .ent    entMM
122 entMM:
123         SAVE_ALL
124 /* save $9 - $15 so the inline exception code can manipulate them.  */
125         subq    $sp, 56, $sp
126         stq     $9, 0($sp)
127         stq     $10, 8($sp)
128         stq     $11, 16($sp)
129         stq     $12, 24($sp)
130         stq     $13, 32($sp)
131         stq     $14, 40($sp)
132         stq     $15, 48($sp)
133         addq    $sp, 56, $19
134 /* handle the fault */
135         lda     $8, 0x3fff
136         bic     $sp, $8, $8
137         jsr     $26, do_page_fault
138 /* reload the registers after the exception code played.  */
139         ldq     $9, 0($sp)
140         ldq     $10, 8($sp)
141         ldq     $11, 16($sp)
142         ldq     $12, 24($sp)
143         ldq     $13, 32($sp)
144         ldq     $14, 40($sp)
145         ldq     $15, 48($sp)
146         addq    $sp, 56, $sp
147 /* finish up the syscall as normal.  */
148         br      ret_from_sys_call
149 .end entMM
150
151         .align  4
152         .globl  entIF
153         .ent    entIF
154 entIF:
155         SAVE_ALL
156         lda     $8, 0x3fff
157         lda     $26, ret_from_sys_call
158         bic     $sp, $8, $8
159         mov     $sp, $17
160         jsr     $31, do_entIF
161 .end entIF
162
163         .align  4
164         .globl  entUna
165         .ent    entUna
166 entUna:
167         lda     $sp, -256($sp)
168         stq     $0, 0($sp)
169         ldq     $0, 256($sp)    /* get PS */
170         stq     $1, 8($sp)
171         stq     $2, 16($sp)
172         stq     $3, 24($sp)
173         and     $0, 8, $0               /* user mode? */
174         stq     $4, 32($sp)
175         bne     $0, entUnaUser  /* yup -> do user-level unaligned fault */
176         stq     $5, 40($sp)
177         stq     $6, 48($sp)
178         stq     $7, 56($sp)
179         stq     $8, 64($sp)
180         stq     $9, 72($sp)
181         stq     $10, 80($sp)
182         stq     $11, 88($sp)
183         stq     $12, 96($sp)
184         stq     $13, 104($sp)
185         stq     $14, 112($sp)
186         stq     $15, 120($sp)
187         /* 16-18 PAL-saved */
188         stq     $19, 152($sp)
189         stq     $20, 160($sp)
190         stq     $21, 168($sp)
191         stq     $22, 176($sp)
192         stq     $23, 184($sp)
193         stq     $24, 192($sp)
194         stq     $25, 200($sp)
195         stq     $26, 208($sp)
196         stq     $27, 216($sp)
197         stq     $28, 224($sp)
198         mov     $sp, $19
199         stq     $gp, 232($sp)
200         lda     $8, 0x3fff
201         stq     $31, 248($sp)
202         bic     $sp, $8, $8
203         jsr     $26, do_entUna
204         ldq     $0, 0($sp)
205         ldq     $1, 8($sp)
206         ldq     $2, 16($sp)
207         ldq     $3, 24($sp)
208         ldq     $4, 32($sp)
209         ldq     $5, 40($sp)
210         ldq     $6, 48($sp)
211         ldq     $7, 56($sp)
212         ldq     $8, 64($sp)
213         ldq     $9, 72($sp)
214         ldq     $10, 80($sp)
215         ldq     $11, 88($sp)
216         ldq     $12, 96($sp)
217         ldq     $13, 104($sp)
218         ldq     $14, 112($sp)
219         ldq     $15, 120($sp)
220         /* 16-18 PAL-saved */
221         ldq     $19, 152($sp)
222         ldq     $20, 160($sp)
223         ldq     $21, 168($sp)
224         ldq     $22, 176($sp)
225         ldq     $23, 184($sp)
226         ldq     $24, 192($sp)
227         ldq     $25, 200($sp)
228         ldq     $26, 208($sp)
229         ldq     $27, 216($sp)
230         ldq     $28, 224($sp)
231         ldq     $gp, 232($sp)
232         lda     $sp, 256($sp)
233         call_pal PAL_rti
234 .end entUna
235
236         .align  4
237         .ent    entUnaUser
238 entUnaUser:
239         ldq     $0, 0($sp)      /* restore original $0 */
240         lda     $sp, 256($sp)   /* pop entUna's stack frame */
241         SAVE_ALL                /* setup normal kernel stack */
242         lda     $sp, -56($sp)
243         stq     $9, 0($sp)
244         stq     $10, 8($sp)
245         stq     $11, 16($sp)
246         stq     $12, 24($sp)
247         stq     $13, 32($sp)
248         stq     $14, 40($sp)
249         stq     $15, 48($sp)
250         lda     $8, 0x3fff
251         addq    $sp, 56, $19
252         bic     $sp, $8, $8
253         jsr     $26, do_entUnaUser
254         ldq     $9, 0($sp)
255         ldq     $10, 8($sp)
256         ldq     $11, 16($sp)
257         ldq     $12, 24($sp)
258         ldq     $13, 32($sp)
259         ldq     $14, 40($sp)
260         ldq     $15, 48($sp)
261         lda     $sp, 56($sp)
262         br      ret_from_sys_call
263 .end entUnaUser
264
265         .align  4
266         .globl  entDbg
267         .ent    entDbg
268 entDbg:
269         SAVE_ALL
270         lda     $8, 0x3fff
271         lda     $26, ret_from_sys_call
272         bic     $sp, $8, $8
273         mov     $sp, $16
274         jsr     $31, do_entDbg
275 .end entDbg
276 \f
277 /*
278  * The system call entry point is special.  Most importantly, it looks
279  * like a function call to userspace as far as clobbered registers.  We
280  * do preserve the argument registers (for syscall restarts) and $26
281  * (for leaf syscall functions).
282  *
283  * So much for theory.  We don't take advantage of this yet.
284  *
285  * Note that a0-a2 are not saved by PALcode as with the other entry points.
286  */
287
288         .align  4
289         .globl  entSys
290         .globl  ret_from_sys_call
291         .ent    entSys
292 entSys:
293         SAVE_ALL
294         lda     $8, 0x3fff
295         bic     $sp, $8, $8
296         lda     $4, NR_SYSCALLS($31)
297         stq     $16, SP_OFF+24($sp)
298         lda     $5, sys_call_table
299         lda     $27, sys_ni_syscall
300         cmpult  $0, $4, $4
301         ldl     $3, TI_FLAGS($8)
302         stq     $17, SP_OFF+32($sp)
303         s8addq  $0, $5, $5
304         stq     $18, SP_OFF+40($sp)
305         blbs    $3, strace
306         beq     $4, 1f
307         ldq     $27, 0($5)
308 1:      jsr     $26, ($27), alpha_ni_syscall
309         ldgp    $gp, 0($26)
310         blt     $0, $syscall_error      /* the call failed */
311         stq     $0, 0($sp)
312         stq     $31, 72($sp)            /* a3=0 => no error */
313
314         .align  4
315 ret_from_sys_call:
316         cmovne  $26, 0, $19             /* $19 = 0 => non-restartable */
317         ldq     $0, SP_OFF($sp)
318         and     $0, 8, $0
319         beq     $0, restore_all
320 ret_to_user:
321         /* Make sure need_resched and sigpending don't change between
322                 sampling and the rti.  */
323         lda     $16, 7
324         call_pal PAL_swpipl
325         ldl     $5, TI_FLAGS($8)
326         and     $5, _TIF_WORK_MASK, $2
327         bne     $2, work_pending
328 restore_all:
329         RESTORE_ALL
330         call_pal PAL_rti
331
332         .align 3
333 $syscall_error:
334         /*
335          * Some system calls (e.g., ptrace) can return arbitrary
336          * values which might normally be mistaken as error numbers.
337          * Those functions must zero $0 (v0) directly in the stack
338          * frame to indicate that a negative return value wasn't an
339          * error number..
340          */
341         ldq     $19, 0($sp)     /* old syscall nr (zero if success) */
342         beq     $19, $ret_success
343
344         ldq     $20, 72($sp)    /* .. and this a3 */
345         subq    $31, $0, $0     /* with error in v0 */
346         addq    $31, 1, $1      /* set a3 for errno return */
347         stq     $0, 0($sp)
348         mov     $31, $26        /* tell "ret_from_sys_call" we can restart */
349         stq     $1, 72($sp)     /* a3 for return */
350         br      ret_from_sys_call
351
352 $ret_success:
353         stq     $0, 0($sp)
354         stq     $31, 72($sp)    /* a3=0 => no error */
355         br      ret_from_sys_call
356 .end entSys
357
358 /*
359  * Do all cleanup when returning from all interrupts and system calls.
360  *
361  * Arguments:
362  *       $5: TI_FLAGS.
363  *       $8: current.
364  *      $19: The old syscall number, or zero if this is not a return
365  *           from a syscall that errored and is possibly restartable.
366  *      $20: The old a3 value
367  */
368
369         .align  4
370         .ent    work_pending
371 work_pending:
372         and     $5, _TIF_NEED_RESCHED, $2
373         beq     $2, $work_notifysig
374
375 $work_resched:
376         subq    $sp, 16, $sp
377         stq     $19, 0($sp)              /* save syscall nr */
378         stq     $20, 8($sp)              /* and error indication (a3) */
379         jsr     $26, schedule
380         ldq     $19, 0($sp)
381         ldq     $20, 8($sp)
382         addq    $sp, 16, $sp
383         /* Make sure need_resched and sigpending don't change between
384                 sampling and the rti.  */
385         lda     $16, 7
386         call_pal PAL_swpipl
387         ldl     $5, TI_FLAGS($8)
388         and     $5, _TIF_WORK_MASK, $2
389         beq     $2, restore_all
390         and     $5, _TIF_NEED_RESCHED, $2
391         bne     $2, $work_resched
392
393 $work_notifysig:
394         mov     $sp, $16
395         bsr     $1, do_switch_stack
396         mov     $sp, $17
397         mov     $5, $18
398         mov     $19, $9         /* save old syscall number */
399         mov     $20, $10        /* save old a3 */
400         and     $5, _TIF_SIGPENDING, $2
401         cmovne  $2, 0, $9       /* we don't want double syscall restarts */
402         jsr     $26, do_notify_resume
403         mov     $9, $19
404         mov     $10, $20
405         bsr     $1, undo_switch_stack
406         br      ret_to_user
407 .end work_pending
408
409 /*
410  * PTRACE syscall handler
411  */
412
413         .align  4
414         .ent    strace
415 strace:
416         /* set up signal stack, call syscall_trace */
417         bsr     $1, do_switch_stack
418         jsr     $26, syscall_trace
419         bsr     $1, undo_switch_stack
420
421         /* get the system call number and the arguments back.. */
422         ldq     $0, 0($sp)
423         ldq     $16, SP_OFF+24($sp)
424         ldq     $17, SP_OFF+32($sp)
425         ldq     $18, SP_OFF+40($sp)
426         ldq     $19, 72($sp)
427         ldq     $20, 80($sp)
428         ldq     $21, 88($sp)
429
430         /* get the system call pointer.. */
431         lda     $1, NR_SYSCALLS($31)
432         lda     $2, sys_call_table
433         lda     $27, alpha_ni_syscall
434         cmpult  $0, $1, $1
435         s8addq  $0, $2, $2
436         beq     $1, 1f
437         ldq     $27, 0($2)
438 1:      jsr     $26, ($27), sys_gettimeofday
439 ret_from_straced:
440         ldgp    $gp, 0($26)
441
442         /* check return.. */
443         blt     $0, $strace_error       /* the call failed */
444         stq     $31, 72($sp)            /* a3=0 => no error */
445 $strace_success:
446         stq     $0, 0($sp)              /* save return value */
447
448         bsr     $1, do_switch_stack
449         jsr     $26, syscall_trace
450         bsr     $1, undo_switch_stack
451         br      $31, ret_from_sys_call
452
453         .align  3
454 $strace_error:
455         ldq     $19, 0($sp)     /* old syscall nr (zero if success) */
456         beq     $19, $strace_success
457         ldq     $20, 72($sp)    /* .. and this a3 */
458
459         subq    $31, $0, $0     /* with error in v0 */
460         addq    $31, 1, $1      /* set a3 for errno return */
461         stq     $0, 0($sp)
462         stq     $1, 72($sp)     /* a3 for return */
463
464         bsr     $1, do_switch_stack
465         mov     $19, $9         /* save old syscall number */
466         mov     $20, $10        /* save old a3 */
467         jsr     $26, syscall_trace
468         mov     $9, $19
469         mov     $10, $20
470         bsr     $1, undo_switch_stack
471
472         mov     $31, $26        /* tell "ret_from_sys_call" we can restart */
473         br      ret_from_sys_call
474 .end strace
475 \f
476 /*
477  * Save and restore the switch stack -- aka the balance of the user context.
478  */
479
480         .align  4
481         .ent    do_switch_stack
482 do_switch_stack:
483         lda     $sp, -SWITCH_STACK_SIZE($sp)
484         stq     $9, 0($sp)
485         stq     $10, 8($sp)
486         stq     $11, 16($sp)
487         stq     $12, 24($sp)
488         stq     $13, 32($sp)
489         stq     $14, 40($sp)
490         stq     $15, 48($sp)
491         stq     $26, 56($sp)
492         stt     $f0, 64($sp)
493         stt     $f1, 72($sp)
494         stt     $f2, 80($sp)
495         stt     $f3, 88($sp)
496         stt     $f4, 96($sp)
497         stt     $f5, 104($sp)
498         stt     $f6, 112($sp)
499         stt     $f7, 120($sp)
500         stt     $f8, 128($sp)
501         stt     $f9, 136($sp)
502         stt     $f10, 144($sp)
503         stt     $f11, 152($sp)
504         stt     $f12, 160($sp)
505         stt     $f13, 168($sp)
506         stt     $f14, 176($sp)
507         stt     $f15, 184($sp)
508         stt     $f16, 192($sp)
509         stt     $f17, 200($sp)
510         stt     $f18, 208($sp)
511         stt     $f19, 216($sp)
512         stt     $f20, 224($sp)
513         stt     $f21, 232($sp)
514         stt     $f22, 240($sp)
515         stt     $f23, 248($sp)
516         stt     $f24, 256($sp)
517         stt     $f25, 264($sp)
518         stt     $f26, 272($sp)
519         stt     $f27, 280($sp)
520         mf_fpcr $f0             # get fpcr
521         stt     $f28, 288($sp)
522         stt     $f29, 296($sp)
523         stt     $f30, 304($sp)
524         stt     $f0, 312($sp)   # save fpcr in slot of $f31
525         ldt     $f0, 64($sp)    # dont let "do_switch_stack" change fp state.
526         ret     $31, ($1), 1
527 .end do_switch_stack
528
529         .align  4
530         .ent    undo_switch_stack
531 undo_switch_stack:
532         ldq     $9, 0($sp)
533         ldq     $10, 8($sp)
534         ldq     $11, 16($sp)
535         ldq     $12, 24($sp)
536         ldq     $13, 32($sp)
537         ldq     $14, 40($sp)
538         ldq     $15, 48($sp)
539         ldq     $26, 56($sp)
540         ldt     $f30, 312($sp)  # get saved fpcr
541         ldt     $f0, 64($sp)
542         ldt     $f1, 72($sp)
543         ldt     $f2, 80($sp)
544         ldt     $f3, 88($sp)
545         mt_fpcr $f30            # install saved fpcr
546         ldt     $f4, 96($sp)
547         ldt     $f5, 104($sp)
548         ldt     $f6, 112($sp)
549         ldt     $f7, 120($sp)
550         ldt     $f8, 128($sp)
551         ldt     $f9, 136($sp)
552         ldt     $f10, 144($sp)
553         ldt     $f11, 152($sp)
554         ldt     $f12, 160($sp)
555         ldt     $f13, 168($sp)
556         ldt     $f14, 176($sp)
557         ldt     $f15, 184($sp)
558         ldt     $f16, 192($sp)
559         ldt     $f17, 200($sp)
560         ldt     $f18, 208($sp)
561         ldt     $f19, 216($sp)
562         ldt     $f20, 224($sp)
563         ldt     $f21, 232($sp)
564         ldt     $f22, 240($sp)
565         ldt     $f23, 248($sp)
566         ldt     $f24, 256($sp)
567         ldt     $f25, 264($sp)
568         ldt     $f26, 272($sp)
569         ldt     $f27, 280($sp)
570         ldt     $f28, 288($sp)
571         ldt     $f29, 296($sp)
572         ldt     $f30, 304($sp)
573         lda     $sp, SWITCH_STACK_SIZE($sp)
574         ret     $31, ($1), 1
575 .end undo_switch_stack
576 \f
577 /*
578  * The meat of the context switch code.
579  */
580
581         .align  4
582         .globl  alpha_switch_to
583         .ent    alpha_switch_to
584 alpha_switch_to:
585         .prologue 0
586         bsr     $1, do_switch_stack
587         call_pal PAL_swpctx
588         lda     $8, 0x3fff
589         bsr     $1, undo_switch_stack
590         bic     $sp, $8, $8
591         mov     $17, $0
592         ret
593 .end alpha_switch_to
594
595 /*
596  * New processes begin life here.
597  */
598
599         .globl  ret_from_fork
600         .align  4
601         .ent    ret_from_fork
602 ret_from_fork:
603         lda     $26, ret_from_sys_call
604         mov     $17, $16
605         jmp     $31, schedule_tail
606 .end ret_from_fork
607
608 /*
609  * kernel_thread(fn, arg, clone_flags)
610  */
611         .align 4
612         .globl  kernel_thread
613         .ent    kernel_thread
614 kernel_thread:
615         /* We can be called from a module.  */
616         ldgp    $gp, 0($27)
617         .prologue 1
618         subq    $sp, SP_OFF+6*8, $sp
619         br      $1, 2f          /* load start address */
620
621         /* We've now "returned" from a fake system call.  */
622         unop
623         blt     $0, 1f          /* error?  */
624         ldi     $1, 0x3fff
625         beq     $20, 1f         /* parent or child?  */
626
627         bic     $sp, $1, $8     /* in child.  */
628         jsr     $26, ($27)
629         ldgp    $gp, 0($26)
630         mov     $0, $16
631         mov     $31, $26
632         jmp     $31, sys_exit
633
634 1:      ret                     /* in parent.  */
635
636         .align 4
637 2:      /* Fake a system call stack frame, as we can't do system calls
638            from kernel space.  Note that we store FN and ARG as they
639            need to be set up in the child for the call.  Also store $8
640            and $26 for use in the parent.  */
641         stq     $31, SP_OFF($sp)        /* ps */
642         stq     $1, SP_OFF+8($sp)       /* pc */
643         stq     $gp, SP_OFF+16($sp)     /* gp */
644         stq     $16, 136($sp)           /* $27; FN for child */
645         stq     $17, SP_OFF+24($sp)     /* $16; ARG for child */
646         stq     $8, 64($sp)             /* $8 */
647         stq     $26, 128($sp)           /* $26 */
648         /* Avoid the HAE being gratuitously wrong, to avoid restoring it.  */
649         ldq     $2, alpha_mv+HAE_CACHE
650         stq     $2, 152($sp)            /* HAE */
651
652         /* Shuffle FLAGS to the front; add CLONE_VM.  */
653         ldi     $1, CLONE_VM|CLONE_UNTRACED
654         or      $18, $1, $16
655         bsr     $26, sys_clone
656
657         /* We don't actually care for a3 success widgetry in the kernel.
658            Not for positive errno values.  */
659         stq     $0, 0($sp)              /* $0 */
660         br      restore_all
661 .end kernel_thread
662
663 /*
664  * kernel_execve(path, argv, envp)
665  */
666         .align  4
667         .globl  kernel_execve
668         .ent    kernel_execve
669 kernel_execve:
670         /* We can be called from a module.  */
671         ldgp    $gp, 0($27)
672         lda     $sp, -(32+SIZEOF_PT_REGS+8)($sp)
673         .frame  $sp, 32+SIZEOF_PT_REGS+8, $26, 0
674         stq     $26, 0($sp)
675         stq     $16, 8($sp)
676         stq     $17, 16($sp)
677         stq     $18, 24($sp)
678         .prologue 1
679
680         lda     $16, 32($sp)
681         lda     $17, 0
682         lda     $18, SIZEOF_PT_REGS
683         bsr     $26, memset             !samegp
684
685         /* Avoid the HAE being gratuitously wrong, which would cause us
686            to do the whole turn off interrupts thing and restore it.  */
687         ldq     $2, alpha_mv+HAE_CACHE
688         stq     $2, 152+32($sp)
689
690         ldq     $16, 8($sp)
691         ldq     $17, 16($sp)
692         ldq     $18, 24($sp)
693         lda     $19, 32($sp)
694         bsr     $26, do_execve          !samegp
695
696         ldq     $26, 0($sp)
697         bne     $0, 1f                  /* error! */
698
699         /* Move the temporary pt_regs struct from its current location
700            to the top of the kernel stack frame.  See copy_thread for
701            details for a normal process.  */
702         lda     $16, 0x4000 - SIZEOF_PT_REGS($8)
703         lda     $17, 32($sp)
704         lda     $18, SIZEOF_PT_REGS
705         bsr     $26, memmove            !samegp
706
707         /* Take that over as our new stack frame and visit userland!  */
708         lda     $sp, 0x4000 - SIZEOF_PT_REGS($8)
709         br      $31, ret_from_sys_call
710
711 1:      lda     $sp, 32+SIZEOF_PT_REGS+8($sp)
712         ret
713 .end kernel_execve
714
715 \f
716 /*
717  * Special system calls.  Most of these are special in that they either
718  * have to play switch_stack games or in some way use the pt_regs struct.
719  */
720         .align  4
721         .globl  sys_fork
722         .ent    sys_fork
723 sys_fork:
724         .prologue 0
725         mov     $sp, $21
726         bsr     $1, do_switch_stack
727         bis     $31, SIGCHLD, $16
728         mov     $31, $17
729         mov     $31, $18
730         mov     $31, $19
731         mov     $31, $20
732         jsr     $26, alpha_clone
733         bsr     $1, undo_switch_stack
734         ret
735 .end sys_fork
736
737         .align  4
738         .globl  sys_clone
739         .ent    sys_clone
740 sys_clone:
741         .prologue 0
742         mov     $sp, $21
743         bsr     $1, do_switch_stack
744         /* $16, $17, $18, $19, $20 come from the user.  */
745         jsr     $26, alpha_clone
746         bsr     $1, undo_switch_stack
747         ret
748 .end sys_clone
749
750         .align  4
751         .globl  sys_vfork
752         .ent    sys_vfork
753 sys_vfork:
754         .prologue 0
755         mov     $sp, $16
756         bsr     $1, do_switch_stack
757         jsr     $26, alpha_vfork
758         bsr     $1, undo_switch_stack
759         ret
760 .end sys_vfork
761
762         .align  4
763         .globl  sys_sigreturn
764         .ent    sys_sigreturn
765 sys_sigreturn:
766         .prologue 0
767         lda     $9, ret_from_straced
768         cmpult  $26, $9, $9
769         mov     $sp, $17
770         lda     $18, -SWITCH_STACK_SIZE($sp)
771         lda     $sp, -SWITCH_STACK_SIZE($sp)
772         jsr     $26, do_sigreturn
773         bne     $9, 1f
774         jsr     $26, syscall_trace
775 1:      br      $1, undo_switch_stack
776         br      ret_from_sys_call
777 .end sys_sigreturn
778
779         .align  4
780         .globl  sys_rt_sigreturn
781         .ent    sys_rt_sigreturn
782 sys_rt_sigreturn:
783         .prologue 0
784         lda     $9, ret_from_straced
785         cmpult  $26, $9, $9
786         mov     $sp, $17
787         lda     $18, -SWITCH_STACK_SIZE($sp)
788         lda     $sp, -SWITCH_STACK_SIZE($sp)
789         jsr     $26, do_rt_sigreturn
790         bne     $9, 1f
791         jsr     $26, syscall_trace
792 1:      br      $1, undo_switch_stack
793         br      ret_from_sys_call
794 .end sys_rt_sigreturn
795
796         .align  4
797         .globl  sys_sethae
798         .ent    sys_sethae
799 sys_sethae:
800         .prologue 0
801         stq     $16, 152($sp)
802         ret
803 .end sys_sethae
804
805         .align  4
806         .globl  osf_getpriority
807         .ent    osf_getpriority
808 osf_getpriority:
809         lda     $sp, -16($sp)
810         stq     $26, 0($sp)
811         .prologue 0
812
813         jsr     $26, sys_getpriority
814
815         ldq     $26, 0($sp)
816         blt     $0, 1f
817
818         /* Return value is the unbiased priority, i.e. 20 - prio.
819            This does result in negative return values, so signal
820            no error by writing into the R0 slot.  */
821         lda     $1, 20
822         stq     $31, 16($sp)
823         subl    $1, $0, $0
824         unop
825
826 1:      lda     $sp, 16($sp)
827         ret
828 .end osf_getpriority
829
830         .align  4
831         .globl  sys_getxuid
832         .ent    sys_getxuid
833 sys_getxuid:
834         .prologue 0
835         ldq     $2, TI_TASK($8)
836         ldq     $3, TASK_CRED($2)
837         ldl     $0, CRED_UID($3)
838         ldl     $1, CRED_EUID($3)
839         stq     $1, 80($sp)
840         ret
841 .end sys_getxuid
842
843         .align  4
844         .globl  sys_getxgid
845         .ent    sys_getxgid
846 sys_getxgid:
847         .prologue 0
848         ldq     $2, TI_TASK($8)
849         ldq     $3, TASK_CRED($2)
850         ldl     $0, CRED_GID($3)
851         ldl     $1, CRED_EGID($3)
852         stq     $1, 80($sp)
853         ret
854 .end sys_getxgid
855
856         .align  4
857         .globl  sys_getxpid
858         .ent    sys_getxpid
859 sys_getxpid:
860         .prologue 0
861         ldq     $2, TI_TASK($8)
862
863         /* See linux/kernel/timer.c sys_getppid for discussion
864            about this loop.  */
865         ldq     $3, TASK_GROUP_LEADER($2)
866         ldq     $4, TASK_REAL_PARENT($3)
867         ldl     $0, TASK_TGID($2)
868 1:      ldl     $1, TASK_TGID($4)
869 #ifdef CONFIG_SMP
870         mov     $4, $5
871         mb
872         ldq     $3, TASK_GROUP_LEADER($2)
873         ldq     $4, TASK_REAL_PARENT($3)
874         cmpeq   $4, $5, $5
875         beq     $5, 1b
876 #endif
877         stq     $1, 80($sp)
878         ret
879 .end sys_getxpid
880
881         .align  4
882         .globl  sys_alpha_pipe
883         .ent    sys_alpha_pipe
884 sys_alpha_pipe:
885         lda     $sp, -16($sp)
886         stq     $26, 0($sp)
887         .prologue 0
888
889         mov     $31, $17
890         lda     $16, 8($sp)
891         jsr     $26, do_pipe_flags
892
893         ldq     $26, 0($sp)
894         bne     $0, 1f
895
896         /* The return values are in $0 and $20.  */
897         ldl     $1, 12($sp)
898         ldl     $0, 8($sp)
899
900         stq     $1, 80+16($sp)
901 1:      lda     $sp, 16($sp)
902         ret
903 .end sys_alpha_pipe
904
905         .align  4
906         .globl  sys_execve
907         .ent    sys_execve
908 sys_execve:
909         .prologue 0
910         mov     $sp, $19
911         jmp     $31, do_sys_execve
912 .end sys_execve
913
914         .align  4
915         .globl  osf_sigprocmask
916         .ent    osf_sigprocmask
917 osf_sigprocmask:
918         .prologue 0
919         mov     $sp, $18
920         jmp     $31, sys_osf_sigprocmask
921 .end osf_sigprocmask
922
923         .align  4
924         .globl  alpha_ni_syscall
925         .ent    alpha_ni_syscall
926 alpha_ni_syscall:
927         .prologue 0
928         /* Special because it also implements overflow handling via
929            syscall number 0.  And if you recall, zero is a special
930            trigger for "not an error".  Store large non-zero there.  */
931         lda     $0, -ENOSYS
932         unop
933         stq     $0, 0($sp)
934         ret
935 .end alpha_ni_syscall