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); \
92 * Non-syscall kernel entry points.
101 lda $26, ret_from_sys_call
113 lda $26, ret_from_sys_call
124 /* save $9 - $15 so the inline exception code can manipulate them. */
134 /* handle the fault */
137 jsr $26, do_page_fault
138 /* reload the registers after the exception code played. */
147 /* finish up the syscall as normal. */
157 lda $26, ret_from_sys_call
169 ldq $0, 256($sp) /* get PS */
173 and $0, 8, $0 /* user mode? */
175 bne $0, entUnaUser /* yup -> do user-level unaligned fault */
187 /* 16-18 PAL-saved */
220 /* 16-18 PAL-saved */
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 */
253 jsr $26, do_entUnaUser
271 lda $26, ret_from_sys_call
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).
283 * So much for theory. We don't take advantage of this yet.
285 * Note that a0-a2 are not saved by PALcode as with the other entry points.
290 .globl ret_from_sys_call
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
302 stq $17, SP_OFF+32($sp)
304 stq $18, SP_OFF+40($sp)
308 1: jsr $26, ($27), alpha_ni_syscall
310 blt $0, $syscall_error /* the call failed */
312 stq $31, 72($sp) /* a3=0 => no error */
316 cmovne $26, 0, $19 /* $19 = 0 => non-restartable */
321 /* Make sure need_resched and sigpending don't change between
322 sampling and the rti. */
326 and $5, _TIF_WORK_MASK, $2
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
341 ldq $19, 0($sp) /* old syscall nr (zero if success) */
342 beq $19, $ret_success
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 */
348 mov $31, $26 /* tell "ret_from_sys_call" we can restart */
349 stq $1, 72($sp) /* a3 for return */
354 stq $31, 72($sp) /* a3=0 => no error */
359 * Do all cleanup when returning from all interrupts and system calls.
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: The old a3 value
372 and $5, _TIF_NEED_RESCHED, $2
373 beq $2, $work_notifysig
377 stq $19, 0($sp) /* save syscall nr */
378 stq $20, 8($sp) /* and error indication (a3) */
383 /* Make sure need_resched and sigpending don't change between
384 sampling and the rti. */
388 and $5, _TIF_WORK_MASK, $2
390 and $5, _TIF_NEED_RESCHED, $2
391 bne $2, $work_resched
395 bsr $1, do_switch_stack
398 mov $19, $9 /* save old syscall number */
399 mov $20, $10 /* save old a3 */
400 and $5, _TIF_SIGPENDING, $2
401 cmovne $2, 0, $9 /* we don't want double syscall restarts */
402 jsr $26, do_notify_resume
405 bsr $1, undo_switch_stack
410 * PTRACE syscall handler
416 /* set up signal stack, call syscall_trace */
417 bsr $1, do_switch_stack
418 jsr $26, syscall_trace
419 bsr $1, undo_switch_stack
421 /* get the system call number and the arguments back.. */
423 ldq $16, SP_OFF+24($sp)
424 ldq $17, SP_OFF+32($sp)
425 ldq $18, SP_OFF+40($sp)
430 /* get the system call pointer.. */
431 lda $1, NR_SYSCALLS($31)
432 lda $2, sys_call_table
433 lda $27, alpha_ni_syscall
438 1: jsr $26, ($27), sys_gettimeofday
443 blt $0, $strace_error /* the call failed */
444 stq $31, 72($sp) /* a3=0 => no error */
446 stq $0, 0($sp) /* save return value */
448 bsr $1, do_switch_stack
449 jsr $26, syscall_trace
450 bsr $1, undo_switch_stack
451 br $31, ret_from_sys_call
455 ldq $19, 0($sp) /* old syscall nr (zero if success) */
456 beq $19, $strace_success
457 ldq $20, 72($sp) /* .. and this a3 */
459 subq $31, $0, $0 /* with error in v0 */
460 addq $31, 1, $1 /* set a3 for errno return */
462 stq $1, 72($sp) /* a3 for return */
464 bsr $1, do_switch_stack
465 mov $19, $9 /* save old syscall number */
466 mov $20, $10 /* save old a3 */
467 jsr $26, syscall_trace
470 bsr $1, undo_switch_stack
472 mov $31, $26 /* tell "ret_from_sys_call" we can restart */
477 * Save and restore the switch stack -- aka the balance of the user context.
483 lda $sp, -SWITCH_STACK_SIZE($sp)
520 mf_fpcr $f0 # get fpcr
524 stt $f0, 312($sp) # save fpcr in slot of $f31
525 ldt $f0, 64($sp) # dont let "do_switch_stack" change fp state.
530 .ent undo_switch_stack
540 ldt $f30, 312($sp) # get saved fpcr
545 mt_fpcr $f30 # install saved fpcr
573 lda $sp, SWITCH_STACK_SIZE($sp)
575 .end undo_switch_stack
578 * The meat of the context switch code.
582 .globl alpha_switch_to
586 bsr $1, do_switch_stack
589 bsr $1, undo_switch_stack
596 * New processes begin life here.
603 lda $26, ret_from_sys_call
605 jmp $31, schedule_tail
609 * kernel_thread(fn, arg, clone_flags)
615 /* We can be called from a module. */
618 subq $sp, SP_OFF+6*8, $sp
619 br $1, 2f /* load start address */
621 /* We've now "returned" from a fake system call. */
623 blt $0, 1f /* error? */
625 beq $20, 1f /* parent or child? */
627 bic $sp, $1, $8 /* in child. */
634 1: ret /* in parent. */
637 2: /* Fake a system call stack frame, as we can't do system calls
638 from kernel space. Note that we store FN and ARG as they
639 need to be set up in the child for the call. Also store $8
640 and $26 for use in the parent. */
641 stq $31, SP_OFF($sp) /* ps */
642 stq $1, SP_OFF+8($sp) /* pc */
643 stq $gp, SP_OFF+16($sp) /* gp */
644 stq $16, 136($sp) /* $27; FN for child */
645 stq $17, SP_OFF+24($sp) /* $16; ARG for child */
646 stq $8, 64($sp) /* $8 */
647 stq $26, 128($sp) /* $26 */
648 /* Avoid the HAE being gratuitously wrong, to avoid restoring it. */
649 ldq $2, alpha_mv+HAE_CACHE
650 stq $2, 152($sp) /* HAE */
652 /* Shuffle FLAGS to the front; add CLONE_VM. */
653 ldi $1, CLONE_VM|CLONE_UNTRACED
657 /* We don't actually care for a3 success widgetry in the kernel.
658 Not for positive errno values. */
659 stq $0, 0($sp) /* $0 */
664 * kernel_execve(path, argv, envp)
670 /* We can be called from a module. */
672 lda $sp, -(32+SIZEOF_PT_REGS+8)($sp)
673 .frame $sp, 32+SIZEOF_PT_REGS+8, $26, 0
682 lda $18, SIZEOF_PT_REGS
683 bsr $26, memset !samegp
685 /* Avoid the HAE being gratuitously wrong, which would cause us
686 to do the whole turn off interrupts thing and restore it. */
687 ldq $2, alpha_mv+HAE_CACHE
694 bsr $26, do_execve !samegp
697 bne $0, 1f /* error! */
699 /* Move the temporary pt_regs struct from its current location
700 to the top of the kernel stack frame. See copy_thread for
701 details for a normal process. */
702 lda $16, 0x4000 - SIZEOF_PT_REGS($8)
704 lda $18, SIZEOF_PT_REGS
705 bsr $26, memmove !samegp
707 /* Take that over as our new stack frame and visit userland! */
708 lda $sp, 0x4000 - SIZEOF_PT_REGS($8)
709 br $31, ret_from_sys_call
711 1: lda $sp, 32+SIZEOF_PT_REGS+8($sp)
717 * Special system calls. Most of these are special in that they either
718 * have to play switch_stack games or in some way use the pt_regs struct.
726 bsr $1, do_switch_stack
727 bis $31, SIGCHLD, $16
733 bsr $1, undo_switch_stack
743 bsr $1, do_switch_stack
744 /* $16, $17, $18, $19, $20 come from the user. */
746 bsr $1, undo_switch_stack
756 bsr $1, do_switch_stack
758 bsr $1, undo_switch_stack
767 lda $9, ret_from_straced
770 lda $18, -SWITCH_STACK_SIZE($sp)
771 lda $sp, -SWITCH_STACK_SIZE($sp)
772 jsr $26, do_sigreturn
774 jsr $26, syscall_trace
775 1: br $1, undo_switch_stack
780 .globl sys_rt_sigreturn
781 .ent sys_rt_sigreturn
784 lda $9, ret_from_straced
787 lda $18, -SWITCH_STACK_SIZE($sp)
788 lda $sp, -SWITCH_STACK_SIZE($sp)
789 jsr $26, do_rt_sigreturn
791 jsr $26, syscall_trace
792 1: br $1, undo_switch_stack
794 .end sys_rt_sigreturn
806 .globl osf_getpriority
813 jsr $26, sys_getpriority
818 /* Return value is the unbiased priority, i.e. 20 - prio.
819 This does result in negative return values, so signal
820 no error by writing into the R0 slot. */
836 ldq $3, TASK_CRED($2)
838 ldl $1, CRED_EUID($3)
849 ldq $3, TASK_CRED($2)
851 ldl $1, CRED_EGID($3)
863 /* See linux/kernel/timer.c sys_getppid for discussion
865 ldq $3, TASK_GROUP_LEADER($2)
866 ldq $4, TASK_REAL_PARENT($3)
867 ldl $0, TASK_TGID($2)
868 1: ldl $1, TASK_TGID($4)
872 ldq $3, TASK_GROUP_LEADER($2)
873 ldq $4, TASK_REAL_PARENT($3)
882 .globl sys_alpha_pipe
891 jsr $26, do_pipe_flags
896 /* The return values are in $0 and $20. */
911 jmp $31, do_sys_execve
915 .globl osf_sigprocmask
920 jmp $31, sys_osf_sigprocmask
924 .globl alpha_ni_syscall
925 .ent alpha_ni_syscall
928 /* Special because it also implements overflow handling via
929 syscall number 0. And if you recall, zero is a special
930 trigger for "not an error". Store large non-zero there. */
935 .end alpha_ni_syscall