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