/* SPDX-License-Identifier: GPL-2.0 */
/*
* arch/alpha/kernel/entry.S
*
* Kernel entry-points.
*/
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/pal.h>
#include <asm/errno.h>
#include <asm/unistd.h>
.text
.set noat
.cfi_sections .debug_frame
.macro CFI_START_OSF_FRAME func
.align 4
.globl \func
.type \func,@function
\func:
.cfi_startproc simple
.cfi_return_column 64
.cfi_def_cfa $sp, 48
.cfi_rel_offset 64 , 8
.cfi_rel_offset $gp, 16
.cfi_rel_offset $16 , 24
.cfi_rel_offset $17 , 32
.cfi_rel_offset $18 , 40
.endm
.macro CFI_END_OSF_FRAME func
.cfi_endproc
.size \func, . - \func
.endm
/*
* This defines the normal kernel pt-regs layout.
*
* regs 9-15 preserved by C code
* regs 16-18 saved by PAL-code
* regs 29-30 saved and set up by PAL-code
* JRP - Save regs 16-18 in a special area of the stack, so that
* the palcode-provided values are available to the signal handler.
*/
.macro SAVE_ALL
subq $sp, SP_OFF, $sp
.cfi_adjust_cfa_offset SP_OFF
stq $0 , 0 ($sp)
stq $1 , 8 ($sp)
stq $2 , 16 ($sp)
stq $3 , 24 ($sp)
stq $4 , 32 ($sp)
stq $28 , 144 ($sp)
.cfi_rel_offset $0 , 0
.cfi_rel_offset $1 , 8
.cfi_rel_offset $2 , 16
.cfi_rel_offset $3 , 24
.cfi_rel_offset $4 , 32
.cfi_rel_offset $28 , 144
lda $2 , alpha_mv
stq $5 , 40 ($sp)
stq $6 , 48 ($sp)
stq $7 , 56 ($sp)
stq $8 , 64 ($sp)
stq $19 , 72 ($sp)
stq $20 , 80 ($sp)
stq $21 , 88 ($sp)
ldq $2 , HAE_CACHE($2 )
stq $22 , 96 ($sp)
stq $23 , 104 ($sp)
stq $24 , 112 ($sp)
stq $25 , 120 ($sp)
stq $26 , 128 ($sp)
stq $27 , 136 ($sp)
stq $2 , 152 ($sp)
stq $16 , 160 ($sp)
stq $17 , 168 ($sp)
stq $18 , 176 ($sp)
.cfi_rel_offset $5 , 40
.cfi_rel_offset $6 , 48
.cfi_rel_offset $7 , 56
.cfi_rel_offset $8 , 64
.cfi_rel_offset $19 , 72
.cfi_rel_offset $20 , 80
.cfi_rel_offset $21 , 88
.cfi_rel_offset $22 , 96
.cfi_rel_offset $23 , 104
.cfi_rel_offset $24 , 112
.cfi_rel_offset $25 , 120
.cfi_rel_offset $26 , 128
.cfi_rel_offset $27 , 136
.endm
.macro RESTORE_ALL
lda $19 , alpha_mv
ldq $0 , 0 ($sp)
ldq $1 , 8 ($sp)
ldq $2 , 16 ($sp)
ldq $3 , 24 ($sp)
ldq $21 , 152 ($sp)
ldq $20 , HAE_CACHE($19 )
ldq $4 , 32 ($sp)
ldq $5 , 40 ($sp)
ldq $6 , 48 ($sp)
ldq $7 , 56 ($sp)
subq $20 , $21 , $20
ldq $8 , 64 ($sp)
beq $20 , 99 f
ldq $20 , HAE_REG($19 )
stq $21 , HAE_CACHE($19 )
stq $21 , 0 ($20 )
99 : ldq $19 , 72 ($sp)
ldq $20 , 80 ($sp)
ldq $21 , 88 ($sp)
ldq $22 , 96 ($sp)
ldq $23 , 104 ($sp)
ldq $24 , 112 ($sp)
ldq $25 , 120 ($sp)
ldq $26 , 128 ($sp)
ldq $27 , 136 ($sp)
ldq $28 , 144 ($sp)
addq $sp, SP_OFF, $sp
.cfi_restore $0
.cfi_restore $1
.cfi_restore $2
.cfi_restore $3
.cfi_restore $4
.cfi_restore $5
.cfi_restore $6
.cfi_restore $7
.cfi_restore $8
.cfi_restore $19
.cfi_restore $20
.cfi_restore $21
.cfi_restore $22
.cfi_restore $23
.cfi_restore $24
.cfi_restore $25
.cfi_restore $26
.cfi_restore $27
.cfi_restore $28
.cfi_adjust_cfa_offset -SP_OFF
.endm
.macro DO_SWITCH_STACK
bsr $1 , do_switch_stack
.cfi_adjust_cfa_offset SWITCH_STACK_SIZE
.cfi_rel_offset $9 , 0
.cfi_rel_offset $10 , 8
.cfi_rel_offset $11 , 16
.cfi_rel_offset $12 , 24
.cfi_rel_offset $13 , 32
.cfi_rel_offset $14 , 40
.cfi_rel_offset $15 , 48
.endm
.macro UNDO_SWITCH_STACK
bsr $1 , undo_switch_stack
.cfi_restore $9
.cfi_restore $10
.cfi_restore $11
.cfi_restore $12
.cfi_restore $13
.cfi_restore $14
.cfi_restore $15
.cfi_adjust_cfa_offset -SWITCH_STACK_SIZE
.endm
/*
* Non-syscall kernel entry points.
*/
CFI_START_OSF_FRAME entInt
SAVE_ALL
lda $8 , 0 x3fff
lda $26 , ret_from_sys_call
bic $sp, $8 , $8
mov $sp, $19
jsr $31 , do_entInt
CFI_END_OSF_FRAME entInt
CFI_START_OSF_FRAME entArith
SAVE_ALL
lda $8 , 0 x3fff
lda $26 , ret_from_sys_call
bic $sp, $8 , $8
mov $sp, $18
jsr $31 , do_entArith
CFI_END_OSF_FRAME entArith
CFI_START_OSF_FRAME entMM
SAVE_ALL
/* save $9 - $15 so the inline exception code can manipulate them. */
subq $sp, 64 , $sp
.cfi_adjust_cfa_offset 64
stq $9 , 0 ($sp)
stq $10 , 8 ($sp)
stq $11 , 16 ($sp)
stq $12 , 24 ($sp)
stq $13 , 32 ($sp)
stq $14 , 40 ($sp)
stq $15 , 48 ($sp)
.cfi_rel_offset $9 , 0
.cfi_rel_offset $10 , 8
.cfi_rel_offset $11 , 16
.cfi_rel_offset $12 , 24
.cfi_rel_offset $13 , 32
.cfi_rel_offset $14 , 40
.cfi_rel_offset $15 , 48
addq $sp, 64 , $19
/* handle the fault */
lda $8 , 0 x3fff
bic $sp, $8 , $8
jsr $26 , do_page_fault
/* reload the registers after the exception code played. */
ldq $9 , 0 ($sp)
ldq $10 , 8 ($sp)
ldq $11 , 16 ($sp)
ldq $12 , 24 ($sp)
ldq $13 , 32 ($sp)
ldq $14 , 40 ($sp)
ldq $15 , 48 ($sp)
addq $sp, 64 , $sp
.cfi_restore $9
.cfi_restore $10
.cfi_restore $11
.cfi_restore $12
.cfi_restore $13
.cfi_restore $14
.cfi_restore $15
.cfi_adjust_cfa_offset -64
/* finish up the syscall as normal. */
br ret_from_sys_call
CFI_END_OSF_FRAME entMM
CFI_START_OSF_FRAME entIF
SAVE_ALL
lda $8 , 0 x3fff
lda $26 , ret_from_sys_call
bic $sp, $8 , $8
mov $sp, $17
jsr $31 , do_entIF
CFI_END_OSF_FRAME entIF
CFI_START_OSF_FRAME entUna
lda $sp, -256 ($sp)
.cfi_adjust_cfa_offset 256
stq $0 , 0 ($sp)
.cfi_rel_offset $0 , 0
.cfi_remember_state
ldq $0 , 256 ($sp) /* get PS */
stq $1 , 8 ($sp)
stq $2 , 16 ($sp)
stq $3 , 24 ($sp)
and $0 , 8 , $0 /* user mode? */
stq $4 , 32 ($sp)
bne $0 , entUnaUser /* yup -> do user-level unaligned fault */
stq $5 , 40 ($sp)
stq $6 , 48 ($sp)
stq $7 , 56 ($sp)
stq $8 , 64 ($sp)
stq $9 , 72 ($sp)
stq $10 , 80 ($sp)
stq $11 , 88 ($sp)
stq $12 , 96 ($sp)
stq $13 , 104 ($sp)
stq $14 , 112 ($sp)
stq $15 , 120 ($sp)
/* 16-18 PAL-saved */
stq $19 , 152 ($sp)
stq $20 , 160 ($sp)
stq $21 , 168 ($sp)
stq $22 , 176 ($sp)
stq $23 , 184 ($sp)
stq $24 , 192 ($sp)
stq $25 , 200 ($sp)
stq $26 , 208 ($sp)
stq $27 , 216 ($sp)
stq $28 , 224 ($sp)
mov $sp, $19
stq $gp, 232 ($sp)
.cfi_rel_offset $1 , 1 *8
.cfi_rel_offset $2 , 2 *8
.cfi_rel_offset $3 , 3 *8
.cfi_rel_offset $4 , 4 *8
.cfi_rel_offset $5 , 5 *8
.cfi_rel_offset $6 , 6 *8
.cfi_rel_offset $7 , 7 *8
.cfi_rel_offset $8 , 8 *8
.cfi_rel_offset $9 , 9 *8
.cfi_rel_offset $10 , 10 *8
.cfi_rel_offset $11 , 11 *8
.cfi_rel_offset $12 , 12 *8
.cfi_rel_offset $13 , 13 *8
.cfi_rel_offset $14 , 14 *8
.cfi_rel_offset $15 , 15 *8
.cfi_rel_offset $19 , 19 *8
.cfi_rel_offset $20 , 20 *8
.cfi_rel_offset $21 , 21 *8
.cfi_rel_offset $22 , 22 *8
.cfi_rel_offset $23 , 23 *8
.cfi_rel_offset $24 , 24 *8
.cfi_rel_offset $25 , 25 *8
.cfi_rel_offset $26 , 26 *8
.cfi_rel_offset $27 , 27 *8
.cfi_rel_offset $28 , 28 *8
.cfi_rel_offset $29 , 29 *8
lda $8 , 0 x3fff
stq $31 , 248 ($sp)
bic $sp, $8 , $8
jsr $26 , do_entUna
ldq $0 , 0 ($sp)
ldq $1 , 8 ($sp)
ldq $2 , 16 ($sp)
ldq $3 , 24 ($sp)
ldq $4 , 32 ($sp)
ldq $5 , 40 ($sp)
ldq $6 , 48 ($sp)
ldq $7 , 56 ($sp)
ldq $8 , 64 ($sp)
ldq $9 , 72 ($sp)
ldq $10 , 80 ($sp)
ldq $11 , 88 ($sp)
ldq $12 , 96 ($sp)
ldq $13 , 104 ($sp)
ldq $14 , 112 ($sp)
ldq $15 , 120 ($sp)
/* 16-18 PAL-saved */
ldq $19 , 152 ($sp)
ldq $20 , 160 ($sp)
ldq $21 , 168 ($sp)
ldq $22 , 176 ($sp)
ldq $23 , 184 ($sp)
ldq $24 , 192 ($sp)
ldq $25 , 200 ($sp)
ldq $26 , 208 ($sp)
ldq $27 , 216 ($sp)
ldq $28 , 224 ($sp)
ldq $gp, 232 ($sp)
lda $sp, 256 ($sp)
.cfi_restore $1
.cfi_restore $2
.cfi_restore $3
.cfi_restore $4
.cfi_restore $5
.cfi_restore $6
.cfi_restore $7
.cfi_restore $8
.cfi_restore $9
.cfi_restore $10
.cfi_restore $11
.cfi_restore $12
.cfi_restore $13
.cfi_restore $14
.cfi_restore $15
.cfi_restore $19
.cfi_restore $20
.cfi_restore $21
.cfi_restore $22
.cfi_restore $23
.cfi_restore $24
.cfi_restore $25
.cfi_restore $26
.cfi_restore $27
.cfi_restore $28
.cfi_restore $29
.cfi_adjust_cfa_offset -256
call_pal PAL_rti
.align 4
entUnaUser:
.cfi_restore_state
ldq $0 , 0 ($sp) /* restore original $0 */
lda $sp, 256 ($sp) /* pop entUna's stack frame */
.cfi_restore $0
.cfi_adjust_cfa_offset -256
SAVE_ALL /* setup normal kernel stack */
lda $sp, -64 ($sp)
.cfi_adjust_cfa_offset 64
stq $9 , 0 ($sp)
stq $10 , 8 ($sp)
stq $11 , 16 ($sp)
stq $12 , 24 ($sp)
stq $13 , 32 ($sp)
stq $14 , 40 ($sp)
stq $15 , 48 ($sp)
.cfi_rel_offset $9 , 0
.cfi_rel_offset $10 , 8
.cfi_rel_offset $11 , 16
.cfi_rel_offset $12 , 24
.cfi_rel_offset $13 , 32
.cfi_rel_offset $14 , 40
.cfi_rel_offset $15 , 48
lda $8 , 0 x3fff
addq $sp, 64 , $19
bic $sp, $8 , $8
jsr $26 , do_entUnaUser
ldq $9 , 0 ($sp)
ldq $10 , 8 ($sp)
ldq $11 , 16 ($sp)
ldq $12 , 24 ($sp)
ldq $13 , 32 ($sp)
ldq $14 , 40 ($sp)
ldq $15 , 48 ($sp)
lda $sp, 64 ($sp)
.cfi_restore $9
.cfi_restore $10
.cfi_restore $11
.cfi_restore $12
.cfi_restore $13
.cfi_restore $14
.cfi_restore $15
.cfi_adjust_cfa_offset -64
br ret_from_sys_call
CFI_END_OSF_FRAME entUna
CFI_START_OSF_FRAME entDbg
SAVE_ALL
lda $8 , 0 x3fff
lda $26 , ret_from_sys_call
bic $sp, $8 , $8
mov $sp, $16
jsr $31 , do_entDbg
CFI_END_OSF_FRAME entDbg
/*
* The system call entry point is special. Most importantly, it looks
* like a function call to userspace as far as clobbered registers. We
* do preserve the argument registers (for syscall restarts) and $26
* (for leaf syscall functions).
*
* So much for theory. We don't take advantage of this yet.
*
* Note that a0-a2 are not saved by PALcode as with the other entry points.
*/
.align 4
.globl entSys
.type entSys, @function
.cfi_startproc simple
.cfi_return_column 64
.cfi_def_cfa $sp, 48
.cfi_rel_offset 64 , 8
.cfi_rel_offset $gp, 16
entSys:
SAVE_ALL
lda $8 , 0 x3fff
bic $sp, $8 , $8
lda $4 , NR_syscalls($31 )
stq $16 , SP_OFF+24 ($sp)
lda $5 , sys_call_table
lda $27 , sys_ni_syscall
cmpult $0 , $4 , $4
ldl $3 , TI_FLAGS($8 )
stq $17 , SP_OFF+32 ($sp)
s8addq $0 , $5 , $5
stq $18 , SP_OFF+40 ($sp)
.cfi_rel_offset $16 , SP_OFF+24
.cfi_rel_offset $17 , SP_OFF+32
.cfi_rel_offset $18 , SP_OFF+40
#ifdef CONFIG_AUDITSYSCALL
lda $6 , _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
and $3 , $6 , $3
bne $3 , strace
#else
blbs $3 , strace /* check for SYSCALL_TRACE in disguise */
#endif
beq $4 , 1 f
ldq $27 , 0 ($5 )
1 : jsr $26 , ($27 ), sys_ni_syscall
ldgp $gp, 0 ($26 )
blt $0 , $syscall_error /* the call failed */
$ret_success:
stq $0 , 0 ($sp)
stq $31 , 72 ($sp) /* a3=0 => no error */
.align 4
.globl ret_from_sys_call
ret_from_sys_call:
cmovne $26 , 0 , $18 /* $18 = 0 => non-restartable */
ldq $0 , SP_OFF($sp)
and $0 , 8 , $0
beq $0 , ret_to_kernel
ret_to_user:
/* Make sure need_resched and sigpending don't change between
sampling and the rti. */
lda $16 , 7
call_pal PAL_swpipl
ldl $17 , TI_FLAGS($8 )
and $17 , _TIF_WORK_MASK, $2
bne $2 , work_pending
restore_all:
ldl $2 , TI_STATUS($8 )
and $2 , TS_SAVED_FP | TS_RESTORE_FP, $3
bne $3 , restore_fpu
restore_other:
.cfi_remember_state
RESTORE_ALL
call_pal PAL_rti
ret_to_kernel:
.cfi_restore_state
lda $16 , 7
call_pal PAL_swpipl
br restore_other
.align 3
$syscall_error:
/*
* Some system calls (e.g., ptrace) can return arbitrary
* values which might normally be mistaken as error numbers.
* Those functions must zero $0 (v0) directly in the stack
* frame to indicate that a negative return value wasn't an
* error number..
*/
ldq $18 , 0 ($sp) /* old syscall nr (zero if success) */
beq $18 , $ret_success
ldq $19 , 72 ($sp) /* .. and this a3 */
subq $31 , $0 , $0 /* with error in v0 */
addq $31 , 1 , $1 /* set a3 for errno return */
stq $0 , 0 ($sp)
mov $31 , $26 /* tell "ret_from_sys_call" we can restart */
stq $1 , 72 ($sp) /* a3 for return */
br ret_from_sys_call
/*
* Do all cleanup when returning from all interrupts and system calls.
*
* Arguments:
* $8: current.
* $17: TI_FLAGS.
* $18: The old syscall number, or zero if this is not a return
* from a syscall that errored and is possibly restartable.
* $19: The old a3 value
*/
.align 4
.type work_pending, @function
work_pending:
and $17 , _TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL, $2
bne $2 , $work_notifysig
$work_resched:
/*
* We can get here only if we returned from syscall without SIGPENDING
* or got through work_notifysig already. Either case means no syscall
* restarts for us, so let $18 and $19 burn.
*/
jsr $26 , schedule
mov 0 , $18
br ret_to_user
$work_notifysig:
mov $sp, $16
DO_SWITCH_STACK
jsr $26 , do_work_pending
UNDO_SWITCH_STACK
br restore_all
/*
* PTRACE syscall handler
*/
.align 4
.type strace, @function
strace:
/* set up signal stack, call syscall_trace */
// NB: if anyone adds preemption, this block will need to be protected
ldl $1 , TI_STATUS($8 )
and $1 , TS_SAVED_FP, $3
or $1 , TS_SAVED_FP, $2
bne $3 , 1 f
stl $2 , TI_STATUS($8 )
bsr $26 , __save_fpu
1 :
DO_SWITCH_STACK
jsr $26 , syscall_trace_enter /* returns the syscall number */
UNDO_SWITCH_STACK
/* get the arguments back.. */
ldq $16 , SP_OFF+24 ($sp)
ldq $17 , SP_OFF+32 ($sp)
ldq $18 , SP_OFF+40 ($sp)
ldq $19 , 72 ($sp)
ldq $20 , 80 ($sp)
ldq $21 , 88 ($sp)
/* get the system call pointer.. */
lda $1 , NR_syscalls($31 )
lda $2 , sys_call_table
lda $27 , sys_ni_syscall
cmpult $0 , $1 , $1
s8addq $0 , $2 , $2
beq $1 , 1 f
ldq $27 , 0 ($2 )
1 : jsr $26 , ($27 ), sys_gettimeofday
ret_from_straced:
ldgp $gp, 0 ($26 )
/* check return.. */
blt $0 , $strace_error /* the call failed */
$strace_success:
stq $31 , 72 ($sp) /* a3=0 => no error */
stq $0 , 0 ($sp) /* save return value */
DO_SWITCH_STACK
jsr $26 , syscall_trace_leave
UNDO_SWITCH_STACK
br $31 , ret_from_sys_call
.align 3
$strace_error:
ldq $18 , 0 ($sp) /* old syscall nr (zero if success) */
beq $18 , $strace_success
ldq $19 , 72 ($sp) /* .. and this a3 */
subq $31 , $0 , $0 /* with error in v0 */
addq $31 , 1 , $1 /* set a3 for errno return */
stq $0 , 0 ($sp)
stq $1 , 72 ($sp) /* a3 for return */
DO_SWITCH_STACK
mov $18 , $9 /* save old syscall number */
mov $19 , $10 /* save old a3 */
jsr $26 , syscall_trace_leave
mov $9 , $18
mov $10 , $19
UNDO_SWITCH_STACK
mov $31 , $26 /* tell "ret_from_sys_call" we can restart */
br ret_from_sys_call
CFI_END_OSF_FRAME entSys
/*
* Save and restore the switch stack -- aka the balance of the user context.
*/
.align 4
.type do_switch_stack, @function
.cfi_startproc simple
.cfi_return_column 64
.cfi_def_cfa $sp, 0
.cfi_register 64 , $1
do_switch_stack:
lda $sp, -SWITCH_STACK_SIZE($sp)
.cfi_adjust_cfa_offset SWITCH_STACK_SIZE
stq $9 , 0 ($sp)
stq $10 , 8 ($sp)
stq $11 , 16 ($sp)
stq $12 , 24 ($sp)
stq $13 , 32 ($sp)
stq $14 , 40 ($sp)
stq $15 , 48 ($sp)
stq $26 , 56 ($sp)
ret $31 , ($1 ), 1
.cfi_endproc
.size do_switch_stack, .-do_switch_stack
.align 4
.type undo_switch_stack, @function
.cfi_startproc simple
.cfi_def_cfa $sp, 0
.cfi_register 64 , $1
undo_switch_stack:
ldq $9 , 0 ($sp)
ldq $10 , 8 ($sp)
ldq $11 , 16 ($sp)
ldq $12 , 24 ($sp)
ldq $13 , 32 ($sp)
ldq $14 , 40 ($sp)
ldq $15 , 48 ($sp)
ldq $26 , 56 ($sp)
lda $sp, SWITCH_STACK_SIZE($sp)
ret $31 , ($1 ), 1
.cfi_endproc
.size undo_switch_stack, .-undo_switch_stack
#define FR(n) n * 8 + TI_FP($8 )
.align 4
.globl __save_fpu
.type __save_fpu, @function
__save_fpu:
#define V(n) stt $f##n, FR(n)
V( 0 ); V( 1 ); V( 2 ); V( 3 )
V( 4 ); V( 5 ); V( 6 ); V( 7 )
V( 8 ); V( 9 ); V(10 ); V(11 )
V(12 ); V(13 ); V(14 ); V(15 )
V(16 ); V(17 ); V(18 ); V(19 )
V(20 ); V(21 ); V(22 ); V(23 )
V(24 ); V(25 ); V(26 ); V(27 )
mf_fpcr $f0 # get fpcr
V(28 ); V(29 ); V(30 )
stt $f0, FR(31 ) # save fpcr in slot of $f31
ldt $f0, FR(0 ) # don't let "__save_fpu" change fp state.
ret
#undef V
.size __save_fpu, .-__save_fpu
.align 4
restore_fpu:
and $3 , TS_RESTORE_FP, $3
bic $2 , TS_SAVED_FP | TS_RESTORE_FP, $2
beq $3 , 1 f
#define V(n) ldt $f##n, FR(n)
ldt $f30, FR(31 ) # get saved fpcr
V( 0 ); V( 1 ); V( 2 ); V( 3 )
mt_fpcr $f30 # install saved fpcr
V( 4 ); V( 5 ); V( 6 ); V( 7 )
V( 8 ); V( 9 ); V(10 ); V(11 )
V(12 ); V(13 ); V(14 ); V(15 )
V(16 ); V(17 ); V(18 ); V(19 )
V(20 ); V(21 ); V(22 ); V(23 )
V(24 ); V(25 ); V(26 ); V(27 )
V(28 ); V(29 ); V(30 )
1 : stl $2 , TI_STATUS($8 )
br restore_other
#undef V
/*
* The meat of the context switch code.
*/
.align 4
.globl alpha_switch_to
.type alpha_switch_to, @function
.cfi_startproc
alpha_switch_to:
DO_SWITCH_STACK
ldl $1 , TI_STATUS($8 )
and $1 , TS_RESTORE_FP, $3
bne $3 , 1 f
or $1 , TS_RESTORE_FP | TS_SAVED_FP, $2
and $1 , TS_SAVED_FP, $3
stl $2 , TI_STATUS($8 )
bne $3 , 1 f
bsr $26 , __save_fpu
1 :
call_pal PAL_swpctx
lda $8 , 0 x3fff
UNDO_SWITCH_STACK
bic $sp, $8 , $8
mov $17 , $0
ret
.cfi_endproc
.size alpha_switch_to, .-alpha_switch_to
/*
* New processes begin life here.
*/
.globl ret_from_fork
.align 4
.ent ret_from_fork
ret_from_fork:
lda $26 , ret_to_user
mov $17 , $16
jmp $31 , schedule_tail
.end ret_from_fork
/*
* ... and new kernel threads - here
*/
.align 4
.globl ret_from_kernel_thread
.ent ret_from_kernel_thread
ret_from_kernel_thread:
mov $17 , $16
jsr $26 , schedule_tail
mov $9 , $27
mov $10 , $16
jsr $26 , ($9 )
br $31 , ret_to_user
.end ret_from_kernel_thread
/*
* Special system calls. Most of these are special in that they either
* have to play switch_stack games.
*/
.macro fork_like name
.align 4
.globl alpha_\name
.ent alpha_\name
alpha_\name:
.prologue 0
bsr $1 , do_switch_stack
// NB: if anyone adds preemption, this block will need to be protected
ldl $1 , TI_STATUS($8 )
and $1 , TS_SAVED_FP, $3
or $1 , TS_SAVED_FP, $2
bne $3 , 1 f
stl $2 , TI_STATUS($8 )
bsr $26 , __save_fpu
1 :
jsr $26 , sys_\name
ldq $26 , 56 ($sp)
lda $sp, SWITCH_STACK_SIZE($sp)
ret
.end alpha_\name
.endm
fork_like fork
fork_like vfork
fork_like clone
fork_like clone3
.macro sigreturn_like name
.align 4
.globl sys_\name
.ent sys_\name
sys_\name:
.prologue 0
lda $9 , ret_from_straced
cmpult $26 , $9 , $9
lda $sp, -SWITCH_STACK_SIZE($sp)
jsr $26 , do_\name
bne $9 , 1 f
jsr $26 , syscall_trace_leave
1 : br $1 , undo_switch_stack
br ret_from_sys_call
.end sys_\name
.endm
sigreturn_like sigreturn
sigreturn_like rt_sigreturn
.align 4
.globl alpha_syscall_zero
.ent alpha_syscall_zero
alpha_syscall_zero:
.prologue 0
/* Special because it needs to do something opposite to
force_successful_syscall_return(). We use the saved
syscall number for that, zero meaning "not an error".
That works nicely, but for real syscall 0 we need to
make sure that this logics doesn't get confused.
Store a non-zero there - -ENOSYS we need in register
for our return value will do just fine.
*/
lda $0 , -ENOSYS
unop
stq $0 , 0 ($sp)
ret
.end alpha_syscall_zero
Messung V0.5 in Prozent C=93 H=90 G=91
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-07)
¤
*© Formatika GbR, Deutschland