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