xref: /openbmc/linux/arch/alpha/kernel/entry.S (revision cba1ec7e)
11da177e4SLinus Torvalds/*
21da177e4SLinus Torvalds * arch/alpha/kernel/entry.S
31da177e4SLinus Torvalds *
41da177e4SLinus Torvalds * Kernel entry-points.
51da177e4SLinus Torvalds */
61da177e4SLinus Torvalds
7e2d5df93SSam Ravnborg#include <asm/asm-offsets.h>
81da177e4SLinus Torvalds#include <asm/thread_info.h>
91da177e4SLinus Torvalds#include <asm/pal.h>
101da177e4SLinus Torvalds#include <asm/errno.h>
111da177e4SLinus Torvalds#include <asm/unistd.h>
121da177e4SLinus Torvalds
131da177e4SLinus Torvalds	.text
141da177e4SLinus Torvalds	.set noat
151da177e4SLinus Torvalds
161da177e4SLinus Torvalds/* Stack offsets.  */
171da177e4SLinus Torvalds#define SP_OFF			184
181da177e4SLinus Torvalds#define SWITCH_STACK_SIZE	320
191da177e4SLinus Torvalds
201da177e4SLinus Torvalds/*
211da177e4SLinus Torvalds * This defines the normal kernel pt-regs layout.
221da177e4SLinus Torvalds *
231da177e4SLinus Torvalds * regs 9-15 preserved by C code
241da177e4SLinus Torvalds * regs 16-18 saved by PAL-code
251da177e4SLinus Torvalds * regs 29-30 saved and set up by PAL-code
261da177e4SLinus Torvalds * JRP - Save regs 16-18 in a special area of the stack, so that
271da177e4SLinus Torvalds * the palcode-provided values are available to the signal handler.
281da177e4SLinus Torvalds */
291da177e4SLinus Torvalds
301da177e4SLinus Torvalds#define SAVE_ALL			\
311da177e4SLinus Torvalds	subq	$sp, SP_OFF, $sp;	\
321da177e4SLinus Torvalds	stq	$0, 0($sp);		\
331da177e4SLinus Torvalds	stq	$1, 8($sp);		\
341da177e4SLinus Torvalds	stq	$2, 16($sp);		\
351da177e4SLinus Torvalds	stq	$3, 24($sp);		\
361da177e4SLinus Torvalds	stq	$4, 32($sp);		\
371da177e4SLinus Torvalds	stq	$28, 144($sp);		\
381da177e4SLinus Torvalds	lda	$2, alpha_mv;		\
391da177e4SLinus Torvalds	stq	$5, 40($sp);		\
401da177e4SLinus Torvalds	stq	$6, 48($sp);		\
411da177e4SLinus Torvalds	stq	$7, 56($sp);		\
421da177e4SLinus Torvalds	stq	$8, 64($sp);		\
431da177e4SLinus Torvalds	stq	$19, 72($sp);		\
441da177e4SLinus Torvalds	stq	$20, 80($sp);		\
451da177e4SLinus Torvalds	stq	$21, 88($sp);		\
461da177e4SLinus Torvalds	ldq	$2, HAE_CACHE($2);	\
471da177e4SLinus Torvalds	stq	$22, 96($sp);		\
481da177e4SLinus Torvalds	stq	$23, 104($sp);		\
491da177e4SLinus Torvalds	stq	$24, 112($sp);		\
501da177e4SLinus Torvalds	stq	$25, 120($sp);		\
511da177e4SLinus Torvalds	stq	$26, 128($sp);		\
521da177e4SLinus Torvalds	stq	$27, 136($sp);		\
531da177e4SLinus Torvalds	stq	$2, 152($sp);		\
541da177e4SLinus Torvalds	stq	$16, 160($sp);		\
551da177e4SLinus Torvalds	stq	$17, 168($sp);		\
561da177e4SLinus Torvalds	stq	$18, 176($sp)
571da177e4SLinus Torvalds
581da177e4SLinus Torvalds#define RESTORE_ALL			\
591da177e4SLinus Torvalds	lda	$19, alpha_mv;		\
601da177e4SLinus Torvalds	ldq	$0, 0($sp);		\
611da177e4SLinus Torvalds	ldq	$1, 8($sp);		\
621da177e4SLinus Torvalds	ldq	$2, 16($sp);		\
631da177e4SLinus Torvalds	ldq	$3, 24($sp);		\
641da177e4SLinus Torvalds	ldq	$21, 152($sp);		\
651da177e4SLinus Torvalds	ldq	$20, HAE_CACHE($19);	\
661da177e4SLinus Torvalds	ldq	$4, 32($sp);		\
671da177e4SLinus Torvalds	ldq	$5, 40($sp);		\
681da177e4SLinus Torvalds	ldq	$6, 48($sp);		\
691da177e4SLinus Torvalds	ldq	$7, 56($sp);		\
701da177e4SLinus Torvalds	subq	$20, $21, $20;		\
711da177e4SLinus Torvalds	ldq	$8, 64($sp);		\
721da177e4SLinus Torvalds	beq	$20, 99f;		\
731da177e4SLinus Torvalds	ldq	$20, HAE_REG($19);	\
741da177e4SLinus Torvalds	stq	$21, HAE_CACHE($19);	\
751da177e4SLinus Torvalds	stq	$21, 0($20);		\
761da177e4SLinus Torvalds99:;					\
771da177e4SLinus Torvalds	ldq	$19, 72($sp);		\
781da177e4SLinus Torvalds	ldq	$20, 80($sp);		\
791da177e4SLinus Torvalds	ldq	$21, 88($sp);		\
801da177e4SLinus Torvalds	ldq	$22, 96($sp);		\
811da177e4SLinus Torvalds	ldq	$23, 104($sp);		\
821da177e4SLinus Torvalds	ldq	$24, 112($sp);		\
831da177e4SLinus Torvalds	ldq	$25, 120($sp);		\
841da177e4SLinus Torvalds	ldq	$26, 128($sp);		\
851da177e4SLinus Torvalds	ldq	$27, 136($sp);		\
861da177e4SLinus Torvalds	ldq	$28, 144($sp);		\
871da177e4SLinus Torvalds	addq	$sp, SP_OFF, $sp
881da177e4SLinus Torvalds
891da177e4SLinus Torvalds/*
901da177e4SLinus Torvalds * Non-syscall kernel entry points.
911da177e4SLinus Torvalds */
921da177e4SLinus Torvalds
931da177e4SLinus Torvalds	.align	4
941da177e4SLinus Torvalds	.globl	entInt
951da177e4SLinus Torvalds	.ent	entInt
961da177e4SLinus TorvaldsentInt:
971da177e4SLinus Torvalds	SAVE_ALL
981da177e4SLinus Torvalds	lda	$8, 0x3fff
991da177e4SLinus Torvalds	lda	$26, ret_from_sys_call
1001da177e4SLinus Torvalds	bic	$sp, $8, $8
1011da177e4SLinus Torvalds	mov	$sp, $19
1021da177e4SLinus Torvalds	jsr	$31, do_entInt
1031da177e4SLinus Torvalds.end entInt
1041da177e4SLinus Torvalds
1051da177e4SLinus Torvalds	.align	4
1061da177e4SLinus Torvalds	.globl	entArith
1071da177e4SLinus Torvalds	.ent	entArith
1081da177e4SLinus TorvaldsentArith:
1091da177e4SLinus Torvalds	SAVE_ALL
1101da177e4SLinus Torvalds	lda	$8, 0x3fff
1111da177e4SLinus Torvalds	lda	$26, ret_from_sys_call
1121da177e4SLinus Torvalds	bic	$sp, $8, $8
1131da177e4SLinus Torvalds	mov	$sp, $18
1141da177e4SLinus Torvalds	jsr	$31, do_entArith
1151da177e4SLinus Torvalds.end entArith
1161da177e4SLinus Torvalds
1171da177e4SLinus Torvalds	.align	4
1181da177e4SLinus Torvalds	.globl	entMM
1191da177e4SLinus Torvalds	.ent	entMM
1201da177e4SLinus TorvaldsentMM:
1211da177e4SLinus Torvalds	SAVE_ALL
1221da177e4SLinus Torvalds/* save $9 - $15 so the inline exception code can manipulate them.  */
1231da177e4SLinus Torvalds	subq	$sp, 56, $sp
1241da177e4SLinus Torvalds	stq	$9, 0($sp)
1251da177e4SLinus Torvalds	stq	$10, 8($sp)
1261da177e4SLinus Torvalds	stq	$11, 16($sp)
1271da177e4SLinus Torvalds	stq	$12, 24($sp)
1281da177e4SLinus Torvalds	stq	$13, 32($sp)
1291da177e4SLinus Torvalds	stq	$14, 40($sp)
1301da177e4SLinus Torvalds	stq	$15, 48($sp)
1311da177e4SLinus Torvalds	addq	$sp, 56, $19
1321da177e4SLinus Torvalds/* handle the fault */
1331da177e4SLinus Torvalds	lda	$8, 0x3fff
1341da177e4SLinus Torvalds	bic	$sp, $8, $8
1351da177e4SLinus Torvalds	jsr	$26, do_page_fault
1361da177e4SLinus Torvalds/* reload the registers after the exception code played.  */
1371da177e4SLinus Torvalds	ldq	$9, 0($sp)
1381da177e4SLinus Torvalds	ldq	$10, 8($sp)
1391da177e4SLinus Torvalds	ldq	$11, 16($sp)
1401da177e4SLinus Torvalds	ldq	$12, 24($sp)
1411da177e4SLinus Torvalds	ldq	$13, 32($sp)
1421da177e4SLinus Torvalds	ldq	$14, 40($sp)
1431da177e4SLinus Torvalds	ldq	$15, 48($sp)
1441da177e4SLinus Torvalds	addq	$sp, 56, $sp
1451da177e4SLinus Torvalds/* finish up the syscall as normal.  */
1461da177e4SLinus Torvalds	br	ret_from_sys_call
1471da177e4SLinus Torvalds.end entMM
1481da177e4SLinus Torvalds
1491da177e4SLinus Torvalds	.align	4
1501da177e4SLinus Torvalds	.globl	entIF
1511da177e4SLinus Torvalds	.ent	entIF
1521da177e4SLinus TorvaldsentIF:
1531da177e4SLinus Torvalds	SAVE_ALL
1541da177e4SLinus Torvalds	lda	$8, 0x3fff
1551da177e4SLinus Torvalds	lda	$26, ret_from_sys_call
1561da177e4SLinus Torvalds	bic	$sp, $8, $8
1571da177e4SLinus Torvalds	mov	$sp, $17
1581da177e4SLinus Torvalds	jsr	$31, do_entIF
1591da177e4SLinus Torvalds.end entIF
1601da177e4SLinus Torvalds
1611da177e4SLinus Torvalds	.align	4
1621da177e4SLinus Torvalds	.globl	entUna
1631da177e4SLinus Torvalds	.ent	entUna
1641da177e4SLinus TorvaldsentUna:
1651da177e4SLinus Torvalds	lda	$sp, -256($sp)
1661da177e4SLinus Torvalds	stq	$0, 0($sp)
1671da177e4SLinus Torvalds	ldq	$0, 256($sp)	/* get PS */
1681da177e4SLinus Torvalds	stq	$1, 8($sp)
1691da177e4SLinus Torvalds	stq	$2, 16($sp)
1701da177e4SLinus Torvalds	stq	$3, 24($sp)
1711da177e4SLinus Torvalds	and	$0, 8, $0		/* user mode? */
1721da177e4SLinus Torvalds	stq	$4, 32($sp)
1731da177e4SLinus Torvalds	bne	$0, entUnaUser	/* yup -> do user-level unaligned fault */
1741da177e4SLinus Torvalds	stq	$5, 40($sp)
1751da177e4SLinus Torvalds	stq	$6, 48($sp)
1761da177e4SLinus Torvalds	stq	$7, 56($sp)
1771da177e4SLinus Torvalds	stq	$8, 64($sp)
1781da177e4SLinus Torvalds	stq	$9, 72($sp)
1791da177e4SLinus Torvalds	stq	$10, 80($sp)
1801da177e4SLinus Torvalds	stq	$11, 88($sp)
1811da177e4SLinus Torvalds	stq	$12, 96($sp)
1821da177e4SLinus Torvalds	stq	$13, 104($sp)
1831da177e4SLinus Torvalds	stq	$14, 112($sp)
1841da177e4SLinus Torvalds	stq	$15, 120($sp)
1851da177e4SLinus Torvalds	/* 16-18 PAL-saved */
1861da177e4SLinus Torvalds	stq	$19, 152($sp)
1871da177e4SLinus Torvalds	stq	$20, 160($sp)
1881da177e4SLinus Torvalds	stq	$21, 168($sp)
1891da177e4SLinus Torvalds	stq	$22, 176($sp)
1901da177e4SLinus Torvalds	stq	$23, 184($sp)
1911da177e4SLinus Torvalds	stq	$24, 192($sp)
1921da177e4SLinus Torvalds	stq	$25, 200($sp)
1931da177e4SLinus Torvalds	stq	$26, 208($sp)
1941da177e4SLinus Torvalds	stq	$27, 216($sp)
1951da177e4SLinus Torvalds	stq	$28, 224($sp)
196d70ddac1SRichard Henderson	mov	$sp, $19
1971da177e4SLinus Torvalds	stq	$gp, 232($sp)
1981da177e4SLinus Torvalds	lda	$8, 0x3fff
1991da177e4SLinus Torvalds	stq	$31, 248($sp)
2001da177e4SLinus Torvalds	bic	$sp, $8, $8
2011da177e4SLinus Torvalds	jsr	$26, do_entUna
2021da177e4SLinus Torvalds	ldq	$0, 0($sp)
2031da177e4SLinus Torvalds	ldq	$1, 8($sp)
2041da177e4SLinus Torvalds	ldq	$2, 16($sp)
2051da177e4SLinus Torvalds	ldq	$3, 24($sp)
2061da177e4SLinus Torvalds	ldq	$4, 32($sp)
2071da177e4SLinus Torvalds	ldq	$5, 40($sp)
2081da177e4SLinus Torvalds	ldq	$6, 48($sp)
2091da177e4SLinus Torvalds	ldq	$7, 56($sp)
2101da177e4SLinus Torvalds	ldq	$8, 64($sp)
2111da177e4SLinus Torvalds	ldq	$9, 72($sp)
2121da177e4SLinus Torvalds	ldq	$10, 80($sp)
2131da177e4SLinus Torvalds	ldq	$11, 88($sp)
2141da177e4SLinus Torvalds	ldq	$12, 96($sp)
2151da177e4SLinus Torvalds	ldq	$13, 104($sp)
2161da177e4SLinus Torvalds	ldq	$14, 112($sp)
2171da177e4SLinus Torvalds	ldq	$15, 120($sp)
2181da177e4SLinus Torvalds	/* 16-18 PAL-saved */
2191da177e4SLinus Torvalds	ldq	$19, 152($sp)
2201da177e4SLinus Torvalds	ldq	$20, 160($sp)
2211da177e4SLinus Torvalds	ldq	$21, 168($sp)
2221da177e4SLinus Torvalds	ldq	$22, 176($sp)
2231da177e4SLinus Torvalds	ldq	$23, 184($sp)
2241da177e4SLinus Torvalds	ldq	$24, 192($sp)
2251da177e4SLinus Torvalds	ldq	$25, 200($sp)
2261da177e4SLinus Torvalds	ldq	$26, 208($sp)
2271da177e4SLinus Torvalds	ldq	$27, 216($sp)
2281da177e4SLinus Torvalds	ldq	$28, 224($sp)
2291da177e4SLinus Torvalds	ldq	$gp, 232($sp)
2301da177e4SLinus Torvalds	lda	$sp, 256($sp)
2311da177e4SLinus Torvalds	call_pal PAL_rti
2321da177e4SLinus Torvalds.end entUna
2331da177e4SLinus Torvalds
2341da177e4SLinus Torvalds	.align	4
2351da177e4SLinus Torvalds	.ent	entUnaUser
2361da177e4SLinus TorvaldsentUnaUser:
2371da177e4SLinus Torvalds	ldq	$0, 0($sp)	/* restore original $0 */
2381da177e4SLinus Torvalds	lda	$sp, 256($sp)	/* pop entUna's stack frame */
2391da177e4SLinus Torvalds	SAVE_ALL		/* setup normal kernel stack */
2401da177e4SLinus Torvalds	lda	$sp, -56($sp)
2411da177e4SLinus Torvalds	stq	$9, 0($sp)
2421da177e4SLinus Torvalds	stq	$10, 8($sp)
2431da177e4SLinus Torvalds	stq	$11, 16($sp)
2441da177e4SLinus Torvalds	stq	$12, 24($sp)
2451da177e4SLinus Torvalds	stq	$13, 32($sp)
2461da177e4SLinus Torvalds	stq	$14, 40($sp)
2471da177e4SLinus Torvalds	stq	$15, 48($sp)
2481da177e4SLinus Torvalds	lda	$8, 0x3fff
2491da177e4SLinus Torvalds	addq	$sp, 56, $19
2501da177e4SLinus Torvalds	bic	$sp, $8, $8
2511da177e4SLinus Torvalds	jsr	$26, do_entUnaUser
2521da177e4SLinus Torvalds	ldq	$9, 0($sp)
2531da177e4SLinus Torvalds	ldq	$10, 8($sp)
2541da177e4SLinus Torvalds	ldq	$11, 16($sp)
2551da177e4SLinus Torvalds	ldq	$12, 24($sp)
2561da177e4SLinus Torvalds	ldq	$13, 32($sp)
2571da177e4SLinus Torvalds	ldq	$14, 40($sp)
2581da177e4SLinus Torvalds	ldq	$15, 48($sp)
2591da177e4SLinus Torvalds	lda	$sp, 56($sp)
2601da177e4SLinus Torvalds	br	ret_from_sys_call
2611da177e4SLinus Torvalds.end entUnaUser
2621da177e4SLinus Torvalds
2631da177e4SLinus Torvalds	.align	4
2641da177e4SLinus Torvalds	.globl	entDbg
2651da177e4SLinus Torvalds	.ent	entDbg
2661da177e4SLinus TorvaldsentDbg:
2671da177e4SLinus Torvalds	SAVE_ALL
2681da177e4SLinus Torvalds	lda	$8, 0x3fff
2691da177e4SLinus Torvalds	lda	$26, ret_from_sys_call
2701da177e4SLinus Torvalds	bic	$sp, $8, $8
2711da177e4SLinus Torvalds	mov	$sp, $16
2721da177e4SLinus Torvalds	jsr	$31, do_entDbg
2731da177e4SLinus Torvalds.end entDbg
2741da177e4SLinus Torvalds
2751da177e4SLinus Torvalds/*
2761da177e4SLinus Torvalds * The system call entry point is special.  Most importantly, it looks
2771da177e4SLinus Torvalds * like a function call to userspace as far as clobbered registers.  We
2781da177e4SLinus Torvalds * do preserve the argument registers (for syscall restarts) and $26
2791da177e4SLinus Torvalds * (for leaf syscall functions).
2801da177e4SLinus Torvalds *
2811da177e4SLinus Torvalds * So much for theory.  We don't take advantage of this yet.
2821da177e4SLinus Torvalds *
2831da177e4SLinus Torvalds * Note that a0-a2 are not saved by PALcode as with the other entry points.
2841da177e4SLinus Torvalds */
2851da177e4SLinus Torvalds
2861da177e4SLinus Torvalds	.align	4
2871da177e4SLinus Torvalds	.globl	entSys
2881da177e4SLinus Torvalds	.globl	ret_from_sys_call
2891da177e4SLinus Torvalds	.ent	entSys
2901da177e4SLinus TorvaldsentSys:
2911da177e4SLinus Torvalds	SAVE_ALL
2921da177e4SLinus Torvalds	lda	$8, 0x3fff
2931da177e4SLinus Torvalds	bic	$sp, $8, $8
2941da177e4SLinus Torvalds	lda	$4, NR_SYSCALLS($31)
2951da177e4SLinus Torvalds	stq	$16, SP_OFF+24($sp)
2961da177e4SLinus Torvalds	lda	$5, sys_call_table
2971da177e4SLinus Torvalds	lda	$27, sys_ni_syscall
2981da177e4SLinus Torvalds	cmpult	$0, $4, $4
2991da177e4SLinus Torvalds	ldl	$3, TI_FLAGS($8)
3001da177e4SLinus Torvalds	stq	$17, SP_OFF+32($sp)
3011da177e4SLinus Torvalds	s8addq	$0, $5, $5
3021da177e4SLinus Torvalds	stq	$18, SP_OFF+40($sp)
3031da177e4SLinus Torvalds	blbs	$3, strace
3041da177e4SLinus Torvalds	beq	$4, 1f
3051da177e4SLinus Torvalds	ldq	$27, 0($5)
3061da177e4SLinus Torvalds1:	jsr	$26, ($27), alpha_ni_syscall
3071da177e4SLinus Torvalds	ldgp	$gp, 0($26)
3081da177e4SLinus Torvalds	blt	$0, $syscall_error	/* the call failed */
3091da177e4SLinus Torvalds	stq	$0, 0($sp)
3101da177e4SLinus Torvalds	stq	$31, 72($sp)		/* a3=0 => no error */
3111da177e4SLinus Torvalds
3121da177e4SLinus Torvalds	.align	4
3131da177e4SLinus Torvaldsret_from_sys_call:
3141da177e4SLinus Torvalds	cmovne	$26, 0, $19		/* $19 = 0 => non-restartable */
3151da177e4SLinus Torvalds	ldq	$0, SP_OFF($sp)
3161da177e4SLinus Torvalds	and	$0, 8, $0
31777edffb6SAl Viro	beq	$0, ret_to_kernel
318494486a1SAl Viroret_to_user:
3191da177e4SLinus Torvalds	/* Make sure need_resched and sigpending don't change between
3201da177e4SLinus Torvalds		sampling and the rti.  */
3211da177e4SLinus Torvalds	lda	$16, 7
3221da177e4SLinus Torvalds	call_pal PAL_swpipl
3231da177e4SLinus Torvalds	ldl	$5, TI_FLAGS($8)
3241da177e4SLinus Torvalds	and	$5, _TIF_WORK_MASK, $2
325494486a1SAl Viro	bne	$2, work_pending
3261da177e4SLinus Torvaldsrestore_all:
3271da177e4SLinus Torvalds	RESTORE_ALL
3281da177e4SLinus Torvalds	call_pal PAL_rti
3291da177e4SLinus Torvalds
33077edffb6SAl Viroret_to_kernel:
33177edffb6SAl Viro	lda	$16, 7
33277edffb6SAl Viro	call_pal PAL_swpipl
33377edffb6SAl Viro	br restore_all
33477edffb6SAl Viro
3351da177e4SLinus Torvalds	.align 3
3361da177e4SLinus Torvalds$syscall_error:
3371da177e4SLinus Torvalds	/*
3381da177e4SLinus Torvalds	 * Some system calls (e.g., ptrace) can return arbitrary
3391da177e4SLinus Torvalds	 * values which might normally be mistaken as error numbers.
3401da177e4SLinus Torvalds	 * Those functions must zero $0 (v0) directly in the stack
3411da177e4SLinus Torvalds	 * frame to indicate that a negative return value wasn't an
3421da177e4SLinus Torvalds	 * error number..
3431da177e4SLinus Torvalds	 */
3441da177e4SLinus Torvalds	ldq	$19, 0($sp)	/* old syscall nr (zero if success) */
3451da177e4SLinus Torvalds	beq	$19, $ret_success
3461da177e4SLinus Torvalds
3471da177e4SLinus Torvalds	ldq	$20, 72($sp)	/* .. and this a3 */
3481da177e4SLinus Torvalds	subq	$31, $0, $0	/* with error in v0 */
3491da177e4SLinus Torvalds	addq	$31, 1, $1	/* set a3 for errno return */
3501da177e4SLinus Torvalds	stq	$0, 0($sp)
3511da177e4SLinus Torvalds	mov	$31, $26	/* tell "ret_from_sys_call" we can restart */
3521da177e4SLinus Torvalds	stq	$1, 72($sp)	/* a3 for return */
3531da177e4SLinus Torvalds	br	ret_from_sys_call
3541da177e4SLinus Torvalds
3551da177e4SLinus Torvalds$ret_success:
3561da177e4SLinus Torvalds	stq	$0, 0($sp)
3571da177e4SLinus Torvalds	stq	$31, 72($sp)	/* a3=0 => no error */
3581da177e4SLinus Torvalds	br	ret_from_sys_call
3591da177e4SLinus Torvalds.end entSys
3601da177e4SLinus Torvalds
3611da177e4SLinus Torvalds/*
3621da177e4SLinus Torvalds * Do all cleanup when returning from all interrupts and system calls.
3631da177e4SLinus Torvalds *
3641da177e4SLinus Torvalds * Arguments:
3651da177e4SLinus Torvalds *       $5: TI_FLAGS.
3661da177e4SLinus Torvalds *       $8: current.
3671da177e4SLinus Torvalds *      $19: The old syscall number, or zero if this is not a return
3681da177e4SLinus Torvalds *           from a syscall that errored and is possibly restartable.
369494486a1SAl Viro *      $20: The old a3 value
3701da177e4SLinus Torvalds */
3711da177e4SLinus Torvalds
3721da177e4SLinus Torvalds	.align	4
3731da177e4SLinus Torvalds	.ent	work_pending
3741da177e4SLinus Torvaldswork_pending:
3751da177e4SLinus Torvalds	and	$5, _TIF_NEED_RESCHED, $2
3761da177e4SLinus Torvalds	beq	$2, $work_notifysig
3771da177e4SLinus Torvalds
3781da177e4SLinus Torvalds$work_resched:
3791da177e4SLinus Torvalds	subq	$sp, 16, $sp
3801da177e4SLinus Torvalds	stq	$19, 0($sp)              /* save syscall nr */
3811da177e4SLinus Torvalds	stq	$20, 8($sp)              /* and error indication (a3) */
3821da177e4SLinus Torvalds	jsr	$26, schedule
3831da177e4SLinus Torvalds	ldq	$19, 0($sp)
3841da177e4SLinus Torvalds	ldq	$20, 8($sp)
3851da177e4SLinus Torvalds	addq	$sp, 16, $sp
3861da177e4SLinus Torvalds	/* Make sure need_resched and sigpending don't change between
3871da177e4SLinus Torvalds		sampling and the rti.  */
3881da177e4SLinus Torvalds	lda	$16, 7
3891da177e4SLinus Torvalds	call_pal PAL_swpipl
3901da177e4SLinus Torvalds	ldl	$5, TI_FLAGS($8)
3911da177e4SLinus Torvalds	and	$5, _TIF_WORK_MASK, $2
3921da177e4SLinus Torvalds	beq	$2, restore_all
3931da177e4SLinus Torvalds	and	$5, _TIF_NEED_RESCHED, $2
3941da177e4SLinus Torvalds	bne	$2, $work_resched
3951da177e4SLinus Torvalds
3961da177e4SLinus Torvalds$work_notifysig:
397b927b3e2SRichard Henderson	mov	$sp, $16
398494486a1SAl Viro	bsr	$1, do_switch_stack
399b927b3e2SRichard Henderson	mov	$sp, $17
400b927b3e2SRichard Henderson	mov	$5, $18
401494486a1SAl Viro	mov	$19, $9		/* save old syscall number */
402494486a1SAl Viro	mov	$20, $10	/* save old a3 */
403494486a1SAl Viro	and	$5, _TIF_SIGPENDING, $2
404494486a1SAl Viro	cmovne	$2, 0, $9	/* we don't want double syscall restarts */
4051da177e4SLinus Torvalds	jsr	$26, do_notify_resume
406494486a1SAl Viro	mov	$9, $19
407494486a1SAl Viro	mov	$10, $20
4081da177e4SLinus Torvalds	bsr	$1, undo_switch_stack
409494486a1SAl Viro	br	ret_to_user
4101da177e4SLinus Torvalds.end work_pending
4111da177e4SLinus Torvalds
4121da177e4SLinus Torvalds/*
4131da177e4SLinus Torvalds * PTRACE syscall handler
4141da177e4SLinus Torvalds */
4151da177e4SLinus Torvalds
4161da177e4SLinus Torvalds	.align	4
4171da177e4SLinus Torvalds	.ent	strace
4181da177e4SLinus Torvaldsstrace:
4191da177e4SLinus Torvalds	/* set up signal stack, call syscall_trace */
4201da177e4SLinus Torvalds	bsr	$1, do_switch_stack
4211da177e4SLinus Torvalds	jsr	$26, syscall_trace
4221da177e4SLinus Torvalds	bsr	$1, undo_switch_stack
4231da177e4SLinus Torvalds
4241da177e4SLinus Torvalds	/* get the system call number and the arguments back.. */
4251da177e4SLinus Torvalds	ldq	$0, 0($sp)
4261da177e4SLinus Torvalds	ldq	$16, SP_OFF+24($sp)
4271da177e4SLinus Torvalds	ldq	$17, SP_OFF+32($sp)
4281da177e4SLinus Torvalds	ldq	$18, SP_OFF+40($sp)
4291da177e4SLinus Torvalds	ldq	$19, 72($sp)
4301da177e4SLinus Torvalds	ldq	$20, 80($sp)
4311da177e4SLinus Torvalds	ldq	$21, 88($sp)
4321da177e4SLinus Torvalds
4331da177e4SLinus Torvalds	/* get the system call pointer.. */
4341da177e4SLinus Torvalds	lda	$1, NR_SYSCALLS($31)
4351da177e4SLinus Torvalds	lda	$2, sys_call_table
4361da177e4SLinus Torvalds	lda	$27, alpha_ni_syscall
4371da177e4SLinus Torvalds	cmpult	$0, $1, $1
4381da177e4SLinus Torvalds	s8addq	$0, $2, $2
4391da177e4SLinus Torvalds	beq	$1, 1f
4401da177e4SLinus Torvalds	ldq	$27, 0($2)
4411da177e4SLinus Torvalds1:	jsr	$26, ($27), sys_gettimeofday
44253293638SAl Viroret_from_straced:
4431da177e4SLinus Torvalds	ldgp	$gp, 0($26)
4441da177e4SLinus Torvalds
4451da177e4SLinus Torvalds	/* check return.. */
4461da177e4SLinus Torvalds	blt	$0, $strace_error	/* the call failed */
4471da177e4SLinus Torvalds	stq	$31, 72($sp)		/* a3=0 => no error */
4481da177e4SLinus Torvalds$strace_success:
4491da177e4SLinus Torvalds	stq	$0, 0($sp)		/* save return value */
4501da177e4SLinus Torvalds
4511da177e4SLinus Torvalds	bsr	$1, do_switch_stack
4521da177e4SLinus Torvalds	jsr	$26, syscall_trace
4531da177e4SLinus Torvalds	bsr	$1, undo_switch_stack
4541da177e4SLinus Torvalds	br	$31, ret_from_sys_call
4551da177e4SLinus Torvalds
4561da177e4SLinus Torvalds	.align	3
4571da177e4SLinus Torvalds$strace_error:
4581da177e4SLinus Torvalds	ldq	$19, 0($sp)	/* old syscall nr (zero if success) */
4591da177e4SLinus Torvalds	beq	$19, $strace_success
4601da177e4SLinus Torvalds	ldq	$20, 72($sp)	/* .. and this a3 */
4611da177e4SLinus Torvalds
4621da177e4SLinus Torvalds	subq	$31, $0, $0	/* with error in v0 */
4631da177e4SLinus Torvalds	addq	$31, 1, $1	/* set a3 for errno return */
4641da177e4SLinus Torvalds	stq	$0, 0($sp)
4651da177e4SLinus Torvalds	stq	$1, 72($sp)	/* a3 for return */
4661da177e4SLinus Torvalds
4671da177e4SLinus Torvalds	bsr	$1, do_switch_stack
4681da177e4SLinus Torvalds	mov	$19, $9		/* save old syscall number */
4691da177e4SLinus Torvalds	mov	$20, $10	/* save old a3 */
4701da177e4SLinus Torvalds	jsr	$26, syscall_trace
4711da177e4SLinus Torvalds	mov	$9, $19
4721da177e4SLinus Torvalds	mov	$10, $20
4731da177e4SLinus Torvalds	bsr	$1, undo_switch_stack
4741da177e4SLinus Torvalds
4751da177e4SLinus Torvalds	mov	$31, $26	/* tell "ret_from_sys_call" we can restart */
4761da177e4SLinus Torvalds	br	ret_from_sys_call
4771da177e4SLinus Torvalds.end strace
4781da177e4SLinus Torvalds
4791da177e4SLinus Torvalds/*
4801da177e4SLinus Torvalds * Save and restore the switch stack -- aka the balance of the user context.
4811da177e4SLinus Torvalds */
4821da177e4SLinus Torvalds
4831da177e4SLinus Torvalds	.align	4
4841da177e4SLinus Torvalds	.ent	do_switch_stack
4851da177e4SLinus Torvaldsdo_switch_stack:
4861da177e4SLinus Torvalds	lda	$sp, -SWITCH_STACK_SIZE($sp)
4871da177e4SLinus Torvalds	stq	$9, 0($sp)
4881da177e4SLinus Torvalds	stq	$10, 8($sp)
4891da177e4SLinus Torvalds	stq	$11, 16($sp)
4901da177e4SLinus Torvalds	stq	$12, 24($sp)
4911da177e4SLinus Torvalds	stq	$13, 32($sp)
4921da177e4SLinus Torvalds	stq	$14, 40($sp)
4931da177e4SLinus Torvalds	stq	$15, 48($sp)
4941da177e4SLinus Torvalds	stq	$26, 56($sp)
4951da177e4SLinus Torvalds	stt	$f0, 64($sp)
4961da177e4SLinus Torvalds	stt	$f1, 72($sp)
4971da177e4SLinus Torvalds	stt	$f2, 80($sp)
4981da177e4SLinus Torvalds	stt	$f3, 88($sp)
4991da177e4SLinus Torvalds	stt	$f4, 96($sp)
5001da177e4SLinus Torvalds	stt	$f5, 104($sp)
5011da177e4SLinus Torvalds	stt	$f6, 112($sp)
5021da177e4SLinus Torvalds	stt	$f7, 120($sp)
5031da177e4SLinus Torvalds	stt	$f8, 128($sp)
5041da177e4SLinus Torvalds	stt	$f9, 136($sp)
5051da177e4SLinus Torvalds	stt	$f10, 144($sp)
5061da177e4SLinus Torvalds	stt	$f11, 152($sp)
5071da177e4SLinus Torvalds	stt	$f12, 160($sp)
5081da177e4SLinus Torvalds	stt	$f13, 168($sp)
5091da177e4SLinus Torvalds	stt	$f14, 176($sp)
5101da177e4SLinus Torvalds	stt	$f15, 184($sp)
5111da177e4SLinus Torvalds	stt	$f16, 192($sp)
5121da177e4SLinus Torvalds	stt	$f17, 200($sp)
5131da177e4SLinus Torvalds	stt	$f18, 208($sp)
5141da177e4SLinus Torvalds	stt	$f19, 216($sp)
5151da177e4SLinus Torvalds	stt	$f20, 224($sp)
5161da177e4SLinus Torvalds	stt	$f21, 232($sp)
5171da177e4SLinus Torvalds	stt	$f22, 240($sp)
5181da177e4SLinus Torvalds	stt	$f23, 248($sp)
5191da177e4SLinus Torvalds	stt	$f24, 256($sp)
5201da177e4SLinus Torvalds	stt	$f25, 264($sp)
5211da177e4SLinus Torvalds	stt	$f26, 272($sp)
5221da177e4SLinus Torvalds	stt	$f27, 280($sp)
5231da177e4SLinus Torvalds	mf_fpcr	$f0		# get fpcr
5241da177e4SLinus Torvalds	stt	$f28, 288($sp)
5251da177e4SLinus Torvalds	stt	$f29, 296($sp)
5261da177e4SLinus Torvalds	stt	$f30, 304($sp)
5271da177e4SLinus Torvalds	stt	$f0, 312($sp)	# save fpcr in slot of $f31
5281da177e4SLinus Torvalds	ldt	$f0, 64($sp)	# dont let "do_switch_stack" change fp state.
5291da177e4SLinus Torvalds	ret	$31, ($1), 1
5301da177e4SLinus Torvalds.end do_switch_stack
5311da177e4SLinus Torvalds
5321da177e4SLinus Torvalds	.align	4
5331da177e4SLinus Torvalds	.ent	undo_switch_stack
5341da177e4SLinus Torvaldsundo_switch_stack:
5351da177e4SLinus Torvalds	ldq	$9, 0($sp)
5361da177e4SLinus Torvalds	ldq	$10, 8($sp)
5371da177e4SLinus Torvalds	ldq	$11, 16($sp)
5381da177e4SLinus Torvalds	ldq	$12, 24($sp)
5391da177e4SLinus Torvalds	ldq	$13, 32($sp)
5401da177e4SLinus Torvalds	ldq	$14, 40($sp)
5411da177e4SLinus Torvalds	ldq	$15, 48($sp)
5421da177e4SLinus Torvalds	ldq	$26, 56($sp)
5431da177e4SLinus Torvalds	ldt	$f30, 312($sp)	# get saved fpcr
5441da177e4SLinus Torvalds	ldt	$f0, 64($sp)
5451da177e4SLinus Torvalds	ldt	$f1, 72($sp)
5461da177e4SLinus Torvalds	ldt	$f2, 80($sp)
5471da177e4SLinus Torvalds	ldt	$f3, 88($sp)
5481da177e4SLinus Torvalds	mt_fpcr	$f30		# install saved fpcr
5491da177e4SLinus Torvalds	ldt	$f4, 96($sp)
5501da177e4SLinus Torvalds	ldt	$f5, 104($sp)
5511da177e4SLinus Torvalds	ldt	$f6, 112($sp)
5521da177e4SLinus Torvalds	ldt	$f7, 120($sp)
5531da177e4SLinus Torvalds	ldt	$f8, 128($sp)
5541da177e4SLinus Torvalds	ldt	$f9, 136($sp)
5551da177e4SLinus Torvalds	ldt	$f10, 144($sp)
5561da177e4SLinus Torvalds	ldt	$f11, 152($sp)
5571da177e4SLinus Torvalds	ldt	$f12, 160($sp)
5581da177e4SLinus Torvalds	ldt	$f13, 168($sp)
5591da177e4SLinus Torvalds	ldt	$f14, 176($sp)
5601da177e4SLinus Torvalds	ldt	$f15, 184($sp)
5611da177e4SLinus Torvalds	ldt	$f16, 192($sp)
5621da177e4SLinus Torvalds	ldt	$f17, 200($sp)
5631da177e4SLinus Torvalds	ldt	$f18, 208($sp)
5641da177e4SLinus Torvalds	ldt	$f19, 216($sp)
5651da177e4SLinus Torvalds	ldt	$f20, 224($sp)
5661da177e4SLinus Torvalds	ldt	$f21, 232($sp)
5671da177e4SLinus Torvalds	ldt	$f22, 240($sp)
5681da177e4SLinus Torvalds	ldt	$f23, 248($sp)
5691da177e4SLinus Torvalds	ldt	$f24, 256($sp)
5701da177e4SLinus Torvalds	ldt	$f25, 264($sp)
5711da177e4SLinus Torvalds	ldt	$f26, 272($sp)
5721da177e4SLinus Torvalds	ldt	$f27, 280($sp)
5731da177e4SLinus Torvalds	ldt	$f28, 288($sp)
5741da177e4SLinus Torvalds	ldt	$f29, 296($sp)
5751da177e4SLinus Torvalds	ldt	$f30, 304($sp)
5761da177e4SLinus Torvalds	lda	$sp, SWITCH_STACK_SIZE($sp)
5771da177e4SLinus Torvalds	ret	$31, ($1), 1
5781da177e4SLinus Torvalds.end undo_switch_stack
5791da177e4SLinus Torvalds
5801da177e4SLinus Torvalds/*
5811da177e4SLinus Torvalds * The meat of the context switch code.
5821da177e4SLinus Torvalds */
5831da177e4SLinus Torvalds
5841da177e4SLinus Torvalds	.align	4
5851da177e4SLinus Torvalds	.globl	alpha_switch_to
5861da177e4SLinus Torvalds	.ent	alpha_switch_to
5871da177e4SLinus Torvaldsalpha_switch_to:
5881da177e4SLinus Torvalds	.prologue 0
5891da177e4SLinus Torvalds	bsr	$1, do_switch_stack
5901da177e4SLinus Torvalds	call_pal PAL_swpctx
5911da177e4SLinus Torvalds	lda	$8, 0x3fff
5921da177e4SLinus Torvalds	bsr	$1, undo_switch_stack
5931da177e4SLinus Torvalds	bic	$sp, $8, $8
5941da177e4SLinus Torvalds	mov	$17, $0
5951da177e4SLinus Torvalds	ret
5961da177e4SLinus Torvalds.end alpha_switch_to
5971da177e4SLinus Torvalds
5981da177e4SLinus Torvalds/*
5991da177e4SLinus Torvalds * New processes begin life here.
6001da177e4SLinus Torvalds */
6011da177e4SLinus Torvalds
6021da177e4SLinus Torvalds	.globl	ret_from_fork
6031da177e4SLinus Torvalds	.align	4
6041da177e4SLinus Torvalds	.ent	ret_from_fork
6051da177e4SLinus Torvaldsret_from_fork:
6061da177e4SLinus Torvalds	lda	$26, ret_from_sys_call
6071da177e4SLinus Torvalds	mov	$17, $16
6081da177e4SLinus Torvalds	jmp	$31, schedule_tail
6091da177e4SLinus Torvalds.end ret_from_fork
6101da177e4SLinus Torvalds
6111da177e4SLinus Torvalds/*
612cba1ec7eSAl Viro * ... and new kernel threads - here
6131da177e4SLinus Torvalds */
6141da177e4SLinus Torvalds	.align 4
615cba1ec7eSAl Viro	.globl	ret_from_kernel_thread
616cba1ec7eSAl Viro	.ent	ret_from_kernel_thread
617cba1ec7eSAl Viroret_from_kernel_thread:
618cba1ec7eSAl Viro	mov	$17, $16
619cba1ec7eSAl Viro	jsr	$26, schedule_tail
620cba1ec7eSAl Viro	mov	$9, $27
621cba1ec7eSAl Viro	mov	$10, $16
622cba1ec7eSAl Viro	jsr	$26, ($9)
6231da177e4SLinus Torvalds	ldgp	$gp, 0($26)
6241da177e4SLinus Torvalds	mov	$0, $16
6251da177e4SLinus Torvalds	mov	$31, $26
6261da177e4SLinus Torvalds	jmp	$31, sys_exit
627cba1ec7eSAl Viro.end ret_from_kernel_thread
6281da177e4SLinus Torvalds
6291da177e4SLinus Torvalds
6301da177e4SLinus Torvalds/*
6311da177e4SLinus Torvalds * Special system calls.  Most of these are special in that they either
6321da177e4SLinus Torvalds * have to play switch_stack games or in some way use the pt_regs struct.
6331da177e4SLinus Torvalds */
6341da177e4SLinus Torvalds	.align	4
6351da177e4SLinus Torvalds	.globl	sys_fork
6361da177e4SLinus Torvalds	.ent	sys_fork
6371da177e4SLinus Torvaldssys_fork:
6381da177e4SLinus Torvalds	.prologue 0
6391da177e4SLinus Torvalds	mov	$sp, $21
6401da177e4SLinus Torvalds	bsr	$1, do_switch_stack
6411da177e4SLinus Torvalds	bis	$31, SIGCHLD, $16
6421da177e4SLinus Torvalds	mov	$31, $17
6431da177e4SLinus Torvalds	mov	$31, $18
6441da177e4SLinus Torvalds	mov	$31, $19
6451da177e4SLinus Torvalds	mov	$31, $20
6461da177e4SLinus Torvalds	jsr	$26, alpha_clone
6471da177e4SLinus Torvalds	bsr	$1, undo_switch_stack
6481da177e4SLinus Torvalds	ret
6491da177e4SLinus Torvalds.end sys_fork
6501da177e4SLinus Torvalds
6511da177e4SLinus Torvalds	.align	4
6521da177e4SLinus Torvalds	.globl	sys_clone
6531da177e4SLinus Torvalds	.ent	sys_clone
6541da177e4SLinus Torvaldssys_clone:
6551da177e4SLinus Torvalds	.prologue 0
6561da177e4SLinus Torvalds	mov	$sp, $21
6571da177e4SLinus Torvalds	bsr	$1, do_switch_stack
6581da177e4SLinus Torvalds	/* $16, $17, $18, $19, $20 come from the user.  */
6591da177e4SLinus Torvalds	jsr	$26, alpha_clone
6601da177e4SLinus Torvalds	bsr	$1, undo_switch_stack
6611da177e4SLinus Torvalds	ret
6621da177e4SLinus Torvalds.end sys_clone
6631da177e4SLinus Torvalds
6641da177e4SLinus Torvalds	.align	4
6651da177e4SLinus Torvalds	.globl	sys_vfork
6661da177e4SLinus Torvalds	.ent	sys_vfork
6671da177e4SLinus Torvaldssys_vfork:
6681da177e4SLinus Torvalds	.prologue 0
6691da177e4SLinus Torvalds	mov	$sp, $16
6701da177e4SLinus Torvalds	bsr	$1, do_switch_stack
6711da177e4SLinus Torvalds	jsr	$26, alpha_vfork
6721da177e4SLinus Torvalds	bsr	$1, undo_switch_stack
6731da177e4SLinus Torvalds	ret
6741da177e4SLinus Torvalds.end sys_vfork
6751da177e4SLinus Torvalds
6761da177e4SLinus Torvalds	.align	4
6771da177e4SLinus Torvalds	.globl	sys_sigreturn
6781da177e4SLinus Torvalds	.ent	sys_sigreturn
6791da177e4SLinus Torvaldssys_sigreturn:
6801da177e4SLinus Torvalds	.prologue 0
68153293638SAl Viro	lda	$9, ret_from_straced
68253293638SAl Viro	cmpult	$26, $9, $9
6831da177e4SLinus Torvalds	mov	$sp, $17
6841da177e4SLinus Torvalds	lda	$18, -SWITCH_STACK_SIZE($sp)
6851da177e4SLinus Torvalds	lda	$sp, -SWITCH_STACK_SIZE($sp)
6861da177e4SLinus Torvalds	jsr	$26, do_sigreturn
68753293638SAl Viro	bne	$9, 1f
68853293638SAl Viro	jsr	$26, syscall_trace
68953293638SAl Viro1:	br	$1, undo_switch_stack
6901da177e4SLinus Torvalds	br	ret_from_sys_call
6911da177e4SLinus Torvalds.end sys_sigreturn
6921da177e4SLinus Torvalds
6931da177e4SLinus Torvalds	.align	4
6941da177e4SLinus Torvalds	.globl	sys_rt_sigreturn
6951da177e4SLinus Torvalds	.ent	sys_rt_sigreturn
6961da177e4SLinus Torvaldssys_rt_sigreturn:
6971da177e4SLinus Torvalds	.prologue 0
69853293638SAl Viro	lda	$9, ret_from_straced
69953293638SAl Viro	cmpult	$26, $9, $9
7001da177e4SLinus Torvalds	mov	$sp, $17
7011da177e4SLinus Torvalds	lda	$18, -SWITCH_STACK_SIZE($sp)
7021da177e4SLinus Torvalds	lda	$sp, -SWITCH_STACK_SIZE($sp)
7031da177e4SLinus Torvalds	jsr	$26, do_rt_sigreturn
70453293638SAl Viro	bne	$9, 1f
70553293638SAl Viro	jsr	$26, syscall_trace
70653293638SAl Viro1:	br	$1, undo_switch_stack
7071da177e4SLinus Torvalds	br	ret_from_sys_call
7081da177e4SLinus Torvalds.end sys_rt_sigreturn
7091da177e4SLinus Torvalds
7101da177e4SLinus Torvalds	.align	4
7111da177e4SLinus Torvalds	.globl	alpha_ni_syscall
7121da177e4SLinus Torvalds	.ent	alpha_ni_syscall
7131da177e4SLinus Torvaldsalpha_ni_syscall:
7141da177e4SLinus Torvalds	.prologue 0
7151da177e4SLinus Torvalds	/* Special because it also implements overflow handling via
7161da177e4SLinus Torvalds	   syscall number 0.  And if you recall, zero is a special
7171da177e4SLinus Torvalds	   trigger for "not an error".  Store large non-zero there.  */
7181da177e4SLinus Torvalds	lda	$0, -ENOSYS
7191da177e4SLinus Torvalds	unop
7201da177e4SLinus Torvalds	stq	$0, 0($sp)
7211da177e4SLinus Torvalds	ret
7221da177e4SLinus Torvalds.end alpha_ni_syscall
723