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);		\
7899:;					\
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
98entInt:
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
110entArith:
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
122entMM:
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
154entIF:
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
166entUna:
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
238entUnaUser:
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
268entDbg:
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
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
292entSys:
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)
3081:	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
315ret_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
320ret_from_reschedule:
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	$5, work_pending
328restore_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: Error indication.
367 */
368
369	.align	4
370	.ent	work_pending
371work_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	br	$1, do_switch_stack
396	mov	$sp, $17
397	mov	$5, $18
398	jsr	$26, do_notify_resume
399	bsr	$1, undo_switch_stack
400	br	restore_all
401.end work_pending
402
403/*
404 * PTRACE syscall handler
405 */
406
407	.align	4
408	.ent	strace
409strace:
410	/* set up signal stack, call syscall_trace */
411	bsr	$1, do_switch_stack
412	jsr	$26, syscall_trace
413	bsr	$1, undo_switch_stack
414
415	/* get the system call number and the arguments back.. */
416	ldq	$0, 0($sp)
417	ldq	$16, SP_OFF+24($sp)
418	ldq	$17, SP_OFF+32($sp)
419	ldq	$18, SP_OFF+40($sp)
420	ldq	$19, 72($sp)
421	ldq	$20, 80($sp)
422	ldq	$21, 88($sp)
423
424	/* get the system call pointer.. */
425	lda	$1, NR_SYSCALLS($31)
426	lda	$2, sys_call_table
427	lda	$27, alpha_ni_syscall
428	cmpult	$0, $1, $1
429	s8addq	$0, $2, $2
430	beq	$1, 1f
431	ldq	$27, 0($2)
4321:	jsr	$26, ($27), sys_gettimeofday
433	ldgp	$gp, 0($26)
434
435	/* check return.. */
436	blt	$0, $strace_error	/* the call failed */
437	stq	$31, 72($sp)		/* a3=0 => no error */
438$strace_success:
439	stq	$0, 0($sp)		/* save return value */
440
441	bsr	$1, do_switch_stack
442	jsr	$26, syscall_trace
443	bsr	$1, undo_switch_stack
444	br	$31, ret_from_sys_call
445
446	.align	3
447$strace_error:
448	ldq	$19, 0($sp)	/* old syscall nr (zero if success) */
449	beq	$19, $strace_success
450	ldq	$20, 72($sp)	/* .. and this a3 */
451
452	subq	$31, $0, $0	/* with error in v0 */
453	addq	$31, 1, $1	/* set a3 for errno return */
454	stq	$0, 0($sp)
455	stq	$1, 72($sp)	/* a3 for return */
456
457	bsr	$1, do_switch_stack
458	mov	$19, $9		/* save old syscall number */
459	mov	$20, $10	/* save old a3 */
460	jsr	$26, syscall_trace
461	mov	$9, $19
462	mov	$10, $20
463	bsr	$1, undo_switch_stack
464
465	mov	$31, $26	/* tell "ret_from_sys_call" we can restart */
466	br	ret_from_sys_call
467.end strace
468
469/*
470 * Save and restore the switch stack -- aka the balance of the user context.
471 */
472
473	.align	4
474	.ent	do_switch_stack
475do_switch_stack:
476	lda	$sp, -SWITCH_STACK_SIZE($sp)
477	stq	$9, 0($sp)
478	stq	$10, 8($sp)
479	stq	$11, 16($sp)
480	stq	$12, 24($sp)
481	stq	$13, 32($sp)
482	stq	$14, 40($sp)
483	stq	$15, 48($sp)
484	stq	$26, 56($sp)
485	stt	$f0, 64($sp)
486	stt	$f1, 72($sp)
487	stt	$f2, 80($sp)
488	stt	$f3, 88($sp)
489	stt	$f4, 96($sp)
490	stt	$f5, 104($sp)
491	stt	$f6, 112($sp)
492	stt	$f7, 120($sp)
493	stt	$f8, 128($sp)
494	stt	$f9, 136($sp)
495	stt	$f10, 144($sp)
496	stt	$f11, 152($sp)
497	stt	$f12, 160($sp)
498	stt	$f13, 168($sp)
499	stt	$f14, 176($sp)
500	stt	$f15, 184($sp)
501	stt	$f16, 192($sp)
502	stt	$f17, 200($sp)
503	stt	$f18, 208($sp)
504	stt	$f19, 216($sp)
505	stt	$f20, 224($sp)
506	stt	$f21, 232($sp)
507	stt	$f22, 240($sp)
508	stt	$f23, 248($sp)
509	stt	$f24, 256($sp)
510	stt	$f25, 264($sp)
511	stt	$f26, 272($sp)
512	stt	$f27, 280($sp)
513	mf_fpcr	$f0		# get fpcr
514	stt	$f28, 288($sp)
515	stt	$f29, 296($sp)
516	stt	$f30, 304($sp)
517	stt	$f0, 312($sp)	# save fpcr in slot of $f31
518	ldt	$f0, 64($sp)	# dont let "do_switch_stack" change fp state.
519	ret	$31, ($1), 1
520.end do_switch_stack
521
522	.align	4
523	.ent	undo_switch_stack
524undo_switch_stack:
525	ldq	$9, 0($sp)
526	ldq	$10, 8($sp)
527	ldq	$11, 16($sp)
528	ldq	$12, 24($sp)
529	ldq	$13, 32($sp)
530	ldq	$14, 40($sp)
531	ldq	$15, 48($sp)
532	ldq	$26, 56($sp)
533	ldt	$f30, 312($sp)	# get saved fpcr
534	ldt	$f0, 64($sp)
535	ldt	$f1, 72($sp)
536	ldt	$f2, 80($sp)
537	ldt	$f3, 88($sp)
538	mt_fpcr	$f30		# install saved fpcr
539	ldt	$f4, 96($sp)
540	ldt	$f5, 104($sp)
541	ldt	$f6, 112($sp)
542	ldt	$f7, 120($sp)
543	ldt	$f8, 128($sp)
544	ldt	$f9, 136($sp)
545	ldt	$f10, 144($sp)
546	ldt	$f11, 152($sp)
547	ldt	$f12, 160($sp)
548	ldt	$f13, 168($sp)
549	ldt	$f14, 176($sp)
550	ldt	$f15, 184($sp)
551	ldt	$f16, 192($sp)
552	ldt	$f17, 200($sp)
553	ldt	$f18, 208($sp)
554	ldt	$f19, 216($sp)
555	ldt	$f20, 224($sp)
556	ldt	$f21, 232($sp)
557	ldt	$f22, 240($sp)
558	ldt	$f23, 248($sp)
559	ldt	$f24, 256($sp)
560	ldt	$f25, 264($sp)
561	ldt	$f26, 272($sp)
562	ldt	$f27, 280($sp)
563	ldt	$f28, 288($sp)
564	ldt	$f29, 296($sp)
565	ldt	$f30, 304($sp)
566	lda	$sp, SWITCH_STACK_SIZE($sp)
567	ret	$31, ($1), 1
568.end undo_switch_stack
569
570/*
571 * The meat of the context switch code.
572 */
573
574	.align	4
575	.globl	alpha_switch_to
576	.ent	alpha_switch_to
577alpha_switch_to:
578	.prologue 0
579	bsr	$1, do_switch_stack
580	call_pal PAL_swpctx
581	lda	$8, 0x3fff
582	bsr	$1, undo_switch_stack
583	bic	$sp, $8, $8
584	mov	$17, $0
585	ret
586.end alpha_switch_to
587
588/*
589 * New processes begin life here.
590 */
591
592	.globl	ret_from_fork
593	.align	4
594	.ent	ret_from_fork
595ret_from_fork:
596	lda	$26, ret_from_sys_call
597	mov	$17, $16
598	jmp	$31, schedule_tail
599.end ret_from_fork
600
601/*
602 * kernel_thread(fn, arg, clone_flags)
603 */
604	.align 4
605	.globl	kernel_thread
606	.ent	kernel_thread
607kernel_thread:
608	/* We can be called from a module.  */
609	ldgp	$gp, 0($27)
610	.prologue 1
611	subq	$sp, SP_OFF+6*8, $sp
612	br	$1, 2f		/* load start address */
613
614	/* We've now "returned" from a fake system call.  */
615	unop
616	blt	$0, 1f		/* error?  */
617	ldi	$1, 0x3fff
618	beq	$20, 1f		/* parent or child?  */
619
620	bic	$sp, $1, $8	/* in child.  */
621	jsr	$26, ($27)
622	ldgp	$gp, 0($26)
623	mov	$0, $16
624	mov	$31, $26
625	jmp	$31, sys_exit
626
6271:	ret			/* in parent.  */
628
629	.align 4
6302:	/* Fake a system call stack frame, as we can't do system calls
631	   from kernel space.  Note that we store FN and ARG as they
632	   need to be set up in the child for the call.  Also store $8
633	   and $26 for use in the parent.  */
634	stq	$31, SP_OFF($sp)	/* ps */
635	stq	$1, SP_OFF+8($sp)	/* pc */
636	stq	$gp, SP_OFF+16($sp)	/* gp */
637	stq	$16, 136($sp)		/* $27; FN for child */
638	stq	$17, SP_OFF+24($sp)	/* $16; ARG for child */
639	stq	$8, 64($sp)		/* $8 */
640	stq	$26, 128($sp)		/* $26 */
641	/* Avoid the HAE being gratuitously wrong, to avoid restoring it.  */
642	ldq	$2, alpha_mv+HAE_CACHE
643	stq	$2, 152($sp)		/* HAE */
644
645	/* Shuffle FLAGS to the front; add CLONE_VM.  */
646	ldi	$1, CLONE_VM|CLONE_UNTRACED
647	or	$18, $1, $16
648	bsr	$26, sys_clone
649
650	/* We don't actually care for a3 success widgetry in the kernel.
651	   Not for positive errno values.  */
652	stq	$0, 0($sp)		/* $0 */
653	br	restore_all
654.end kernel_thread
655
656/*
657 * kernel_execve(path, argv, envp)
658 */
659	.align	4
660	.globl	kernel_execve
661	.ent	kernel_execve
662kernel_execve:
663	/* We can be called from a module.  */
664	ldgp	$gp, 0($27)
665	lda	$sp, -(32+SIZEOF_PT_REGS+8)($sp)
666	.frame	$sp, 32+SIZEOF_PT_REGS+8, $26, 0
667	stq	$26, 0($sp)
668	stq	$16, 8($sp)
669	stq	$17, 16($sp)
670	stq	$18, 24($sp)
671	.prologue 1
672
673	lda	$16, 32($sp)
674	lda	$17, 0
675	lda	$18, SIZEOF_PT_REGS
676	bsr	$26, memset		!samegp
677
678	/* Avoid the HAE being gratuitously wrong, which would cause us
679	   to do the whole turn off interrupts thing and restore it.  */
680	ldq	$2, alpha_mv+HAE_CACHE
681	stq	$2, 152+32($sp)
682
683	ldq	$16, 8($sp)
684	ldq	$17, 16($sp)
685	ldq	$18, 24($sp)
686	lda	$19, 32($sp)
687	bsr	$26, do_execve		!samegp
688
689	ldq	$26, 0($sp)
690	bne	$0, 1f			/* error! */
691
692	/* Move the temporary pt_regs struct from its current location
693	   to the top of the kernel stack frame.  See copy_thread for
694	   details for a normal process.  */
695	lda	$16, 0x4000 - SIZEOF_PT_REGS($8)
696	lda	$17, 32($sp)
697	lda	$18, SIZEOF_PT_REGS
698	bsr	$26, memmove		!samegp
699
700	/* Take that over as our new stack frame and visit userland!  */
701	lda	$sp, 0x4000 - SIZEOF_PT_REGS($8)
702	br	$31, ret_from_sys_call
703
7041:	lda	$sp, 32+SIZEOF_PT_REGS+8($sp)
705	ret
706.end kernel_execve
707
708
709/*
710 * Special system calls.  Most of these are special in that they either
711 * have to play switch_stack games or in some way use the pt_regs struct.
712 */
713	.align	4
714	.globl	sys_fork
715	.ent	sys_fork
716sys_fork:
717	.prologue 0
718	mov	$sp, $21
719	bsr	$1, do_switch_stack
720	bis	$31, SIGCHLD, $16
721	mov	$31, $17
722	mov	$31, $18
723	mov	$31, $19
724	mov	$31, $20
725	jsr	$26, alpha_clone
726	bsr	$1, undo_switch_stack
727	ret
728.end sys_fork
729
730	.align	4
731	.globl	sys_clone
732	.ent	sys_clone
733sys_clone:
734	.prologue 0
735	mov	$sp, $21
736	bsr	$1, do_switch_stack
737	/* $16, $17, $18, $19, $20 come from the user.  */
738	jsr	$26, alpha_clone
739	bsr	$1, undo_switch_stack
740	ret
741.end sys_clone
742
743	.align	4
744	.globl	sys_vfork
745	.ent	sys_vfork
746sys_vfork:
747	.prologue 0
748	mov	$sp, $16
749	bsr	$1, do_switch_stack
750	jsr	$26, alpha_vfork
751	bsr	$1, undo_switch_stack
752	ret
753.end sys_vfork
754
755	.align	4
756	.globl	sys_sigreturn
757	.ent	sys_sigreturn
758sys_sigreturn:
759	.prologue 0
760	mov	$sp, $17
761	lda	$18, -SWITCH_STACK_SIZE($sp)
762	lda	$sp, -SWITCH_STACK_SIZE($sp)
763	jsr	$26, do_sigreturn
764	br	$1, undo_switch_stack
765	br	ret_from_sys_call
766.end sys_sigreturn
767
768	.align	4
769	.globl	sys_rt_sigreturn
770	.ent	sys_rt_sigreturn
771sys_rt_sigreturn:
772	.prologue 0
773	mov	$sp, $17
774	lda	$18, -SWITCH_STACK_SIZE($sp)
775	lda	$sp, -SWITCH_STACK_SIZE($sp)
776	jsr	$26, do_rt_sigreturn
777	br	$1, undo_switch_stack
778	br	ret_from_sys_call
779.end sys_rt_sigreturn
780
781	.align	4
782	.globl	sys_sigsuspend
783	.ent	sys_sigsuspend
784sys_sigsuspend:
785	.prologue 0
786	mov	$sp, $17
787	br	$1, do_switch_stack
788	mov	$sp, $18
789	subq	$sp, 16, $sp
790	stq	$26, 0($sp)
791	jsr	$26, do_sigsuspend
792	ldq	$26, 0($sp)
793	lda	$sp, SWITCH_STACK_SIZE+16($sp)
794	ret
795.end sys_sigsuspend
796
797	.align	4
798	.globl	sys_rt_sigsuspend
799	.ent	sys_rt_sigsuspend
800sys_rt_sigsuspend:
801	.prologue 0
802	mov	$sp, $18
803	br	$1, do_switch_stack
804	mov	$sp, $19
805	subq	$sp, 16, $sp
806	stq	$26, 0($sp)
807	jsr	$26, do_rt_sigsuspend
808	ldq	$26, 0($sp)
809	lda	$sp, SWITCH_STACK_SIZE+16($sp)
810	ret
811.end sys_rt_sigsuspend
812
813	.align	4
814	.globl	sys_sethae
815	.ent	sys_sethae
816sys_sethae:
817	.prologue 0
818	stq	$16, 152($sp)
819	ret
820.end sys_sethae
821
822	.align	4
823	.globl	osf_getpriority
824	.ent	osf_getpriority
825osf_getpriority:
826	lda	$sp, -16($sp)
827	stq	$26, 0($sp)
828	.prologue 0
829
830	jsr	$26, sys_getpriority
831
832	ldq	$26, 0($sp)
833	blt	$0, 1f
834
835	/* Return value is the unbiased priority, i.e. 20 - prio.
836	   This does result in negative return values, so signal
837	   no error by writing into the R0 slot.  */
838	lda	$1, 20
839	stq	$31, 16($sp)
840	subl	$1, $0, $0
841	unop
842
8431:	lda	$sp, 16($sp)
844	ret
845.end osf_getpriority
846
847	.align	4
848	.globl	sys_getxuid
849	.ent	sys_getxuid
850sys_getxuid:
851	.prologue 0
852	ldq	$2, TI_TASK($8)
853	ldl	$0, TASK_UID($2)
854	ldl	$1, TASK_EUID($2)
855	stq	$1, 80($sp)
856	ret
857.end sys_getxuid
858
859	.align	4
860	.globl	sys_getxgid
861	.ent	sys_getxgid
862sys_getxgid:
863	.prologue 0
864	ldq	$2, TI_TASK($8)
865	ldl	$0, TASK_GID($2)
866	ldl	$1, TASK_EGID($2)
867	stq	$1, 80($sp)
868	ret
869.end sys_getxgid
870
871	.align	4
872	.globl	sys_getxpid
873	.ent	sys_getxpid
874sys_getxpid:
875	.prologue 0
876	ldq	$2, TI_TASK($8)
877
878	/* See linux/kernel/timer.c sys_getppid for discussion
879	   about this loop.  */
880	ldq	$3, TASK_GROUP_LEADER($2)
881	ldq	$4, TASK_REAL_PARENT($3)
882	ldl	$0, TASK_TGID($2)
8831:	ldl	$1, TASK_TGID($4)
884#ifdef CONFIG_SMP
885	mov	$4, $5
886	mb
887	ldq	$3, TASK_GROUP_LEADER($2)
888	ldq	$4, TASK_REAL_PARENT($3)
889	cmpeq	$4, $5, $5
890	beq	$5, 1b
891#endif
892	stq	$1, 80($sp)
893	ret
894.end sys_getxpid
895
896	.align	4
897	.globl	sys_pipe
898	.ent	sys_pipe
899sys_pipe:
900	lda	$sp, -16($sp)
901	stq	$26, 0($sp)
902	.prologue 0
903
904	lda	$16, 8($sp)
905	jsr	$26, do_pipe
906
907	ldq	$26, 0($sp)
908	bne	$0, 1f
909
910	/* The return values are in $0 and $20.  */
911	ldl	$1, 12($sp)
912	ldl	$0, 8($sp)
913
914	stq	$1, 80+16($sp)
9151:	lda	$sp, 16($sp)
916	ret
917.end sys_pipe
918
919	.align	4
920	.globl	sys_ptrace
921	.ent	sys_ptrace
922sys_ptrace:
923	.prologue 0
924	mov	$sp, $20
925	jmp	$31, do_sys_ptrace
926.end sys_ptrace
927
928	.align	4
929	.globl	sys_execve
930	.ent	sys_execve
931sys_execve:
932	.prologue 0
933	mov	$sp, $19
934	jmp	$31, do_sys_execve
935.end sys_execve
936
937	.align	4
938	.globl	osf_sigprocmask
939	.ent	osf_sigprocmask
940osf_sigprocmask:
941	.prologue 0
942	mov	$sp, $18
943	jmp	$31, do_osf_sigprocmask
944.end osf_sigprocmask
945
946	.align	4
947	.globl	alpha_ni_syscall
948	.ent	alpha_ni_syscall
949alpha_ni_syscall:
950	.prologue 0
951	/* Special because it also implements overflow handling via
952	   syscall number 0.  And if you recall, zero is a special
953	   trigger for "not an error".  Store large non-zero there.  */
954	lda	$0, -ENOSYS
955	unop
956	stq	$0, 0($sp)
957	ret
958.end alpha_ni_syscall
959