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