2005-04-16 15:20:36 -07:00
/ *
* arch/ a l p h a / k e r n e l / e n t r y . S
*
* Kernel e n t r y - p o i n t s .
* /
2005-09-09 21:28:48 +02:00
# include < a s m / a s m - o f f s e t s . h >
2005-04-16 15:20:36 -07:00
# include < a s m / t h r e a d _ i n f o . h >
# include < a s m / p a l . h >
# include < a s m / e r r n o . h >
# include < a s m / u n i s t d . h >
.text
.set noat
/* Stack offsets. */
# define S P _ O F F 1 8 4
# define S W I T C H _ S T A C K _ S I Z E 3 2 0
/ *
* This d e f i n e s t h e n o r m a l k e r n e l p t - r e g s l a y o u t .
*
* regs 9 - 1 5 p r e s e r v e d b y C c o d e
* regs 1 6 - 1 8 s a v e d b y P A L - c o d e
* regs 2 9 - 3 0 s a v e d a n d s e t u p b y P A L - c o d e
* JRP - S a v e r e g s 1 6 - 1 8 i n a s p e c i a l a r e a o f t h e s t a c k , s o t h a t
* the p a l c o d e - p r o v i d e d v a l u e s a r e a v a i l a b l e t o t h e s i g n a l h a n d l e r .
* /
# define S A V E _ A L L \
subq $ s p , S P _ O F F , $ s p ; \
stq $ 0 , 0 ( $ s p ) ; \
stq $ 1 , 8 ( $ s p ) ; \
stq $ 2 , 1 6 ( $ s p ) ; \
stq $ 3 , 2 4 ( $ s p ) ; \
stq $ 4 , 3 2 ( $ s p ) ; \
stq $ 2 8 , 1 4 4 ( $ s p ) ; \
lda $ 2 , a l p h a _ m v ; \
stq $ 5 , 4 0 ( $ s p ) ; \
stq $ 6 , 4 8 ( $ s p ) ; \
stq $ 7 , 5 6 ( $ s p ) ; \
stq $ 8 , 6 4 ( $ s p ) ; \
stq $ 1 9 , 7 2 ( $ s p ) ; \
stq $ 2 0 , 8 0 ( $ s p ) ; \
stq $ 2 1 , 8 8 ( $ s p ) ; \
ldq $ 2 , H A E _ C A C H E ( $ 2 ) ; \
stq $ 2 2 , 9 6 ( $ s p ) ; \
stq $ 2 3 , 1 0 4 ( $ s p ) ; \
stq $ 2 4 , 1 1 2 ( $ s p ) ; \
stq $ 2 5 , 1 2 0 ( $ s p ) ; \
stq $ 2 6 , 1 2 8 ( $ s p ) ; \
stq $ 2 7 , 1 3 6 ( $ s p ) ; \
stq $ 2 , 1 5 2 ( $ s p ) ; \
stq $ 1 6 , 1 6 0 ( $ s p ) ; \
stq $ 1 7 , 1 6 8 ( $ s p ) ; \
stq $ 1 8 , 1 7 6 ( $ s p )
# define R E S T O R E _ A L L \
lda $ 1 9 , a l p h a _ m v ; \
ldq $ 0 , 0 ( $ s p ) ; \
ldq $ 1 , 8 ( $ s p ) ; \
ldq $ 2 , 1 6 ( $ s p ) ; \
ldq $ 3 , 2 4 ( $ s p ) ; \
ldq $ 2 1 , 1 5 2 ( $ s p ) ; \
ldq $ 2 0 , H A E _ C A C H E ( $ 1 9 ) ; \
ldq $ 4 , 3 2 ( $ s p ) ; \
ldq $ 5 , 4 0 ( $ s p ) ; \
ldq $ 6 , 4 8 ( $ s p ) ; \
ldq $ 7 , 5 6 ( $ s p ) ; \
subq $ 2 0 , $ 2 1 , $ 2 0 ; \
ldq $ 8 , 6 4 ( $ s p ) ; \
beq $ 2 0 , 9 9 f ; \
ldq $ 2 0 , H A E _ R E G ( $ 1 9 ) ; \
stq $ 2 1 , H A E _ C A C H E ( $ 1 9 ) ; \
stq $ 2 1 , 0 ( $ 2 0 ) ; \
99 : ; \
ldq $ 1 9 , 7 2 ( $ s p ) ; \
ldq $ 2 0 , 8 0 ( $ s p ) ; \
ldq $ 2 1 , 8 8 ( $ s p ) ; \
ldq $ 2 2 , 9 6 ( $ s p ) ; \
ldq $ 2 3 , 1 0 4 ( $ s p ) ; \
ldq $ 2 4 , 1 1 2 ( $ s p ) ; \
ldq $ 2 5 , 1 2 0 ( $ s p ) ; \
ldq $ 2 6 , 1 2 8 ( $ s p ) ; \
ldq $ 2 7 , 1 3 6 ( $ s p ) ; \
ldq $ 2 8 , 1 4 4 ( $ s p ) ; \
addq $ s p , S P _ O F F , $ s p
/ *
* Non- s y s c a l l k e r n e l e n t r y p o i n t s .
* /
.align 4
.globl entInt
.ent entInt
entInt :
SAVE_ A L L
lda $ 8 , 0 x3 f f f
lda $ 2 6 , r e t _ f r o m _ s y s _ c a l l
bic $ s p , $ 8 , $ 8
mov $ s p , $ 1 9
jsr $ 3 1 , d o _ e n t I n t
.end entInt
.align 4
.globl entArith
.ent entArith
entArith :
SAVE_ A L L
lda $ 8 , 0 x3 f f f
lda $ 2 6 , r e t _ f r o m _ s y s _ c a l l
bic $ s p , $ 8 , $ 8
mov $ s p , $ 1 8
jsr $ 3 1 , d o _ e n t A r i t h
.end entArith
.align 4
.globl entMM
.ent entMM
entMM :
SAVE_ A L L
/* save $9 - $15 so the inline exception code can manipulate them. */
subq $ s p , 5 6 , $ s p
stq $ 9 , 0 ( $ s p )
stq $ 1 0 , 8 ( $ s p )
stq $ 1 1 , 1 6 ( $ s p )
stq $ 1 2 , 2 4 ( $ s p )
stq $ 1 3 , 3 2 ( $ s p )
stq $ 1 4 , 4 0 ( $ s p )
stq $ 1 5 , 4 8 ( $ s p )
addq $ s p , 5 6 , $ 1 9
/* handle the fault */
lda $ 8 , 0 x3 f f f
bic $ s p , $ 8 , $ 8
jsr $ 2 6 , d o _ p a g e _ f a u l t
/* reload the registers after the exception code played. */
ldq $ 9 , 0 ( $ s p )
ldq $ 1 0 , 8 ( $ s p )
ldq $ 1 1 , 1 6 ( $ s p )
ldq $ 1 2 , 2 4 ( $ s p )
ldq $ 1 3 , 3 2 ( $ s p )
ldq $ 1 4 , 4 0 ( $ s p )
ldq $ 1 5 , 4 8 ( $ s p )
addq $ s p , 5 6 , $ s p
/* finish up the syscall as normal. */
br r e t _ f r o m _ s y s _ c a l l
.end entMM
.align 4
.globl entIF
.ent entIF
entIF :
SAVE_ A L L
lda $ 8 , 0 x3 f f f
lda $ 2 6 , r e t _ f r o m _ s y s _ c a l l
bic $ s p , $ 8 , $ 8
mov $ s p , $ 1 7
jsr $ 3 1 , d o _ e n t I F
.end entIF
.align 4
.globl entUna
.ent entUna
entUna :
lda $ s p , - 2 5 6 ( $ s p )
stq $ 0 , 0 ( $ s p )
ldq $ 0 , 2 5 6 ( $ s p ) / * g e t P S * /
stq $ 1 , 8 ( $ s p )
stq $ 2 , 1 6 ( $ s p )
stq $ 3 , 2 4 ( $ s p )
and $ 0 , 8 , $ 0 / * u s e r m o d e ? * /
stq $ 4 , 3 2 ( $ s p )
bne $ 0 , e n t U n a U s e r / * y u p - > d o u s e r - l e v e l u n a l i g n e d f a u l t * /
stq $ 5 , 4 0 ( $ s p )
stq $ 6 , 4 8 ( $ s p )
stq $ 7 , 5 6 ( $ s p )
stq $ 8 , 6 4 ( $ s p )
stq $ 9 , 7 2 ( $ s p )
stq $ 1 0 , 8 0 ( $ s p )
stq $ 1 1 , 8 8 ( $ s p )
stq $ 1 2 , 9 6 ( $ s p )
stq $ 1 3 , 1 0 4 ( $ s p )
stq $ 1 4 , 1 1 2 ( $ s p )
stq $ 1 5 , 1 2 0 ( $ s p )
/* 16-18 PAL-saved */
stq $ 1 9 , 1 5 2 ( $ s p )
stq $ 2 0 , 1 6 0 ( $ s p )
stq $ 2 1 , 1 6 8 ( $ s p )
stq $ 2 2 , 1 7 6 ( $ s p )
stq $ 2 3 , 1 8 4 ( $ s p )
stq $ 2 4 , 1 9 2 ( $ s p )
stq $ 2 5 , 2 0 0 ( $ s p )
stq $ 2 6 , 2 0 8 ( $ s p )
stq $ 2 7 , 2 1 6 ( $ s p )
stq $ 2 8 , 2 2 4 ( $ s p )
2005-10-02 12:49:52 -07:00
mov $ s p , $ 1 9
2005-04-16 15:20:36 -07:00
stq $ g p , 2 3 2 ( $ s p )
lda $ 8 , 0 x3 f f f
stq $ 3 1 , 2 4 8 ( $ s p )
bic $ s p , $ 8 , $ 8
jsr $ 2 6 , d o _ e n t U n a
ldq $ 0 , 0 ( $ s p )
ldq $ 1 , 8 ( $ s p )
ldq $ 2 , 1 6 ( $ s p )
ldq $ 3 , 2 4 ( $ s p )
ldq $ 4 , 3 2 ( $ s p )
ldq $ 5 , 4 0 ( $ s p )
ldq $ 6 , 4 8 ( $ s p )
ldq $ 7 , 5 6 ( $ s p )
ldq $ 8 , 6 4 ( $ s p )
ldq $ 9 , 7 2 ( $ s p )
ldq $ 1 0 , 8 0 ( $ s p )
ldq $ 1 1 , 8 8 ( $ s p )
ldq $ 1 2 , 9 6 ( $ s p )
ldq $ 1 3 , 1 0 4 ( $ s p )
ldq $ 1 4 , 1 1 2 ( $ s p )
ldq $ 1 5 , 1 2 0 ( $ s p )
/* 16-18 PAL-saved */
ldq $ 1 9 , 1 5 2 ( $ s p )
ldq $ 2 0 , 1 6 0 ( $ s p )
ldq $ 2 1 , 1 6 8 ( $ s p )
ldq $ 2 2 , 1 7 6 ( $ s p )
ldq $ 2 3 , 1 8 4 ( $ s p )
ldq $ 2 4 , 1 9 2 ( $ s p )
ldq $ 2 5 , 2 0 0 ( $ s p )
ldq $ 2 6 , 2 0 8 ( $ s p )
ldq $ 2 7 , 2 1 6 ( $ s p )
ldq $ 2 8 , 2 2 4 ( $ s p )
ldq $ g p , 2 3 2 ( $ s p )
lda $ s p , 2 5 6 ( $ s p )
call_ p a l P A L _ r t i
.end entUna
.align 4
.ent entUnaUser
entUnaUser :
ldq $ 0 , 0 ( $ s p ) / * r e s t o r e o r i g i n a l $ 0 * /
lda $ s p , 2 5 6 ( $ s p ) / * p o p e n t U n a ' s s t a c k f r a m e * /
SAVE_ A L L / * s e t u p n o r m a l k e r n e l s t a c k * /
lda $ s p , - 5 6 ( $ s p )
stq $ 9 , 0 ( $ s p )
stq $ 1 0 , 8 ( $ s p )
stq $ 1 1 , 1 6 ( $ s p )
stq $ 1 2 , 2 4 ( $ s p )
stq $ 1 3 , 3 2 ( $ s p )
stq $ 1 4 , 4 0 ( $ s p )
stq $ 1 5 , 4 8 ( $ s p )
lda $ 8 , 0 x3 f f f
addq $ s p , 5 6 , $ 1 9
bic $ s p , $ 8 , $ 8
jsr $ 2 6 , d o _ e n t U n a U s e r
ldq $ 9 , 0 ( $ s p )
ldq $ 1 0 , 8 ( $ s p )
ldq $ 1 1 , 1 6 ( $ s p )
ldq $ 1 2 , 2 4 ( $ s p )
ldq $ 1 3 , 3 2 ( $ s p )
ldq $ 1 4 , 4 0 ( $ s p )
ldq $ 1 5 , 4 8 ( $ s p )
lda $ s p , 5 6 ( $ s p )
br r e t _ f r o m _ s y s _ c a l l
.end entUnaUser
.align 4
.globl entDbg
.ent entDbg
entDbg :
SAVE_ A L L
lda $ 8 , 0 x3 f f f
lda $ 2 6 , r e t _ f r o m _ s y s _ c a l l
bic $ s p , $ 8 , $ 8
mov $ s p , $ 1 6
jsr $ 3 1 , d o _ e n t D b g
.end entDbg
/ *
* The s y s t e m c a l l e n t r y p o i n t i s s p e c i a l . M o s t i m p o r t a n t l y , i t l o o k s
* like a f u n c t i o n c a l l t o u s e r s p a c e a s f a r a s c l o b b e r e d r e g i s t e r s . W e
* do p r e s e r v e t h e a r g u m e n t r e g i s t e r s ( f o r s y s c a l l r e s t a r t s ) a n d $ 2 6
* ( for l e a f s y s c a l l f u n c t i o n s ) .
*
* So m u c h f o r t h e o r y . W e d o n ' t t a k e a d v a n t a g e o f t h i s y e t .
*
* Note t h a t a0 - a2 a r e n o t s a v e d b y P A L c o d e a s w i t h t h e o t h e r e n t r y p o i n t s .
* /
.align 4
.globl entSys
.globl ret_from_sys_call
.ent entSys
entSys :
SAVE_ A L L
lda $ 8 , 0 x3 f f f
bic $ s p , $ 8 , $ 8
lda $ 4 , N R _ S Y S C A L L S ( $ 3 1 )
stq $ 1 6 , S P _ O F F + 2 4 ( $ s p )
lda $ 5 , s y s _ c a l l _ t a b l e
lda $ 2 7 , s y s _ n i _ s y s c a l l
cmpult $ 0 , $ 4 , $ 4
ldl $ 3 , T I _ F L A G S ( $ 8 )
stq $ 1 7 , S P _ O F F + 3 2 ( $ s p )
s8 a d d q $ 0 , $ 5 , $ 5
stq $ 1 8 , S P _ O F F + 4 0 ( $ s p )
blbs $ 3 , s t r a c e
beq $ 4 , 1 f
ldq $ 2 7 , 0 ( $ 5 )
1 : jsr $ 2 6 , ( $ 2 7 ) , a l p h a _ n i _ s y s c a l l
ldgp $ g p , 0 ( $ 2 6 )
blt $ 0 , $ s y s c a l l _ e r r o r / * t h e c a l l f a i l e d * /
stq $ 0 , 0 ( $ s p )
stq $ 3 1 , 7 2 ( $ s p ) / * a3 =0 = > n o e r r o r * /
.align 4
ret_from_sys_call :
cmovne $ 2 6 , 0 , $ 1 9 / * $ 1 9 = 0 = > n o n - r e s t a r t a b l e * /
ldq $ 0 , S P _ O F F ( $ s p )
and $ 0 , 8 , $ 0
2010-09-25 21:07:14 +01:00
beq $ 0 , r e t _ t o _ k e r n e l
alpha: deal with multiple simultaneously pending signals
Unlike the other targets, alpha sets _one_ sigframe and
buggers off until the next syscall/interrupt, even if
more signals are pending. It leads to quite a few unpleasant
inconsistencies, starting with SIGSEGV potentially arriving
not where it should and including e.g. mess with sigsuspend();
consider two pending signals blocked until sigsuspend()
unblocks them. We pick the first one; then, if we are hit
by interrupt while in the handler, we process the second one
as well. If we are not, and if no syscalls had been made,
we get out of the first handler and leave the second signal
pending; normally sigreturn() would've picked it anyway, but
here it starts with restoring the original mask and voila -
the second signal is blocked again. On everything else we
get both delivered consistently.
It's actually easy to fix; the only thing to watch out for
is prevention of double syscall restart. Fortunately, the
idea I've nicked from arm fix by rmk works just fine...
Testcase demonstrating the behaviour in question; on alpha
we get one or both flags set (usually one), on everything
else both are always set.
#include <signal.h>
#include <stdio.h>
int had1, had2;
void f1(int sig) { had1 = 1; }
void f2(int sig) { had2 = 1; }
main()
{
sigset_t set1, set2;
sigemptyset(&set1);
sigemptyset(&set2);
sigaddset(&set2, 1);
sigaddset(&set2, 2);
signal(1, f1);
signal(2, f2);
sigprocmask(SIG_SETMASK, &set2, NULL);
raise(1);
raise(2);
sigsuspend(&set1);
printf("had1:%d had2:%d\n", had1, had2);
}
Tested-by: Michael Cree <mcree@orcon.net.nz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Matt Turner <mattst88@gmail.com>
2010-09-18 08:42:27 -04:00
ret_to_user :
2005-04-16 15:20:36 -07:00
/ * Make s u r e n e e d _ r e s c h e d a n d s i g p e n d i n g d o n ' t c h a n g e b e t w e e n
sampling a n d t h e r t i . * /
lda $ 1 6 , 7
call_ p a l P A L _ s w p i p l
ldl $ 5 , T I _ F L A G S ( $ 8 )
and $ 5 , _ T I F _ W O R K _ M A S K , $ 2
alpha: deal with multiple simultaneously pending signals
Unlike the other targets, alpha sets _one_ sigframe and
buggers off until the next syscall/interrupt, even if
more signals are pending. It leads to quite a few unpleasant
inconsistencies, starting with SIGSEGV potentially arriving
not where it should and including e.g. mess with sigsuspend();
consider two pending signals blocked until sigsuspend()
unblocks them. We pick the first one; then, if we are hit
by interrupt while in the handler, we process the second one
as well. If we are not, and if no syscalls had been made,
we get out of the first handler and leave the second signal
pending; normally sigreturn() would've picked it anyway, but
here it starts with restoring the original mask and voila -
the second signal is blocked again. On everything else we
get both delivered consistently.
It's actually easy to fix; the only thing to watch out for
is prevention of double syscall restart. Fortunately, the
idea I've nicked from arm fix by rmk works just fine...
Testcase demonstrating the behaviour in question; on alpha
we get one or both flags set (usually one), on everything
else both are always set.
#include <signal.h>
#include <stdio.h>
int had1, had2;
void f1(int sig) { had1 = 1; }
void f2(int sig) { had2 = 1; }
main()
{
sigset_t set1, set2;
sigemptyset(&set1);
sigemptyset(&set2);
sigaddset(&set2, 1);
sigaddset(&set2, 2);
signal(1, f1);
signal(2, f2);
sigprocmask(SIG_SETMASK, &set2, NULL);
raise(1);
raise(2);
sigsuspend(&set1);
printf("had1:%d had2:%d\n", had1, had2);
}
Tested-by: Michael Cree <mcree@orcon.net.nz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Matt Turner <mattst88@gmail.com>
2010-09-18 08:42:27 -04:00
bne $ 2 , w o r k _ p e n d i n g
2005-04-16 15:20:36 -07:00
restore_all :
RESTORE_ A L L
call_ p a l P A L _ r t i
2010-09-25 21:07:14 +01:00
ret_to_kernel :
lda $ 1 6 , 7
call_ p a l P A L _ s w p i p l
br r e s t o r e _ a l l
2005-04-16 15:20:36 -07:00
.align 3
$ syscall_error :
/ *
* Some s y s t e m c a l l s ( e . g . , p t r a c e ) c a n r e t u r n a r b i t r a r y
* values w h i c h m i g h t n o r m a l l y b e m i s t a k e n a s e r r o r n u m b e r s .
* Those f u n c t i o n s m u s t z e r o $ 0 ( v0 ) d i r e c t l y i n t h e s t a c k
* frame t o i n d i c a t e t h a t a n e g a t i v e r e t u r n v a l u e w a s n ' t a n
* error n u m b e r . .
* /
ldq $ 1 9 , 0 ( $ s p ) / * o l d s y s c a l l n r ( z e r o i f s u c c e s s ) * /
beq $ 1 9 , $ r e t _ s u c c e s s
ldq $ 2 0 , 7 2 ( $ s p ) / * . . a n d t h i s a3 * /
subq $ 3 1 , $ 0 , $ 0 / * w i t h e r r o r i n v0 * /
addq $ 3 1 , 1 , $ 1 / * s e t a3 f o r e r r n o r e t u r n * /
stq $ 0 , 0 ( $ s p )
mov $ 3 1 , $ 2 6 / * t e l l " r e t _ f r o m _ s y s _ c a l l " w e c a n r e s t a r t * /
stq $ 1 , 7 2 ( $ s p ) / * a3 f o r r e t u r n * /
br r e t _ f r o m _ s y s _ c a l l
$ ret_success :
stq $ 0 , 0 ( $ s p )
stq $ 3 1 , 7 2 ( $ s p ) / * a3 =0 = > n o e r r o r * /
br r e t _ f r o m _ s y s _ c a l l
.end entSys
/ *
* Do a l l c l e a n u p w h e n r e t u r n i n g f r o m a l l i n t e r r u p t s a n d s y s t e m c a l l s .
*
* Arguments :
* $ 5 : TI_ F L A G S .
* $ 8 : current.
* $ 19 : The o l d s y s c a l l n u m b e r , o r z e r o i f t h i s i s n o t a r e t u r n
* from a s y s c a l l t h a t e r r o r e d a n d i s p o s s i b l y r e s t a r t a b l e .
alpha: deal with multiple simultaneously pending signals
Unlike the other targets, alpha sets _one_ sigframe and
buggers off until the next syscall/interrupt, even if
more signals are pending. It leads to quite a few unpleasant
inconsistencies, starting with SIGSEGV potentially arriving
not where it should and including e.g. mess with sigsuspend();
consider two pending signals blocked until sigsuspend()
unblocks them. We pick the first one; then, if we are hit
by interrupt while in the handler, we process the second one
as well. If we are not, and if no syscalls had been made,
we get out of the first handler and leave the second signal
pending; normally sigreturn() would've picked it anyway, but
here it starts with restoring the original mask and voila -
the second signal is blocked again. On everything else we
get both delivered consistently.
It's actually easy to fix; the only thing to watch out for
is prevention of double syscall restart. Fortunately, the
idea I've nicked from arm fix by rmk works just fine...
Testcase demonstrating the behaviour in question; on alpha
we get one or both flags set (usually one), on everything
else both are always set.
#include <signal.h>
#include <stdio.h>
int had1, had2;
void f1(int sig) { had1 = 1; }
void f2(int sig) { had2 = 1; }
main()
{
sigset_t set1, set2;
sigemptyset(&set1);
sigemptyset(&set2);
sigaddset(&set2, 1);
sigaddset(&set2, 2);
signal(1, f1);
signal(2, f2);
sigprocmask(SIG_SETMASK, &set2, NULL);
raise(1);
raise(2);
sigsuspend(&set1);
printf("had1:%d had2:%d\n", had1, had2);
}
Tested-by: Michael Cree <mcree@orcon.net.nz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Matt Turner <mattst88@gmail.com>
2010-09-18 08:42:27 -04:00
* $ 20 : The o l d a3 v a l u e
2005-04-16 15:20:36 -07:00
* /
.align 4
.ent work_pending
work_pending :
and $ 5 , _ T I F _ N E E D _ R E S C H E D , $ 2
beq $ 2 , $ w o r k _ n o t i f y s i g
$ work_resched :
subq $ s p , 1 6 , $ s p
stq $ 1 9 , 0 ( $ s p ) / * s a v e s y s c a l l n r * /
stq $ 2 0 , 8 ( $ s p ) / * a n d e r r o r i n d i c a t i o n ( a3 ) * /
jsr $ 2 6 , s c h e d u l e
ldq $ 1 9 , 0 ( $ s p )
ldq $ 2 0 , 8 ( $ s p )
addq $ s p , 1 6 , $ s p
/ * Make s u r e n e e d _ r e s c h e d a n d s i g p e n d i n g d o n ' t c h a n g e b e t w e e n
sampling a n d t h e r t i . * /
lda $ 1 6 , 7
call_ p a l P A L _ s w p i p l
ldl $ 5 , T I _ F L A G S ( $ 8 )
and $ 5 , _ T I F _ W O R K _ M A S K , $ 2
beq $ 2 , r e s t o r e _ a l l
and $ 5 , _ T I F _ N E E D _ R E S C H E D , $ 2
bne $ 2 , $ w o r k _ r e s c h e d
$ work_notifysig :
2007-05-29 16:03:28 -07:00
mov $ s p , $ 1 6
alpha: deal with multiple simultaneously pending signals
Unlike the other targets, alpha sets _one_ sigframe and
buggers off until the next syscall/interrupt, even if
more signals are pending. It leads to quite a few unpleasant
inconsistencies, starting with SIGSEGV potentially arriving
not where it should and including e.g. mess with sigsuspend();
consider two pending signals blocked until sigsuspend()
unblocks them. We pick the first one; then, if we are hit
by interrupt while in the handler, we process the second one
as well. If we are not, and if no syscalls had been made,
we get out of the first handler and leave the second signal
pending; normally sigreturn() would've picked it anyway, but
here it starts with restoring the original mask and voila -
the second signal is blocked again. On everything else we
get both delivered consistently.
It's actually easy to fix; the only thing to watch out for
is prevention of double syscall restart. Fortunately, the
idea I've nicked from arm fix by rmk works just fine...
Testcase demonstrating the behaviour in question; on alpha
we get one or both flags set (usually one), on everything
else both are always set.
#include <signal.h>
#include <stdio.h>
int had1, had2;
void f1(int sig) { had1 = 1; }
void f2(int sig) { had2 = 1; }
main()
{
sigset_t set1, set2;
sigemptyset(&set1);
sigemptyset(&set2);
sigaddset(&set2, 1);
sigaddset(&set2, 2);
signal(1, f1);
signal(2, f2);
sigprocmask(SIG_SETMASK, &set2, NULL);
raise(1);
raise(2);
sigsuspend(&set1);
printf("had1:%d had2:%d\n", had1, had2);
}
Tested-by: Michael Cree <mcree@orcon.net.nz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Matt Turner <mattst88@gmail.com>
2010-09-18 08:42:27 -04:00
bsr $ 1 , d o _ s w i t c h _ s t a c k
2007-05-29 16:03:28 -07:00
mov $ s p , $ 1 7
mov $ 5 , $ 1 8
alpha: deal with multiple simultaneously pending signals
Unlike the other targets, alpha sets _one_ sigframe and
buggers off until the next syscall/interrupt, even if
more signals are pending. It leads to quite a few unpleasant
inconsistencies, starting with SIGSEGV potentially arriving
not where it should and including e.g. mess with sigsuspend();
consider two pending signals blocked until sigsuspend()
unblocks them. We pick the first one; then, if we are hit
by interrupt while in the handler, we process the second one
as well. If we are not, and if no syscalls had been made,
we get out of the first handler and leave the second signal
pending; normally sigreturn() would've picked it anyway, but
here it starts with restoring the original mask and voila -
the second signal is blocked again. On everything else we
get both delivered consistently.
It's actually easy to fix; the only thing to watch out for
is prevention of double syscall restart. Fortunately, the
idea I've nicked from arm fix by rmk works just fine...
Testcase demonstrating the behaviour in question; on alpha
we get one or both flags set (usually one), on everything
else both are always set.
#include <signal.h>
#include <stdio.h>
int had1, had2;
void f1(int sig) { had1 = 1; }
void f2(int sig) { had2 = 1; }
main()
{
sigset_t set1, set2;
sigemptyset(&set1);
sigemptyset(&set2);
sigaddset(&set2, 1);
sigaddset(&set2, 2);
signal(1, f1);
signal(2, f2);
sigprocmask(SIG_SETMASK, &set2, NULL);
raise(1);
raise(2);
sigsuspend(&set1);
printf("had1:%d had2:%d\n", had1, had2);
}
Tested-by: Michael Cree <mcree@orcon.net.nz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Matt Turner <mattst88@gmail.com>
2010-09-18 08:42:27 -04:00
mov $ 1 9 , $ 9 / * s a v e o l d s y s c a l l n u m b e r * /
mov $ 2 0 , $ 1 0 / * s a v e o l d a3 * /
and $ 5 , _ T I F _ S I G P E N D I N G , $ 2
cmovne $ 2 , 0 , $ 9 / * w e d o n ' t w a n t d o u b l e s y s c a l l r e s t a r t s * /
2005-04-16 15:20:36 -07:00
jsr $ 2 6 , d o _ n o t i f y _ r e s u m e
alpha: deal with multiple simultaneously pending signals
Unlike the other targets, alpha sets _one_ sigframe and
buggers off until the next syscall/interrupt, even if
more signals are pending. It leads to quite a few unpleasant
inconsistencies, starting with SIGSEGV potentially arriving
not where it should and including e.g. mess with sigsuspend();
consider two pending signals blocked until sigsuspend()
unblocks them. We pick the first one; then, if we are hit
by interrupt while in the handler, we process the second one
as well. If we are not, and if no syscalls had been made,
we get out of the first handler and leave the second signal
pending; normally sigreturn() would've picked it anyway, but
here it starts with restoring the original mask and voila -
the second signal is blocked again. On everything else we
get both delivered consistently.
It's actually easy to fix; the only thing to watch out for
is prevention of double syscall restart. Fortunately, the
idea I've nicked from arm fix by rmk works just fine...
Testcase demonstrating the behaviour in question; on alpha
we get one or both flags set (usually one), on everything
else both are always set.
#include <signal.h>
#include <stdio.h>
int had1, had2;
void f1(int sig) { had1 = 1; }
void f2(int sig) { had2 = 1; }
main()
{
sigset_t set1, set2;
sigemptyset(&set1);
sigemptyset(&set2);
sigaddset(&set2, 1);
sigaddset(&set2, 2);
signal(1, f1);
signal(2, f2);
sigprocmask(SIG_SETMASK, &set2, NULL);
raise(1);
raise(2);
sigsuspend(&set1);
printf("had1:%d had2:%d\n", had1, had2);
}
Tested-by: Michael Cree <mcree@orcon.net.nz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Matt Turner <mattst88@gmail.com>
2010-09-18 08:42:27 -04:00
mov $ 9 , $ 1 9
mov $ 1 0 , $ 2 0
2005-04-16 15:20:36 -07:00
bsr $ 1 , u n d o _ s w i t c h _ s t a c k
alpha: deal with multiple simultaneously pending signals
Unlike the other targets, alpha sets _one_ sigframe and
buggers off until the next syscall/interrupt, even if
more signals are pending. It leads to quite a few unpleasant
inconsistencies, starting with SIGSEGV potentially arriving
not where it should and including e.g. mess with sigsuspend();
consider two pending signals blocked until sigsuspend()
unblocks them. We pick the first one; then, if we are hit
by interrupt while in the handler, we process the second one
as well. If we are not, and if no syscalls had been made,
we get out of the first handler and leave the second signal
pending; normally sigreturn() would've picked it anyway, but
here it starts with restoring the original mask and voila -
the second signal is blocked again. On everything else we
get both delivered consistently.
It's actually easy to fix; the only thing to watch out for
is prevention of double syscall restart. Fortunately, the
idea I've nicked from arm fix by rmk works just fine...
Testcase demonstrating the behaviour in question; on alpha
we get one or both flags set (usually one), on everything
else both are always set.
#include <signal.h>
#include <stdio.h>
int had1, had2;
void f1(int sig) { had1 = 1; }
void f2(int sig) { had2 = 1; }
main()
{
sigset_t set1, set2;
sigemptyset(&set1);
sigemptyset(&set2);
sigaddset(&set2, 1);
sigaddset(&set2, 2);
signal(1, f1);
signal(2, f2);
sigprocmask(SIG_SETMASK, &set2, NULL);
raise(1);
raise(2);
sigsuspend(&set1);
printf("had1:%d had2:%d\n", had1, had2);
}
Tested-by: Michael Cree <mcree@orcon.net.nz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Matt Turner <mattst88@gmail.com>
2010-09-18 08:42:27 -04:00
br r e t _ t o _ u s e r
2005-04-16 15:20:36 -07:00
.end work_pending
/ *
* PTRACE s y s c a l l h a n d l e r
* /
.align 4
.ent strace
strace :
/* set up signal stack, call syscall_trace */
bsr $ 1 , d o _ s w i t c h _ s t a c k
jsr $ 2 6 , s y s c a l l _ t r a c e
bsr $ 1 , u n d o _ s w i t c h _ s t a c k
/* get the system call number and the arguments back.. */
ldq $ 0 , 0 ( $ s p )
ldq $ 1 6 , S P _ O F F + 2 4 ( $ s p )
ldq $ 1 7 , S P _ O F F + 3 2 ( $ s p )
ldq $ 1 8 , S P _ O F F + 4 0 ( $ s p )
ldq $ 1 9 , 7 2 ( $ s p )
ldq $ 2 0 , 8 0 ( $ s p )
ldq $ 2 1 , 8 8 ( $ s p )
/* get the system call pointer.. */
lda $ 1 , N R _ S Y S C A L L S ( $ 3 1 )
lda $ 2 , s y s _ c a l l _ t a b l e
lda $ 2 7 , a l p h a _ n i _ s y s c a l l
cmpult $ 0 , $ 1 , $ 1
s8 a d d q $ 0 , $ 2 , $ 2
beq $ 1 , 1 f
ldq $ 2 7 , 0 ( $ 2 )
1 : jsr $ 2 6 , ( $ 2 7 ) , s y s _ g e t t i m e o f d a y
2010-09-18 08:41:16 -04:00
ret_from_straced :
2005-04-16 15:20:36 -07:00
ldgp $ g p , 0 ( $ 2 6 )
/* check return.. */
blt $ 0 , $ s t r a c e _ e r r o r / * t h e c a l l f a i l e d * /
stq $ 3 1 , 7 2 ( $ s p ) / * a3 =0 = > n o e r r o r * /
$ strace_success :
stq $ 0 , 0 ( $ s p ) / * s a v e r e t u r n v a l u e * /
bsr $ 1 , d o _ s w i t c h _ s t a c k
jsr $ 2 6 , s y s c a l l _ t r a c e
bsr $ 1 , u n d o _ s w i t c h _ s t a c k
br $ 3 1 , r e t _ f r o m _ s y s _ c a l l
.align 3
$ strace_error :
ldq $ 1 9 , 0 ( $ s p ) / * o l d s y s c a l l n r ( z e r o i f s u c c e s s ) * /
beq $ 1 9 , $ s t r a c e _ s u c c e s s
ldq $ 2 0 , 7 2 ( $ s p ) / * . . a n d t h i s a3 * /
subq $ 3 1 , $ 0 , $ 0 / * w i t h e r r o r i n v0 * /
addq $ 3 1 , 1 , $ 1 / * s e t a3 f o r e r r n o r e t u r n * /
stq $ 0 , 0 ( $ s p )
stq $ 1 , 7 2 ( $ s p ) / * a3 f o r r e t u r n * /
bsr $ 1 , d o _ s w i t c h _ s t a c k
mov $ 1 9 , $ 9 / * s a v e o l d s y s c a l l n u m b e r * /
mov $ 2 0 , $ 1 0 / * s a v e o l d a3 * /
jsr $ 2 6 , s y s c a l l _ t r a c e
mov $ 9 , $ 1 9
mov $ 1 0 , $ 2 0
bsr $ 1 , u n d o _ s w i t c h _ s t a c k
mov $ 3 1 , $ 2 6 / * t e l l " r e t _ f r o m _ s y s _ c a l l " w e c a n r e s t a r t * /
br r e t _ f r o m _ s y s _ c a l l
.end strace
/ *
* Save a n d r e s t o r e t h e s w i t c h s t a c k - - a k a t h e b a l a n c e o f t h e u s e r c o n t e x t .
* /
.align 4
.ent do_switch_stack
do_switch_stack :
lda $ s p , - S W I T C H _ S T A C K _ S I Z E ( $ s p )
stq $ 9 , 0 ( $ s p )
stq $ 1 0 , 8 ( $ s p )
stq $ 1 1 , 1 6 ( $ s p )
stq $ 1 2 , 2 4 ( $ s p )
stq $ 1 3 , 3 2 ( $ s p )
stq $ 1 4 , 4 0 ( $ s p )
stq $ 1 5 , 4 8 ( $ s p )
stq $ 2 6 , 5 6 ( $ s p )
stt $ f0 , 6 4 ( $ s p )
stt $ f1 , 7 2 ( $ s p )
stt $ f2 , 8 0 ( $ s p )
stt $ f3 , 8 8 ( $ s p )
stt $ f4 , 9 6 ( $ s p )
stt $ f5 , 1 0 4 ( $ s p )
stt $ f6 , 1 1 2 ( $ s p )
stt $ f7 , 1 2 0 ( $ s p )
stt $ f8 , 1 2 8 ( $ s p )
stt $ f9 , 1 3 6 ( $ s p )
stt $ f10 , 1 4 4 ( $ s p )
stt $ f11 , 1 5 2 ( $ s p )
stt $ f12 , 1 6 0 ( $ s p )
stt $ f13 , 1 6 8 ( $ s p )
stt $ f14 , 1 7 6 ( $ s p )
stt $ f15 , 1 8 4 ( $ s p )
stt $ f16 , 1 9 2 ( $ s p )
stt $ f17 , 2 0 0 ( $ s p )
stt $ f18 , 2 0 8 ( $ s p )
stt $ f19 , 2 1 6 ( $ s p )
stt $ f20 , 2 2 4 ( $ s p )
stt $ f21 , 2 3 2 ( $ s p )
stt $ f22 , 2 4 0 ( $ s p )
stt $ f23 , 2 4 8 ( $ s p )
stt $ f24 , 2 5 6 ( $ s p )
stt $ f25 , 2 6 4 ( $ s p )
stt $ f26 , 2 7 2 ( $ s p )
stt $ f27 , 2 8 0 ( $ s p )
mf_ f p c r $ f0 # g e t f p c r
stt $ f28 , 2 8 8 ( $ s p )
stt $ f29 , 2 9 6 ( $ s p )
stt $ f30 , 3 0 4 ( $ s p )
stt $ f0 , 3 1 2 ( $ s p ) # s a v e f p c r i n s l o t o f $ f 31
ldt $ f0 , 6 4 ( $ s p ) # d o n t l e t " do_switch_stack " c h a n g e f p s t a t e .
ret $ 3 1 , ( $ 1 ) , 1
.end do_switch_stack
.align 4
.ent undo_switch_stack
undo_switch_stack :
ldq $ 9 , 0 ( $ s p )
ldq $ 1 0 , 8 ( $ s p )
ldq $ 1 1 , 1 6 ( $ s p )
ldq $ 1 2 , 2 4 ( $ s p )
ldq $ 1 3 , 3 2 ( $ s p )
ldq $ 1 4 , 4 0 ( $ s p )
ldq $ 1 5 , 4 8 ( $ s p )
ldq $ 2 6 , 5 6 ( $ s p )
ldt $ f30 , 3 1 2 ( $ s p ) # g e t s a v e d f p c r
ldt $ f0 , 6 4 ( $ s p )
ldt $ f1 , 7 2 ( $ s p )
ldt $ f2 , 8 0 ( $ s p )
ldt $ f3 , 8 8 ( $ s p )
mt_ f p c r $ f30 # i n s t a l l s a v e d f p c r
ldt $ f4 , 9 6 ( $ s p )
ldt $ f5 , 1 0 4 ( $ s p )
ldt $ f6 , 1 1 2 ( $ s p )
ldt $ f7 , 1 2 0 ( $ s p )
ldt $ f8 , 1 2 8 ( $ s p )
ldt $ f9 , 1 3 6 ( $ s p )
ldt $ f10 , 1 4 4 ( $ s p )
ldt $ f11 , 1 5 2 ( $ s p )
ldt $ f12 , 1 6 0 ( $ s p )
ldt $ f13 , 1 6 8 ( $ s p )
ldt $ f14 , 1 7 6 ( $ s p )
ldt $ f15 , 1 8 4 ( $ s p )
ldt $ f16 , 1 9 2 ( $ s p )
ldt $ f17 , 2 0 0 ( $ s p )
ldt $ f18 , 2 0 8 ( $ s p )
ldt $ f19 , 2 1 6 ( $ s p )
ldt $ f20 , 2 2 4 ( $ s p )
ldt $ f21 , 2 3 2 ( $ s p )
ldt $ f22 , 2 4 0 ( $ s p )
ldt $ f23 , 2 4 8 ( $ s p )
ldt $ f24 , 2 5 6 ( $ s p )
ldt $ f25 , 2 6 4 ( $ s p )
ldt $ f26 , 2 7 2 ( $ s p )
ldt $ f27 , 2 8 0 ( $ s p )
ldt $ f28 , 2 8 8 ( $ s p )
ldt $ f29 , 2 9 6 ( $ s p )
ldt $ f30 , 3 0 4 ( $ s p )
lda $ s p , S W I T C H _ S T A C K _ S I Z E ( $ s p )
ret $ 3 1 , ( $ 1 ) , 1
.end undo_switch_stack
/ *
* The m e a t o f t h e c o n t e x t s w i t c h c o d e .
* /
.align 4
.globl alpha_switch_to
.ent alpha_switch_to
alpha_switch_to :
.prologue 0
bsr $ 1 , d o _ s w i t c h _ s t a c k
call_ p a l P A L _ s w p c t x
lda $ 8 , 0 x3 f f f
bsr $ 1 , u n d o _ s w i t c h _ s t a c k
bic $ s p , $ 8 , $ 8
mov $ 1 7 , $ 0
ret
.end alpha_switch_to
/ *
* New p r o c e s s e s b e g i n l i f e h e r e .
* /
.globl ret_from_fork
.align 4
.ent ret_from_fork
ret_from_fork :
lda $ 2 6 , r e t _ f r o m _ s y s _ c a l l
mov $ 1 7 , $ 1 6
jmp $ 3 1 , s c h e d u l e _ t a i l
.end ret_from_fork
/ *
* kernel_ t h r e a d ( f n , a r g , c l o n e _ f l a g s )
* /
.align 4
.globl kernel_thread
.ent kernel_thread
kernel_thread :
/* We can be called from a module. */
ldgp $ g p , 0 ( $ 2 7 )
.prologue 1
subq $ s p , S P _ O F F + 6 * 8 , $ s p
br $ 1 , 2 f / * l o a d s t a r t a d d r e s s * /
/* We've now "returned" from a fake system call. */
unop
blt $ 0 , 1 f / * e r r o r ? * /
ldi $ 1 , 0 x3 f f f
beq $ 2 0 , 1 f / * p a r e n t o r c h i l d ? * /
bic $ s p , $ 1 , $ 8 / * i n c h i l d . * /
jsr $ 2 6 , ( $ 2 7 )
ldgp $ g p , 0 ( $ 2 6 )
mov $ 0 , $ 1 6
mov $ 3 1 , $ 2 6
jmp $ 3 1 , s y s _ e x i t
1 : ret / * i n p a r e n t . * /
.align 4
2 : / * Fake a s y s t e m c a l l s t a c k f r a m e , a s w e c a n ' t d o s y s t e m c a l l s
from k e r n e l s p a c e . N o t e t h a t w e s t o r e F N a n d A R G a s t h e y
need t o b e s e t u p i n t h e c h i l d f o r t h e c a l l . A l s o s t o r e $ 8
and $ 2 6 f o r u s e i n t h e p a r e n t . * /
stq $ 3 1 , S P _ O F F ( $ s p ) / * p s * /
stq $ 1 , S P _ O F F + 8 ( $ s p ) / * p c * /
stq $ g p , S P _ O F F + 1 6 ( $ s p ) / * g p * /
stq $ 1 6 , 1 3 6 ( $ s p ) / * $ 2 7 ; FN for child */
stq $ 1 7 , S P _ O F F + 2 4 ( $ s p ) / * $ 1 6 ; ARG for child */
stq $ 8 , 6 4 ( $ s p ) / * $ 8 * /
stq $ 2 6 , 1 2 8 ( $ s p ) / * $ 2 6 * /
/* Avoid the HAE being gratuitously wrong, to avoid restoring it. */
ldq $ 2 , a l p h a _ m v + H A E _ C A C H E
stq $ 2 , 1 5 2 ( $ s p ) / * H A E * /
/* Shuffle FLAGS to the front; add CLONE_VM. */
ldi $ 1 , C L O N E _ V M | C L O N E _ U N T R A C E D
or $ 1 8 , $ 1 , $ 1 6
bsr $ 2 6 , s y s _ c l o n e
/ * We d o n ' t a c t u a l l y c a r e f o r a3 s u c c e s s w i d g e t r y i n t h e k e r n e l .
Not f o r p o s i t i v e e r r n o v a l u e s . * /
stq $ 0 , 0 ( $ s p ) / * $ 0 * /
2010-09-25 21:07:14 +01:00
br r e t _ t o _ k e r n e l
2005-04-16 15:20:36 -07:00
.end kernel_thread
/ *
2006-10-02 02:18:31 -07:00
* kernel_ e x e c v e ( p a t h , a r g v , e n v p )
2005-04-16 15:20:36 -07:00
* /
.align 4
2006-10-02 02:18:31 -07:00
.globl kernel_execve
.ent kernel_execve
kernel_execve :
2005-04-16 15:20:36 -07:00
/* We can be called from a module. */
ldgp $ g p , 0 ( $ 2 7 )
lda $ s p , - ( 3 2 + S I Z E O F _ P T _ R E G S + 8 ) ( $ s p )
.frame $ sp, 3 2 + S I Z E O F _ P T _ R E G S + 8 , $ 2 6 , 0
stq $ 2 6 , 0 ( $ s p )
stq $ 1 6 , 8 ( $ s p )
stq $ 1 7 , 1 6 ( $ s p )
stq $ 1 8 , 2 4 ( $ s p )
.prologue 1
lda $ 1 6 , 3 2 ( $ s p )
lda $ 1 7 , 0
lda $ 1 8 , S I Z E O F _ P T _ R E G S
bsr $ 2 6 , m e m s e t ! s a m e g p
/ * Avoid t h e H A E b e i n g g r a t u i t o u s l y w r o n g , w h i c h w o u l d c a u s e u s
to d o t h e w h o l e t u r n o f f i n t e r r u p t s t h i n g a n d r e s t o r e i t . * /
ldq $ 2 , a l p h a _ m v + H A E _ C A C H E
stq $ 2 , 1 5 2 + 3 2 ( $ s p )
ldq $ 1 6 , 8 ( $ s p )
ldq $ 1 7 , 1 6 ( $ s p )
ldq $ 1 8 , 2 4 ( $ s p )
lda $ 1 9 , 3 2 ( $ s p )
bsr $ 2 6 , d o _ e x e c v e ! s a m e g p
ldq $ 2 6 , 0 ( $ s p )
bne $ 0 , 1 f / * e r r o r ! * /
/ * Move t h e t e m p o r a r y p t _ r e g s s t r u c t f r o m i t s c u r r e n t l o c a t i o n
to t h e t o p o f t h e k e r n e l s t a c k f r a m e . S e e c o p y _ t h r e a d f o r
details f o r a n o r m a l p r o c e s s . * /
lda $ 1 6 , 0 x40 0 0 - S I Z E O F _ P T _ R E G S ( $ 8 )
lda $ 1 7 , 3 2 ( $ s p )
lda $ 1 8 , S I Z E O F _ P T _ R E G S
bsr $ 2 6 , m e m m o v e ! s a m e g p
/* Take that over as our new stack frame and visit userland! */
lda $ s p , 0 x40 0 0 - S I Z E O F _ P T _ R E G S ( $ 8 )
br $ 3 1 , r e t _ f r o m _ s y s _ c a l l
1 : lda $ s p , 3 2 + S I Z E O F _ P T _ R E G S + 8 ( $ s p )
ret
2006-10-02 02:18:31 -07:00
.end kernel_execve
2005-04-16 15:20:36 -07:00
/ *
* Special s y s t e m c a l l s . M o s t o f t h e s e a r e s p e c i a l i n t h a t t h e y e i t h e r
* have t o p l a y s w i t c h _ s t a c k g a m e s o r i n s o m e w a y u s e t h e p t _ r e g s s t r u c t .
* /
.align 4
.globl sys_fork
.ent sys_fork
sys_fork :
.prologue 0
mov $ s p , $ 2 1
bsr $ 1 , d o _ s w i t c h _ s t a c k
bis $ 3 1 , S I G C H L D , $ 1 6
mov $ 3 1 , $ 1 7
mov $ 3 1 , $ 1 8
mov $ 3 1 , $ 1 9
mov $ 3 1 , $ 2 0
jsr $ 2 6 , a l p h a _ c l o n e
bsr $ 1 , u n d o _ s w i t c h _ s t a c k
ret
.end sys_fork
.align 4
.globl sys_clone
.ent sys_clone
sys_clone :
.prologue 0
mov $ s p , $ 2 1
bsr $ 1 , d o _ s w i t c h _ s t a c k
/* $16, $17, $18, $19, $20 come from the user. */
jsr $ 2 6 , a l p h a _ c l o n e
bsr $ 1 , u n d o _ s w i t c h _ s t a c k
ret
.end sys_clone
.align 4
.globl sys_vfork
.ent sys_vfork
sys_vfork :
.prologue 0
mov $ s p , $ 1 6
bsr $ 1 , d o _ s w i t c h _ s t a c k
jsr $ 2 6 , a l p h a _ v f o r k
bsr $ 1 , u n d o _ s w i t c h _ s t a c k
ret
.end sys_vfork
.align 4
.globl sys_sigreturn
.ent sys_sigreturn
sys_sigreturn :
.prologue 0
2010-09-18 08:41:16 -04:00
lda $ 9 , r e t _ f r o m _ s t r a c e d
cmpult $ 2 6 , $ 9 , $ 9
2005-04-16 15:20:36 -07:00
mov $ s p , $ 1 7
lda $ 1 8 , - S W I T C H _ S T A C K _ S I Z E ( $ s p )
lda $ s p , - S W I T C H _ S T A C K _ S I Z E ( $ s p )
jsr $ 2 6 , d o _ s i g r e t u r n
2010-09-18 08:41:16 -04:00
bne $ 9 , 1 f
jsr $ 2 6 , s y s c a l l _ t r a c e
1 : br $ 1 , u n d o _ s w i t c h _ s t a c k
2005-04-16 15:20:36 -07:00
br r e t _ f r o m _ s y s _ c a l l
.end sys_sigreturn
.align 4
.globl sys_rt_sigreturn
.ent sys_rt_sigreturn
sys_rt_sigreturn :
.prologue 0
2010-09-18 08:41:16 -04:00
lda $ 9 , r e t _ f r o m _ s t r a c e d
cmpult $ 2 6 , $ 9 , $ 9
2005-04-16 15:20:36 -07:00
mov $ s p , $ 1 7
lda $ 1 8 , - S W I T C H _ S T A C K _ S I Z E ( $ s p )
lda $ s p , - S W I T C H _ S T A C K _ S I Z E ( $ s p )
jsr $ 2 6 , d o _ r t _ s i g r e t u r n
2010-09-18 08:41:16 -04:00
bne $ 9 , 1 f
jsr $ 2 6 , s y s c a l l _ t r a c e
1 : br $ 1 , u n d o _ s w i t c h _ s t a c k
2005-04-16 15:20:36 -07:00
br r e t _ f r o m _ s y s _ c a l l
.end sys_rt_sigreturn
.align 4
.globl sys_sethae
.ent sys_sethae
sys_sethae :
.prologue 0
stq $ 1 6 , 1 5 2 ( $ s p )
ret
.end sys_sethae
.align 4
.globl osf_getpriority
.ent osf_getpriority
osf_getpriority :
lda $ s p , - 1 6 ( $ s p )
stq $ 2 6 , 0 ( $ s p )
.prologue 0
jsr $ 2 6 , s y s _ g e t p r i o r i t y
ldq $ 2 6 , 0 ( $ s p )
blt $ 0 , 1 f
/ * Return v a l u e i s t h e u n b i a s e d p r i o r i t y , i . e . 2 0 - p r i o .
This d o e s r e s u l t i n n e g a t i v e r e t u r n v a l u e s , s o s i g n a l
no e r r o r b y w r i t i n g i n t o t h e R 0 s l o t . * /
lda $ 1 , 2 0
stq $ 3 1 , 1 6 ( $ s p )
subl $ 1 , $ 0 , $ 0
unop
1 : lda $ s p , 1 6 ( $ s p )
ret
.end osf_getpriority
.align 4
.globl sys_getxuid
.ent sys_getxuid
sys_getxuid :
.prologue 0
ldq $ 2 , T I _ T A S K ( $ 8 )
2008-11-14 10:39:16 +11:00
ldq $ 3 , T A S K _ C R E D ( $ 2 )
ldl $ 0 , C R E D _ U I D ( $ 3 )
ldl $ 1 , C R E D _ E U I D ( $ 3 )
2005-04-16 15:20:36 -07:00
stq $ 1 , 8 0 ( $ s p )
ret
.end sys_getxuid
.align 4
.globl sys_getxgid
.ent sys_getxgid
sys_getxgid :
.prologue 0
ldq $ 2 , T I _ T A S K ( $ 8 )
2008-11-14 10:39:16 +11:00
ldq $ 3 , T A S K _ C R E D ( $ 2 )
ldl $ 0 , C R E D _ G I D ( $ 3 )
ldl $ 1 , C R E D _ E G I D ( $ 3 )
2005-04-16 15:20:36 -07:00
stq $ 1 , 8 0 ( $ s p )
ret
.end sys_getxgid
.align 4
.globl sys_getxpid
.ent sys_getxpid
sys_getxpid :
.prologue 0
ldq $ 2 , T I _ T A S K ( $ 8 )
/ * See l i n u x / k e r n e l / t i m e r . c s y s _ g e t p p i d f o r d i s c u s s i o n
about t h i s l o o p . * /
2006-02-01 03:06:12 -08:00
ldq $ 3 , T A S K _ G R O U P _ L E A D E R ( $ 2 )
ldq $ 4 , T A S K _ R E A L _ P A R E N T ( $ 3 )
ldl $ 0 , T A S K _ T G I D ( $ 2 )
1 : ldl $ 1 , T A S K _ T G I D ( $ 4 )
2005-04-16 15:20:36 -07:00
# ifdef C O N F I G _ S M P
2006-02-01 03:06:12 -08:00
mov $ 4 , $ 5
2005-04-16 15:20:36 -07:00
mb
2006-02-01 03:06:12 -08:00
ldq $ 3 , T A S K _ G R O U P _ L E A D E R ( $ 2 )
ldq $ 4 , T A S K _ R E A L _ P A R E N T ( $ 3 )
cmpeq $ 4 , $ 5 , $ 5
beq $ 5 , 1 b
2005-04-16 15:20:36 -07:00
# endif
stq $ 1 , 8 0 ( $ s p )
ret
.end sys_getxpid
.align 4
2009-01-14 14:13:56 +01:00
.globl sys_alpha_pipe
.ent sys_alpha_pipe
sys_alpha_pipe :
2005-04-16 15:20:36 -07:00
lda $ s p , - 1 6 ( $ s p )
stq $ 2 6 , 0 ( $ s p )
.prologue 0
2009-01-14 17:01:33 +08:00
mov $ 3 1 , $ 1 7
2005-04-16 15:20:36 -07:00
lda $ 1 6 , 8 ( $ s p )
2009-01-14 17:01:33 +08:00
jsr $ 2 6 , d o _ p i p e _ f l a g s
2005-04-16 15:20:36 -07:00
ldq $ 2 6 , 0 ( $ s p )
bne $ 0 , 1 f
/* The return values are in $0 and $20. */
ldl $ 1 , 1 2 ( $ s p )
ldl $ 0 , 8 ( $ s p )
stq $ 1 , 8 0 + 1 6 ( $ s p )
1 : lda $ s p , 1 6 ( $ s p )
ret
2009-01-14 14:13:56 +01:00
.end sys_alpha_pipe
2005-04-16 15:20:36 -07:00
.align 4
.globl sys_execve
.ent sys_execve
sys_execve :
.prologue 0
mov $ s p , $ 1 9
jmp $ 3 1 , d o _ s y s _ e x e c v e
.end sys_execve
.align 4
.globl alpha_ni_syscall
.ent alpha_ni_syscall
alpha_ni_syscall :
.prologue 0
/ * Special b e c a u s e i t a l s o i m p l e m e n t s o v e r f l o w h a n d l i n g v i a
syscall n u m b e r 0 . A n d i f y o u r e c a l l , z e r o i s a s p e c i a l
trigger f o r " n o t a n e r r o r " . S t o r e l a r g e n o n - z e r o t h e r e . * /
lda $ 0 , - E N O S Y S
unop
stq $ 0 , 0 ( $ s p )
ret
.end alpha_ni_syscall