Something went wrong. Try again.
Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929/* 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>#include <linux/errno.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
/* * SYSCALL_SKIP_RETURN_RESTART_GATE * * Used when syscall dispatch is skipped (seccomp/ptrace injected nr=-1). * - Ensure we never return r0==-1 with a3==0 (success); convert to ENOSYS. * - Gate whether syscall restart is allowed by preserving restart context * only for ERESTART* returns. Result: * $26 = 0 => restart allowed * $26 = 1 => restart NOT allowed * $18 = preserved syscall nr (regs->r2) if restart allowed, else 0 */.macro SYSCALL_SKIP_RETURN_RESTART_GATE /* Fix up invalid "-1 success" return state. */ ldq $19, 72($sp) /* a3 */ bne $19, 1f /* already error => skip fixup */
ldq $20, 0($sp) /* r0 */ lda $21, -1($31) cmpeq $20, $21, $22 beq $22, 1f /* r0 != -1 => skip fixup */
lda $20, ENOSYS($31) stq $20, 0($sp) /* r0 = ENOSYS */ lda $19, 1($31) stq $19, 72($sp) /* a3 = 1 */1: /* Restart gating: success is never restartable here. */ ldq $19, 72($sp) /* a3 */ beq $19, 3f /* success => not restartable */
ldq $20, 0($sp) /* r0 (positive errno if a3==1) */ lda $21, ERESTARTSYS($31) cmpeq $20, $21, $22 bne $22, 2f lda $21, ERESTARTNOINTR($31) cmpeq $20, $21, $22 bne $22, 2f lda $21, ERESTARTNOHAND($31) cmpeq $20, $21, $22 bne $22, 2f lda $21, ERESTART_RESTARTBLOCK($31) cmpeq $20, $21, $22 bne $22, 2f
3: /* Not a restart code (or success) => restart NOT allowed. */ addq $31, 1, $26 /* $26=1 => restart NOT allowed */ mov 0, $18 br 4f
2: /* Restart allowed. */ ldq $18, 16($sp) /* preserved syscall nr (regs->r2) */ mov $31, $26 /* $26=0 => restart allowed */ br 4f4:.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, 99f 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, 0x3fff lda $26, ret_from_sys_call bic $sp, $8, $8 mov $sp, $19 jsr $31, do_entIntCFI_END_OSF_FRAME entInt
CFI_START_OSF_FRAME entArith SAVE_ALL lda $8, 0x3fff lda $26, ret_from_sys_call bic $sp, $8, $8 mov $sp, $18 jsr $31, do_entArithCFI_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, 0x3fff 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_callCFI_END_OSF_FRAME entMM
CFI_START_OSF_FRAME entIF SAVE_ALL lda $8, 0x3fff lda $26, ret_from_sys_call bic $sp, $8, $8 mov $sp, $17 jsr $31, do_entIFCFI_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, 0x3fff 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 4entUnaUser: .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, 0x3fff 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_callCFI_END_OSF_FRAME entUna
CFI_START_OSF_FRAME entDbg SAVE_ALL lda $8, 0x3fff lda $26, ret_from_sys_call bic $sp, $8, $8 mov $sp, $16 jsr $31, do_entDbgCFI_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. * * Alpha syscall ABI uses: * - r0 for return value * - r19 ("a3") as error indicator (0=success, 1=error; r0 holds errno) * * For seccomp/ptrace/generic syscall helpers we track the syscall * number separately: * - regs->r1: current (mutable) syscall number (may be changed or set to -1) * - regs->r2: original syscall number for restart/rollback * * On entry PAL provides the syscall number in r0; copy it into r1/r2. */
.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, 16entSys: SAVE_ALL ldq $1, 0($sp) /* syscall nr from saved r0 */ stq $1, 8($sp) /* regs->r1 = shadow syscall nr */ stq $1, 16($sp) /* regs->r2 = restart syscall nr */
lda $8, 0x3fff 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 | _TIF_SECCOMP and $3, $6, $3 bne $3, strace#else lda $6, _TIF_SYSCALL_TRACE | _TIF_SECCOMP and $3, $6, $3 bne $3, strace#endif beq $4, 1f ldq $27, 0($5)1: ldq $0, 8($sp) /* syscall nr shadow (regs->r1) */
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_callret_from_sys_call: cmovne $26, 0, $18 /* $18 = 0 => non-restartable */ ldq $0, SP_OFF($sp) and $0, 8, $0 beq $0, ret_to_kernelret_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_pendingrestore_all: ldl $2, TI_STATUS($8) and $2, TS_SAVED_FP | TS_RESTORE_FP, $3 bne $3, restore_fpurestore_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: /* Restart syscall nr comes from saved r2 (preserved even if r0 overwritten). */ ldq $18, 16($sp) /* old syscall nr for restart */
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, @functionwork_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, @functionstrace: /* 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, 1f stl $2, TI_STATUS($8) bsr $26, __save_fpu1: DO_SWITCH_STACK jsr $26, syscall_trace_enter /* returns the syscall number */ UNDO_SWITCH_STACK
stq $0, 8($sp) /* regs->r1 = shadow syscall nr */
/* 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)
/* nr == -1: internal skip-dispatch or userspace syscall(-1)? */ lda $6, -1($31) cmpeq $0, $6, $6 bne $6, $strace_skip_call /* nr == -1 => dispatch */
/* 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, 1f ldq $27, 0($2)1: jsr $26, ($27), sys_gettimeofdayret_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 */
$strace_skip_call: SYSCALL_SKIP_RETURN_RESTART_GATE DO_SWITCH_STACK jsr $26, syscall_trace_leave UNDO_SWITCH_STACK br $31, ret_from_sys_call
.align 3$strace_error: ldq $18, 16($sp) /* restart syscall nr */ 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_callCFI_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, $1do_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, $1undo_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 4restore_fpu: and $3, TS_RESTORE_FP, $3 bic $2, TS_SAVED_FP | TS_RESTORE_FP, $2 beq $3, 1f#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_startprocalpha_switch_to: DO_SWITCH_STACK ldl $1, TI_STATUS($8) and $1, TS_RESTORE_FP, $3 bne $3, 1f or $1, TS_RESTORE_FP | TS_SAVED_FP, $2 and $1, TS_SAVED_FP, $3 stl $2, TI_STATUS($8) bne $3, 1f bsr $26, __save_fpu1: call_pal PAL_swpctx lda $8, 0x3fff 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_forkret_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_threadret_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_\namealpha_\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, 1f stl $2, TI_STATUS($8) bsr $26, __save_fpu1: jsr $26, sys_\name ldq $26, 56($sp) lda $sp, SWITCH_STACK_SIZE($sp) ret.end alpha_\name.endm
fork_like forkfork_like vforkfork_like clonefork_like clone3
.macro sigreturn_like name .align 4 .globl sys_\name .ent sys_\namesys_\name: .prologue 0 lda $9, ret_from_straced cmpult $26, $9, $9 lda $sp, -SWITCH_STACK_SIZE($sp) jsr $26, do_\name bne $9, 1f jsr $26, syscall_trace_leave1: br $1, undo_switch_stack br ret_from_sys_call.end sys_\name.endm
sigreturn_like sigreturnsigreturn_like rt_sigreturn
.align 4 .globl alpha_syscall_zero .ent alpha_syscall_zeroalpha_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