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: Error indication.
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 br $1, do_switch_stack
398 jsr $26, do_notify_resume
399 bsr $1, undo_switch_stack
404 * PTRACE syscall handler
410 /* set up signal stack, call syscall_trace */
411 bsr $1, do_switch_stack
412 jsr $26, syscall_trace
413 bsr $1, undo_switch_stack
415 /* get the system call number and the arguments back.. */
417 ldq $16, SP_OFF+24($sp)
418 ldq $17, SP_OFF+32($sp)
419 ldq $18, SP_OFF+40($sp)
424 /* get the system call pointer.. */
425 lda $1, NR_SYSCALLS($31)
426 lda $2, sys_call_table
427 lda $27, alpha_ni_syscall
432 1: jsr $26, ($27), sys_gettimeofday
436 blt $0, $strace_error /* the call failed */
437 stq $31, 72($sp) /* a3=0 => no error */
439 stq $0, 0($sp) /* save return value */
441 bsr $1, do_switch_stack
442 jsr $26, syscall_trace
443 bsr $1, undo_switch_stack
444 br $31, ret_from_sys_call
448 ldq $19, 0($sp) /* old syscall nr (zero if success) */
449 beq $19, $strace_success
450 ldq $20, 72($sp) /* .. and this a3 */
452 subq $31, $0, $0 /* with error in v0 */
453 addq $31, 1, $1 /* set a3 for errno return */
455 stq $1, 72($sp) /* a3 for return */
457 bsr $1, do_switch_stack
458 mov $19, $9 /* save old syscall number */
459 mov $20, $10 /* save old a3 */
460 jsr $26, syscall_trace
463 bsr $1, undo_switch_stack
465 mov $31, $26 /* tell "ret_from_sys_call" we can restart */
470 * Save and restore the switch stack -- aka the balance of the user context.
476 lda $sp, -SWITCH_STACK_SIZE($sp)
513 mf_fpcr $f0 # get fpcr
517 stt $f0, 312($sp) # save fpcr in slot of $f31
518 ldt $f0, 64($sp) # dont let "do_switch_stack" change fp state.
523 .ent undo_switch_stack
533 ldt $f30, 312($sp) # get saved fpcr
538 mt_fpcr $f30 # install saved fpcr
566 lda $sp, SWITCH_STACK_SIZE($sp)
568 .end undo_switch_stack
571 * The meat of the context switch code.
575 .globl alpha_switch_to
579 bsr $1, do_switch_stack
582 bsr $1, undo_switch_stack
589 * New processes begin life here.
596 lda $26, ret_from_sys_call
598 jmp $31, schedule_tail
602 * kernel_thread(fn, arg, clone_flags)
608 /* We can be called from a module. */
611 subq $sp, SP_OFF+6*8, $sp
612 br $1, 2f /* load start address */
614 /* We've now "returned" from a fake system call. */
616 blt $0, 1f /* error? */
618 beq $20, 1f /* parent or child? */
620 bic $sp, $1, $8 /* in child. */
627 1: ret /* in parent. */
630 2: /* Fake a system call stack frame, as we can't do system calls
631 from kernel space. Note that we store FN and ARG as they
632 need to be set up in the child for the call. Also store $8
633 and $26 for use in the parent. */
634 stq $31, SP_OFF($sp) /* ps */
635 stq $1, SP_OFF+8($sp) /* pc */
636 stq $gp, SP_OFF+16($sp) /* gp */
637 stq $16, 136($sp) /* $27; FN for child */
638 stq $17, SP_OFF+24($sp) /* $16; ARG for child */
639 stq $8, 64($sp) /* $8 */
640 stq $26, 128($sp) /* $26 */
641 /* Avoid the HAE being gratuitously wrong, to avoid restoring it. */
642 ldq $2, alpha_mv+HAE_CACHE
643 stq $2, 152($sp) /* HAE */
645 /* Shuffle FLAGS to the front; add CLONE_VM. */
646 ldi $1, CLONE_VM|CLONE_UNTRACED
650 /* We don't actually care for a3 success widgetry in the kernel.
651 Not for positive errno values. */
652 stq $0, 0($sp) /* $0 */
657 * kernel_execve(path, argv, envp)
663 /* We can be called from a module. */
665 lda $sp, -(32+SIZEOF_PT_REGS+8)($sp)
666 .frame $sp, 32+SIZEOF_PT_REGS+8, $26, 0
675 lda $18, SIZEOF_PT_REGS
676 bsr $26, memset !samegp
678 /* Avoid the HAE being gratuitously wrong, which would cause us
679 to do the whole turn off interrupts thing and restore it. */
680 ldq $2, alpha_mv+HAE_CACHE
687 bsr $26, do_execve !samegp
690 bne $0, 1f /* error! */
692 /* Move the temporary pt_regs struct from its current location
693 to the top of the kernel stack frame. See copy_thread for
694 details for a normal process. */
695 lda $16, 0x4000 - SIZEOF_PT_REGS($8)
697 lda $18, SIZEOF_PT_REGS
698 bsr $26, memmove !samegp
700 /* Take that over as our new stack frame and visit userland! */
701 lda $sp, 0x4000 - SIZEOF_PT_REGS($8)
702 br $31, ret_from_sys_call
704 1: lda $sp, 32+SIZEOF_PT_REGS+8($sp)
710 * Special system calls. Most of these are special in that they either
711 * have to play switch_stack games or in some way use the pt_regs struct.
719 bsr $1, do_switch_stack
720 bis $31, SIGCHLD, $16
726 bsr $1, undo_switch_stack
736 bsr $1, do_switch_stack
737 /* $16, $17, $18, $19, $20 come from the user. */
739 bsr $1, undo_switch_stack
749 bsr $1, do_switch_stack
751 bsr $1, undo_switch_stack
761 lda $18, -SWITCH_STACK_SIZE($sp)
762 lda $sp, -SWITCH_STACK_SIZE($sp)
763 jsr $26, do_sigreturn
764 br $1, undo_switch_stack
769 .globl sys_rt_sigreturn
770 .ent sys_rt_sigreturn
774 lda $18, -SWITCH_STACK_SIZE($sp)
775 lda $sp, -SWITCH_STACK_SIZE($sp)
776 jsr $26, do_rt_sigreturn
777 br $1, undo_switch_stack
779 .end sys_rt_sigreturn
782 .globl sys_sigsuspend
787 br $1, do_switch_stack
791 jsr $26, do_sigsuspend
793 lda $sp, SWITCH_STACK_SIZE+16($sp)
798 .globl sys_rt_sigsuspend
799 .ent sys_rt_sigsuspend
803 br $1, do_switch_stack
807 jsr $26, do_rt_sigsuspend
809 lda $sp, SWITCH_STACK_SIZE+16($sp)
811 .end sys_rt_sigsuspend
823 .globl osf_getpriority
830 jsr $26, sys_getpriority
835 /* Return value is the unbiased priority, i.e. 20 - prio.
836 This does result in negative return values, so signal
837 no error by writing into the R0 slot. */
854 ldl $1, TASK_EUID($2)
866 ldl $1, TASK_EGID($2)
878 /* See linux/kernel/timer.c sys_getppid for discussion
880 ldq $3, TASK_GROUP_LEADER($2)
881 ldq $4, TASK_REAL_PARENT($3)
882 ldl $0, TASK_TGID($2)
883 1: ldl $1, TASK_TGID($4)
887 ldq $3, TASK_GROUP_LEADER($2)
888 ldq $4, TASK_REAL_PARENT($3)
910 /* The return values are in $0 and $20. */
925 jmp $31, do_sys_execve
929 .globl osf_sigprocmask
934 jmp $31, do_osf_sigprocmask
938 .globl alpha_ni_syscall
939 .ent alpha_ni_syscall
942 /* Special because it also implements overflow handling via
943 syscall number 0. And if you recall, zero is a special
944 trigger for "not an error". Store large non-zero there. */
949 .end alpha_ni_syscall