2 * arch/alpha/kernel/entry.S
7 #include <asm/asm-offsets.h>
8 #include <asm/thread_info.h>
10 #include <asm/errno.h>
11 #include <asm/unistd.h>
18 #define SWITCH_STACK_SIZE 320
21 * This defines the normal kernel pt-regs layout.
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.
31 subq $sp, SP_OFF, $sp; \
46 ldq $2, HAE_CACHE($2); \
65 ldq $20, HAE_CACHE($19); \
73 ldq $20, HAE_REG($19); \
74 stq $21, HAE_CACHE($19); \
90 * Non-syscall kernel entry points.
99 lda $26, ret_from_sys_call
111 lda $26, ret_from_sys_call
122 /* save $9 - $15 so the inline exception code can manipulate them. */
132 /* handle the fault */
135 jsr $26, do_page_fault
136 /* reload the registers after the exception code played. */
145 /* finish up the syscall as normal. */
155 lda $26, ret_from_sys_call
167 ldq $0, 256($sp) /* get PS */
171 and $0, 8, $0 /* user mode? */
173 bne $0, entUnaUser /* yup -> do user-level unaligned fault */
185 /* 16-18 PAL-saved */
218 /* 16-18 PAL-saved */
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 */
251 jsr $26, do_entUnaUser
269 lda $26, ret_from_sys_call
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).
281 * So much for theory. We don't take advantage of this yet.
283 * Note that a0-a2 are not saved by PALcode as with the other entry points.
288 .globl ret_from_sys_call
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
300 stq $17, SP_OFF+32($sp)
302 stq $18, SP_OFF+40($sp)
306 1: jsr $26, ($27), alpha_ni_syscall
308 blt $0, $syscall_error /* the call failed */
310 stq $31, 72($sp) /* a3=0 => no error */
314 cmovne $26, 0, $19 /* $19 = 0 => non-restartable */
317 beq $0, ret_to_kernel
319 /* Make sure need_resched and sigpending don't change between
320 sampling and the rti. */
324 and $5, _TIF_WORK_MASK, $2
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
344 ldq $19, 0($sp) /* old syscall nr (zero if success) */
345 beq $19, $ret_success
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 */
351 mov $31, $26 /* tell "ret_from_sys_call" we can restart */
352 stq $1, 72($sp) /* a3 for return */
357 stq $31, 72($sp) /* a3=0 => no error */
362 * Do all cleanup when returning from all interrupts and system calls.
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
375 and $5, _TIF_NEED_RESCHED, $2
376 beq $2, $work_notifysig
380 stq $19, 0($sp) /* save syscall nr */
381 stq $20, 8($sp) /* and error indication (a3) */
386 /* Make sure need_resched and sigpending don't change between
387 sampling and the rti. */
391 and $5, _TIF_WORK_MASK, $2
393 and $5, _TIF_NEED_RESCHED, $2
394 bne $2, $work_resched
398 bsr $1, do_switch_stack
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
408 bsr $1, undo_switch_stack
413 * PTRACE syscall handler
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
424 /* get the system call number and the arguments back.. */
426 ldq $16, SP_OFF+24($sp)
427 ldq $17, SP_OFF+32($sp)
428 ldq $18, SP_OFF+40($sp)
433 /* get the system call pointer.. */
434 lda $1, NR_SYSCALLS($31)
435 lda $2, sys_call_table
436 lda $27, alpha_ni_syscall
441 1: jsr $26, ($27), sys_gettimeofday
446 blt $0, $strace_error /* the call failed */
447 stq $31, 72($sp) /* a3=0 => no error */
449 stq $0, 0($sp) /* save return value */
451 bsr $1, do_switch_stack
452 jsr $26, syscall_trace
453 bsr $1, undo_switch_stack
454 br $31, ret_from_sys_call
458 ldq $19, 0($sp) /* old syscall nr (zero if success) */
459 beq $19, $strace_success
460 ldq $20, 72($sp) /* .. and this a3 */
462 subq $31, $0, $0 /* with error in v0 */
463 addq $31, 1, $1 /* set a3 for errno return */
465 stq $1, 72($sp) /* a3 for return */
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
473 bsr $1, undo_switch_stack
475 mov $31, $26 /* tell "ret_from_sys_call" we can restart */
480 * Save and restore the switch stack -- aka the balance of the user context.
486 lda $sp, -SWITCH_STACK_SIZE($sp)
523 mf_fpcr $f0 # get fpcr
527 stt $f0, 312($sp) # save fpcr in slot of $f31
528 ldt $f0, 64($sp) # dont let "do_switch_stack" change fp state.
533 .ent undo_switch_stack
543 ldt $f30, 312($sp) # get saved fpcr
548 mt_fpcr $f30 # install saved fpcr
576 lda $sp, SWITCH_STACK_SIZE($sp)
578 .end undo_switch_stack
581 * The meat of the context switch code.
585 .globl alpha_switch_to
589 bsr $1, do_switch_stack
592 bsr $1, undo_switch_stack
599 * New processes begin life here.
606 lda $26, ret_from_sys_call
608 jmp $31, schedule_tail
612 * kernel_thread(fn, arg, clone_flags)
618 /* We can be called from a module. */
621 subq $sp, SP_OFF+6*8, $sp
622 br $1, 2f /* load start address */
624 /* We've now "returned" from a fake system call. */
626 blt $0, 1f /* error? */
628 beq $20, 1f /* parent or child? */
630 bic $sp, $1, $8 /* in child. */
637 1: ret /* in parent. */
640 2: /* 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 */
655 /* Shuffle FLAGS to the front; add CLONE_VM. */
656 ldi $1, CLONE_VM|CLONE_UNTRACED
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 */
667 * kernel_execve(path, argv, envp)
673 /* We can be called from a module. */
675 lda $sp, -(32+SIZEOF_PT_REGS+8)($sp)
676 .frame $sp, 32+SIZEOF_PT_REGS+8, $26, 0
685 lda $18, SIZEOF_PT_REGS
686 bsr $26, memset !samegp
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
697 bsr $26, do_execve !samegp
700 bne $0, 1f /* error! */
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)
707 lda $18, SIZEOF_PT_REGS
708 bsr $26, memmove !samegp
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
714 1: lda $sp, 32+SIZEOF_PT_REGS+8($sp)
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.
729 bsr $1, do_switch_stack
730 bis $31, SIGCHLD, $16
736 bsr $1, undo_switch_stack
746 bsr $1, do_switch_stack
747 /* $16, $17, $18, $19, $20 come from the user. */
749 bsr $1, undo_switch_stack
759 bsr $1, do_switch_stack
761 bsr $1, undo_switch_stack
770 lda $9, ret_from_straced
773 lda $18, -SWITCH_STACK_SIZE($sp)
774 lda $sp, -SWITCH_STACK_SIZE($sp)
775 jsr $26, do_sigreturn
777 jsr $26, syscall_trace
778 1: br $1, undo_switch_stack
783 .globl sys_rt_sigreturn
784 .ent sys_rt_sigreturn
787 lda $9, ret_from_straced
790 lda $18, -SWITCH_STACK_SIZE($sp)
791 lda $sp, -SWITCH_STACK_SIZE($sp)
792 jsr $26, do_rt_sigreturn
794 jsr $26, syscall_trace
795 1: br $1, undo_switch_stack
797 .end sys_rt_sigreturn
809 .globl osf_getpriority
816 jsr $26, sys_getpriority
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. */
839 ldq $3, TASK_CRED($2)
841 ldl $1, CRED_EUID($3)
852 ldq $3, TASK_CRED($2)
854 ldl $1, CRED_EGID($3)
866 /* See linux/kernel/timer.c sys_getppid for discussion
868 ldq $3, TASK_GROUP_LEADER($2)
869 ldq $4, TASK_REAL_PARENT($3)
870 ldl $0, TASK_TGID($2)
871 1: ldl $1, TASK_TGID($4)
875 ldq $3, TASK_GROUP_LEADER($2)
876 ldq $4, TASK_REAL_PARENT($3)
885 .globl sys_alpha_pipe
894 jsr $26, do_pipe_flags
899 /* The return values are in $0 and $20. */
914 jmp $31, do_sys_execve
918 .globl alpha_ni_syscall
919 .ent alpha_ni_syscall
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. */
929 .end alpha_ni_syscall