Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
08f73957
Commit
08f73957
authored
Nov 07, 2012
by
Al Viro
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
sparc: convert to ksignal
Signed-off-by:
Al Viro
<
viro@zeniv.linux.org.uk
>
parent
7e243643
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
164 additions
and
254 deletions
+164
-254
arch/sparc/kernel/signal32.c
arch/sparc/kernel/signal32.c
+62
-92
arch/sparc/kernel/signal_32.c
arch/sparc/kernel/signal_32.c
+59
-87
arch/sparc/kernel/signal_64.c
arch/sparc/kernel/signal_64.c
+43
-75
No files found.
arch/sparc/kernel/signal32.c
View file @
08f73957
...
...
@@ -323,7 +323,7 @@ static int invalid_frame_pointer(void __user *fp, int fplen)
return
0
;
}
static
void
__user
*
get_sigframe
(
struct
sigaction
*
sa
,
struct
pt_regs
*
regs
,
unsigned
long
framesize
)
static
void
__user
*
get_sigframe
(
struct
ksignal
*
ksig
,
struct
pt_regs
*
regs
,
unsigned
long
framesize
)
{
unsigned
long
sp
;
...
...
@@ -338,12 +338,7 @@ static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns
return
(
void
__user
*
)
-
1L
;
/* This is the X/Open sanctioned signal stack switching. */
if
(
sa
->
sa_flags
&
SA_ONSTACK
)
{
if
(
sas_ss_flags
(
sp
)
==
0
)
sp
=
current
->
sas_ss_sp
+
current
->
sas_ss_size
;
}
sp
-=
framesize
;
sp
=
sigsp
(
sp
,
ksig
)
-
framesize
;
/* Always align the stack frame. This handles two cases. First,
* sigaltstack need not be mindful of platform specific stack
...
...
@@ -414,8 +409,8 @@ static void flush_signal_insns(unsigned long address)
}
static
int
setup_frame32
(
struct
k
_sigaction
*
ka
,
struct
pt_regs
*
regs
,
int
signo
,
sigset_t
*
oldset
)
static
int
setup_frame32
(
struct
k
signal
*
ksig
,
struct
pt_regs
*
regs
,
sigset_t
*
oldset
)
{
struct
signal_frame32
__user
*
sf
;
int
i
,
err
,
wsaved
;
...
...
@@ -437,10 +432,12 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
sigframe_size
+=
sizeof
(
__siginfo_rwin_t
);
sf
=
(
struct
signal_frame32
__user
*
)
get_sigframe
(
&
ka
->
sa
,
regs
,
sigframe_size
);
get_sigframe
(
ksig
,
regs
,
sigframe_size
);
if
(
invalid_frame_pointer
(
sf
,
sigframe_size
))
goto
sigill
;
if
(
invalid_frame_pointer
(
sf
,
sigframe_size
))
{
do_exit
(
SIGILL
);
return
-
EINVAL
;
}
tail
=
(
sf
+
1
);
...
...
@@ -514,16 +511,16 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
err
|=
__put_user
(
rp
->
ins
[
7
],
&
sf
->
ss
.
callers_pc
);
}
if
(
err
)
goto
sigsegv
;
return
err
;
/* 3. signal handler back-trampoline and parameters */
regs
->
u_regs
[
UREG_FP
]
=
(
unsigned
long
)
sf
;
regs
->
u_regs
[
UREG_I0
]
=
signo
;
regs
->
u_regs
[
UREG_I0
]
=
ksig
->
sig
;
regs
->
u_regs
[
UREG_I1
]
=
(
unsigned
long
)
&
sf
->
info
;
regs
->
u_regs
[
UREG_I2
]
=
(
unsigned
long
)
&
sf
->
info
;
/* 4. signal handler */
regs
->
tpc
=
(
unsigned
long
)
k
a
->
sa
.
sa_handler
;
regs
->
tpc
=
(
unsigned
long
)
k
sig
->
ka
.
sa
.
sa_handler
;
regs
->
tnpc
=
(
regs
->
tpc
+
4
);
if
(
test_thread_flag
(
TIF_32BIT
))
{
regs
->
tpc
&=
0xffffffff
;
...
...
@@ -531,8 +528,8 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
}
/* 5. return to kernel instructions */
if
(
k
a
->
ka_restorer
)
{
regs
->
u_regs
[
UREG_I7
]
=
(
unsigned
long
)
k
a
->
ka_restorer
;
if
(
k
sig
->
ka
.
ka_restorer
)
{
regs
->
u_regs
[
UREG_I7
]
=
(
unsigned
long
)
k
sig
->
ka
.
ka_restorer
;
}
else
{
unsigned
long
address
=
((
unsigned
long
)
&
(
sf
->
insns
[
0
]));
...
...
@@ -541,23 +538,14 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
err
=
__put_user
(
0x821020d8
,
&
sf
->
insns
[
0
]);
/*mov __NR_sigreturn, %g1*/
err
|=
__put_user
(
0x91d02010
,
&
sf
->
insns
[
1
]);
/*t 0x10*/
if
(
err
)
goto
sigsegv
;
return
err
;
flush_signal_insns
(
address
);
}
return
0
;
sigill:
do_exit
(
SIGILL
);
return
-
EINVAL
;
sigsegv:
force_sigsegv
(
signo
,
current
);
return
-
EFAULT
;
}
static
int
setup_rt_frame32
(
struct
k_sigaction
*
ka
,
struct
pt_regs
*
regs
,
unsigned
long
signr
,
sigset_t
*
oldset
,
siginfo_t
*
info
)
static
int
setup_rt_frame32
(
struct
ksignal
*
ksig
,
struct
pt_regs
*
regs
,
sigset_t
*
oldset
)
{
struct
rt_signal_frame32
__user
*
sf
;
int
i
,
err
,
wsaved
;
...
...
@@ -579,10 +567,12 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
sigframe_size
+=
sizeof
(
__siginfo_rwin_t
);
sf
=
(
struct
rt_signal_frame32
__user
*
)
get_sigframe
(
&
ka
->
sa
,
regs
,
sigframe_size
);
get_sigframe
(
ksig
,
regs
,
sigframe_size
);
if
(
invalid_frame_pointer
(
sf
,
sigframe_size
))
goto
sigill
;
if
(
invalid_frame_pointer
(
sf
,
sigframe_size
))
{
do_exit
(
SIGILL
);
return
-
EINVAL
;
}
tail
=
(
sf
+
1
);
...
...
@@ -627,7 +617,7 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
}
/* Update the siginfo structure. */
err
|=
copy_siginfo_to_user32
(
&
sf
->
info
,
info
);
err
|=
copy_siginfo_to_user32
(
&
sf
->
info
,
&
ksig
->
info
);
/* Setup sigaltstack */
err
|=
__compat_save_altstack
(
&
sf
->
stack
,
regs
->
u_regs
[
UREG_FP
]);
...
...
@@ -660,16 +650,16 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
err
|=
__put_user
(
rp
->
ins
[
7
],
&
sf
->
ss
.
callers_pc
);
}
if
(
err
)
goto
sigsegv
;
return
err
;
/* 3. signal handler back-trampoline and parameters */
regs
->
u_regs
[
UREG_FP
]
=
(
unsigned
long
)
sf
;
regs
->
u_regs
[
UREG_I0
]
=
signr
;
regs
->
u_regs
[
UREG_I0
]
=
ksig
->
sig
;
regs
->
u_regs
[
UREG_I1
]
=
(
unsigned
long
)
&
sf
->
info
;
regs
->
u_regs
[
UREG_I2
]
=
(
unsigned
long
)
&
sf
->
regs
;
/* 4. signal handler */
regs
->
tpc
=
(
unsigned
long
)
k
a
->
sa
.
sa_handler
;
regs
->
tpc
=
(
unsigned
long
)
k
sig
->
ka
.
sa
.
sa_handler
;
regs
->
tnpc
=
(
regs
->
tpc
+
4
);
if
(
test_thread_flag
(
TIF_32BIT
))
{
regs
->
tpc
&=
0xffffffff
;
...
...
@@ -677,8 +667,8 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
}
/* 5. return to kernel instructions */
if
(
k
a
->
ka_restorer
)
regs
->
u_regs
[
UREG_I7
]
=
(
unsigned
long
)
k
a
->
ka_restorer
;
if
(
k
sig
->
ka
.
ka_restorer
)
regs
->
u_regs
[
UREG_I7
]
=
(
unsigned
long
)
k
sig
->
ka
.
ka_restorer
;
else
{
unsigned
long
address
=
((
unsigned
long
)
&
(
sf
->
insns
[
0
]));
...
...
@@ -690,36 +680,25 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
/* t 0x10 */
err
|=
__put_user
(
0x91d02010
,
&
sf
->
insns
[
1
]);
if
(
err
)
goto
sigsegv
;
return
err
;
flush_signal_insns
(
address
);
}
return
0
;
sigill:
do_exit
(
SIGILL
);
return
-
EINVAL
;
sigsegv:
force_sigsegv
(
signr
,
current
);
return
-
EFAULT
;
}
static
inline
void
handle_signal32
(
unsigned
long
signr
,
struct
k_sigaction
*
ka
,
siginfo_t
*
info
,
sigset_t
*
oldset
,
struct
pt_regs
*
regs
)
static
inline
void
handle_signal32
(
struct
ksignal
*
ksig
,
struct
pt_regs
*
regs
)
{
sigset_t
*
oldset
=
sigmask_to_save
();
int
err
;
if
(
k
a
->
sa
.
sa_flags
&
SA_SIGINFO
)
err
=
setup_rt_frame32
(
k
a
,
regs
,
signr
,
oldset
,
info
);
if
(
k
sig
->
ka
.
sa
.
sa_flags
&
SA_SIGINFO
)
err
=
setup_rt_frame32
(
k
sig
,
regs
,
oldset
);
else
err
=
setup_frame32
(
k
a
,
regs
,
signr
,
oldset
);
err
=
setup_frame32
(
k
sig
,
regs
,
oldset
);
if
(
err
)
return
;
signal_delivered
(
signr
,
info
,
ka
,
regs
,
0
);
signal_setup_done
(
err
,
ksig
,
0
);
}
static
inline
void
syscall_restart32
(
unsigned
long
orig_i0
,
struct
pt_regs
*
regs
,
...
...
@@ -749,50 +728,41 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs
*/
void
do_signal32
(
sigset_t
*
oldset
,
struct
pt_regs
*
regs
)
{
struct
k_sigaction
ka
;
unsigned
long
orig_i0
;
int
restart_syscall
;
siginfo_t
info
;
int
signr
;
signr
=
get_signal_to_deliver
(
&
info
,
&
ka
,
regs
,
NULL
);
struct
ksignal
ksig
;
unsigned
long
orig_i0
=
0
;
int
restart_syscall
=
0
;
bool
has_handler
=
get_signal
(
&
ksig
);
restart_syscall
=
0
;
orig_i0
=
0
;
if
(
pt_regs_is_syscall
(
regs
)
&&
(
regs
->
tstate
&
(
TSTATE_XCARRY
|
TSTATE_ICARRY
)))
{
restart_syscall
=
1
;
orig_i0
=
regs
->
u_regs
[
UREG_G6
];
}
if
(
signr
>
0
)
{
if
(
has_handler
)
{
if
(
restart_syscall
)
syscall_restart32
(
orig_i0
,
regs
,
&
ka
.
sa
);
handle_signal32
(
signr
,
&
ka
,
&
info
,
oldset
,
regs
);
return
;
}
if
(
restart_syscall
&&
(
regs
->
u_regs
[
UREG_I0
]
==
ERESTARTNOHAND
||
regs
->
u_regs
[
UREG_I0
]
==
ERESTARTSYS
||
regs
->
u_regs
[
UREG_I0
]
==
ERESTARTNOINTR
))
{
/* replay the system call when we are done */
regs
->
u_regs
[
UREG_I0
]
=
orig_i0
;
regs
->
tpc
-=
4
;
regs
->
tnpc
-=
4
;
pt_regs_clear_syscall
(
regs
);
}
if
(
restart_syscall
&&
regs
->
u_regs
[
UREG_I0
]
==
ERESTART_RESTARTBLOCK
)
{
regs
->
u_regs
[
UREG_G1
]
=
__NR_restart_syscall
;
regs
->
tpc
-=
4
;
regs
->
tnpc
-=
4
;
pt_regs_clear_syscall
(
regs
);
syscall_restart32
(
orig_i0
,
regs
,
&
ksig
.
ka
.
sa
);
handle_signal32
(
&
ksig
,
regs
);
}
else
{
if
(
restart_syscall
)
{
switch
(
regs
->
u_regs
[
UREG_I0
])
{
case
ERESTARTNOHAND
:
case
ERESTARTSYS
:
case
ERESTARTNOINTR
:
/* replay the system call when we are done */
regs
->
u_regs
[
UREG_I0
]
=
orig_i0
;
regs
->
tpc
-=
4
;
regs
->
tnpc
-=
4
;
pt_regs_clear_syscall
(
regs
);
case
ERESTART_RESTARTBLOCK
:
regs
->
u_regs
[
UREG_G1
]
=
__NR_restart_syscall
;
regs
->
tpc
-=
4
;
regs
->
tnpc
-=
4
;
pt_regs_clear_syscall
(
regs
);
}
}
restore_saved_sigmask
();
}
/* If there's no signal to deliver, we just put the saved sigmask
* back
*/
restore_saved_sigmask
();
}
struct
sigstack32
{
...
...
arch/sparc/kernel/signal_32.c
View file @
08f73957
...
...
@@ -186,7 +186,7 @@ static inline int invalid_frame_pointer(void __user *fp, int fplen)
return
0
;
}
static
inline
void
__user
*
get_sigframe
(
struct
sigaction
*
sa
,
struct
pt_regs
*
regs
,
unsigned
long
framesize
)
static
inline
void
__user
*
get_sigframe
(
struct
ksignal
*
ksig
,
struct
pt_regs
*
regs
,
unsigned
long
framesize
)
{
unsigned
long
sp
=
regs
->
u_regs
[
UREG_FP
];
...
...
@@ -198,12 +198,7 @@ static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *re
return
(
void
__user
*
)
-
1L
;
/* This is the X/Open sanctioned signal stack switching. */
if
(
sa
->
sa_flags
&
SA_ONSTACK
)
{
if
(
sas_ss_flags
(
sp
)
==
0
)
sp
=
current
->
sas_ss_sp
+
current
->
sas_ss_size
;
}
sp
-=
framesize
;
sp
=
sigsp
(
sp
,
ksig
)
-
framesize
;
/* Always align the stack frame. This handles two cases. First,
* sigaltstack need not be mindful of platform specific stack
...
...
@@ -216,8 +211,8 @@ static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *re
return
(
void
__user
*
)
sp
;
}
static
int
setup_frame
(
struct
k
_sigaction
*
ka
,
struct
pt_regs
*
regs
,
int
signo
,
sigset_t
*
oldset
)
static
int
setup_frame
(
struct
k
signal
*
ksig
,
struct
pt_regs
*
regs
,
sigset_t
*
oldset
)
{
struct
signal_frame
__user
*
sf
;
int
sigframe_size
,
err
,
wsaved
;
...
...
@@ -235,10 +230,12 @@ static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
sigframe_size
+=
sizeof
(
__siginfo_rwin_t
);
sf
=
(
struct
signal_frame
__user
*
)
get_sigframe
(
&
ka
->
sa
,
regs
,
sigframe_size
);
get_sigframe
(
ksig
,
regs
,
sigframe_size
);
if
(
invalid_frame_pointer
(
sf
,
sigframe_size
))
goto
sigill_and_return
;
if
(
invalid_frame_pointer
(
sf
,
sigframe_size
))
{
do_exit
(
SIGILL
);
return
-
EINVAL
;
}
tail
=
sf
+
1
;
...
...
@@ -277,21 +274,21 @@ static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
err
|=
__copy_to_user
(
sf
,
rp
,
sizeof
(
struct
reg_window32
));
}
if
(
err
)
goto
sigsegv
;
return
err
;
/* 3. signal handler back-trampoline and parameters */
regs
->
u_regs
[
UREG_FP
]
=
(
unsigned
long
)
sf
;
regs
->
u_regs
[
UREG_I0
]
=
signo
;
regs
->
u_regs
[
UREG_I0
]
=
ksig
->
sig
;
regs
->
u_regs
[
UREG_I1
]
=
(
unsigned
long
)
&
sf
->
info
;
regs
->
u_regs
[
UREG_I2
]
=
(
unsigned
long
)
&
sf
->
info
;
/* 4. signal handler */
regs
->
pc
=
(
unsigned
long
)
k
a
->
sa
.
sa_handler
;
regs
->
pc
=
(
unsigned
long
)
k
sig
->
ka
.
sa
.
sa_handler
;
regs
->
npc
=
(
regs
->
pc
+
4
);
/* 5. return to kernel instructions */
if
(
k
a
->
ka_restorer
)
regs
->
u_regs
[
UREG_I7
]
=
(
unsigned
long
)
k
a
->
ka_restorer
;
if
(
k
sig
->
ka
.
ka_restorer
)
regs
->
u_regs
[
UREG_I7
]
=
(
unsigned
long
)
k
sig
->
ka
.
ka_restorer
;
else
{
regs
->
u_regs
[
UREG_I7
]
=
(
unsigned
long
)(
&
(
sf
->
insns
[
0
])
-
2
);
...
...
@@ -301,24 +298,16 @@ static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
/* t 0x10 */
err
|=
__put_user
(
0x91d02010
,
&
sf
->
insns
[
1
]);
if
(
err
)
goto
sigsegv
;
return
err
;
/* Flush instruction space. */
flush_sig_insns
(
current
->
mm
,
(
unsigned
long
)
&
(
sf
->
insns
[
0
]));
}
return
0
;
sigill_and_return:
do_exit
(
SIGILL
);
return
-
EINVAL
;
sigsegv:
force_sigsegv
(
signo
,
current
);
return
-
EFAULT
;
}
static
int
setup_rt_frame
(
struct
k
_sigaction
*
ka
,
struct
pt_regs
*
regs
,
int
signo
,
sigset_t
*
oldset
,
siginfo_t
*
info
)
static
int
setup_rt_frame
(
struct
k
signal
*
ksig
,
struct
pt_regs
*
regs
,
sigset_t
*
oldset
)
{
struct
rt_signal_frame
__user
*
sf
;
int
sigframe_size
,
wsaved
;
...
...
@@ -334,9 +323,11 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
if
(
wsaved
)
sigframe_size
+=
sizeof
(
__siginfo_rwin_t
);
sf
=
(
struct
rt_signal_frame
__user
*
)
get_sigframe
(
&
ka
->
sa
,
regs
,
sigframe_size
);
if
(
invalid_frame_pointer
(
sf
,
sigframe_size
))
goto
sigill
;
get_sigframe
(
ksig
,
regs
,
sigframe_size
);
if
(
invalid_frame_pointer
(
sf
,
sigframe_size
))
{
do_exit
(
SIGILL
);
return
-
EINVAL
;
}
tail
=
sf
+
1
;
err
=
__put_user
(
regs
->
pc
,
&
sf
->
regs
.
pc
);
...
...
@@ -380,21 +371,21 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
err
|=
__copy_to_user
(
sf
,
rp
,
sizeof
(
struct
reg_window32
));
}
err
|=
copy_siginfo_to_user
(
&
sf
->
info
,
info
);
err
|=
copy_siginfo_to_user
(
&
sf
->
info
,
&
ksig
->
info
);
if
(
err
)
goto
sigsegv
;
return
err
;
regs
->
u_regs
[
UREG_FP
]
=
(
unsigned
long
)
sf
;
regs
->
u_regs
[
UREG_I0
]
=
signo
;
regs
->
u_regs
[
UREG_I0
]
=
ksig
->
sig
;
regs
->
u_regs
[
UREG_I1
]
=
(
unsigned
long
)
&
sf
->
info
;
regs
->
u_regs
[
UREG_I2
]
=
(
unsigned
long
)
&
sf
->
regs
;
regs
->
pc
=
(
unsigned
long
)
k
a
->
sa
.
sa_handler
;
regs
->
pc
=
(
unsigned
long
)
k
sig
->
ka
.
sa
.
sa_handler
;
regs
->
npc
=
(
regs
->
pc
+
4
);
if
(
k
a
->
ka_restorer
)
regs
->
u_regs
[
UREG_I7
]
=
(
unsigned
long
)
k
a
->
ka_restorer
;
if
(
k
sig
->
ka
.
ka_restorer
)
regs
->
u_regs
[
UREG_I7
]
=
(
unsigned
long
)
k
sig
->
ka
.
ka_restorer
;
else
{
regs
->
u_regs
[
UREG_I7
]
=
(
unsigned
long
)(
&
(
sf
->
insns
[
0
])
-
2
);
...
...
@@ -404,38 +395,25 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
/* t 0x10 */
err
|=
__put_user
(
0x91d02010
,
&
sf
->
insns
[
1
]);
if
(
err
)
goto
sigsegv
;
return
err
;
/* Flush instruction space. */
flush_sig_insns
(
current
->
mm
,
(
unsigned
long
)
&
(
sf
->
insns
[
0
]));
}
return
0
;
sigill:
do_exit
(
SIGILL
);
return
-
EINVAL
;
sigsegv:
force_sigsegv
(
signo
,
current
);
return
-
EFAULT
;
}
static
inline
void
handle_signal
(
unsigned
long
signr
,
struct
k_sigaction
*
ka
,
siginfo_t
*
info
,
struct
pt_regs
*
regs
)
handle_signal
(
struct
ksignal
*
ksig
,
struct
pt_regs
*
regs
)
{
sigset_t
*
oldset
=
sigmask_to_save
();
int
err
;
if
(
k
a
->
sa
.
sa_flags
&
SA_SIGINFO
)
err
=
setup_rt_frame
(
k
a
,
regs
,
signr
,
oldset
,
info
);
if
(
k
sig
->
ka
.
sa
.
sa_flags
&
SA_SIGINFO
)
err
=
setup_rt_frame
(
k
sig
,
regs
,
oldset
);
else
err
=
setup_frame
(
ka
,
regs
,
signr
,
oldset
);
if
(
err
)
return
;
signal_delivered
(
signr
,
info
,
ka
,
regs
,
0
);
err
=
setup_frame
(
ksig
,
regs
,
oldset
);
signal_setup_done
(
err
,
ksig
,
0
);
}
static
inline
void
syscall_restart
(
unsigned
long
orig_i0
,
struct
pt_regs
*
regs
,
...
...
@@ -465,10 +443,9 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
*/
static
void
do_signal
(
struct
pt_regs
*
regs
,
unsigned
long
orig_i0
)
{
struct
k
_sigaction
ka
;
struct
k
signal
ksig
;
int
restart_syscall
;
siginfo_t
info
;
int
signr
;
bool
has_handler
;
/* It's a lot of work and synchronization to add a new ptrace
* register for GDB to save and restore in order to get
...
...
@@ -491,7 +468,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
if
(
pt_regs_is_syscall
(
regs
)
&&
(
regs
->
psr
&
PSR_C
))
regs
->
u_regs
[
UREG_G6
]
=
orig_i0
;
signr
=
get_signal_to_deliver
(
&
info
,
&
ka
,
regs
,
NULL
);
has_handler
=
get_signal
(
&
ksig
);
/* If the debugger messes with the program counter, it clears
* the software "in syscall" bit, directing us to not perform
...
...
@@ -503,35 +480,30 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
orig_i0
=
regs
->
u_regs
[
UREG_G6
];
}
if
(
signr
>
0
)
{
if
(
has_handler
)
{
if
(
restart_syscall
)
syscall_restart
(
orig_i0
,
regs
,
&
ka
.
sa
);
handle_signal
(
signr
,
&
ka
,
&
info
,
regs
);
return
;
}
if
(
restart_syscall
&&
(
regs
->
u_regs
[
UREG_I0
]
==
ERESTARTNOHAND
||
regs
->
u_regs
[
UREG_I0
]
==
ERESTARTSYS
||
regs
->
u_regs
[
UREG_I0
]
==
ERESTARTNOINTR
))
{
/* replay the system call when we are done */
regs
->
u_regs
[
UREG_I0
]
=
orig_i0
;
regs
->
pc
-=
4
;
regs
->
npc
-=
4
;
pt_regs_clear_syscall
(
regs
);
}
if
(
restart_syscall
&&
regs
->
u_regs
[
UREG_I0
]
==
ERESTART_RESTARTBLOCK
)
{
regs
->
u_regs
[
UREG_G1
]
=
__NR_restart_syscall
;
regs
->
pc
-=
4
;
regs
->
npc
-=
4
;
pt_regs_clear_syscall
(
regs
);
syscall_restart
(
orig_i0
,
regs
,
&
ksig
.
ka
.
sa
);
handle_signal
(
&
ksig
,
regs
);
}
else
{
if
(
restart_syscall
)
{
switch
(
regs
->
u_regs
[
UREG_I0
])
{
case
ERESTARTNOHAND
:
case
ERESTARTSYS
:
case
ERESTARTNOINTR
:
/* replay the system call when we are done */
regs
->
u_regs
[
UREG_I0
]
=
orig_i0
;
regs
->
pc
-=
4
;
regs
->
npc
-=
4
;
pt_regs_clear_syscall
(
regs
);
case
ERESTART_RESTARTBLOCK
:
regs
->
u_regs
[
UREG_G1
]
=
__NR_restart_syscall
;
regs
->
pc
-=
4
;
regs
->
npc
-=
4
;
pt_regs_clear_syscall
(
regs
);
}
}
restore_saved_sigmask
();
}
/* if there's no signal to deliver, we just put the saved sigmask
* back
*/
restore_saved_sigmask
();
}
void
do_notify_resume
(
struct
pt_regs
*
regs
,
unsigned
long
orig_i0
,
...
...
arch/sparc/kernel/signal_64.c
View file @
08f73957
...
...
@@ -308,7 +308,7 @@ static int invalid_frame_pointer(void __user *fp)
return
0
;
}
static
inline
void
__user
*
get_sigframe
(
struct
k
_sigaction
*
ka
,
struct
pt_regs
*
regs
,
unsigned
long
framesize
)
static
inline
void
__user
*
get_sigframe
(
struct
k
signal
*
ksig
,
struct
pt_regs
*
regs
,
unsigned
long
framesize
)
{
unsigned
long
sp
=
regs
->
u_regs
[
UREG_FP
]
+
STACK_BIAS
;
...
...
@@ -320,12 +320,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *
return
(
void
__user
*
)
-
1L
;
/* This is the X/Open sanctioned signal stack switching. */
if
(
ka
->
sa
.
sa_flags
&
SA_ONSTACK
)
{
if
(
sas_ss_flags
(
sp
)
==
0
)
sp
=
current
->
sas_ss_sp
+
current
->
sas_ss_size
;
}
sp
-=
framesize
;
sp
=
sigsp
(
sp
,
ksig
)
-
framesize
;
/* Always align the stack frame. This handles two cases. First,
* sigaltstack need not be mindful of platform specific stack
...
...
@@ -339,8 +334,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *
}
static
inline
int
setup_rt_frame
(
struct
k_sigaction
*
ka
,
struct
pt_regs
*
regs
,
int
signo
,
sigset_t
*
oldset
,
siginfo_t
*
info
)
setup_rt_frame
(
struct
ksignal
*
ksig
,
struct
pt_regs
*
regs
)
{
struct
rt_signal_frame
__user
*
sf
;
int
wsaved
,
err
,
sf_size
;
...
...
@@ -358,10 +352,12 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
if
(
wsaved
)
sf_size
+=
sizeof
(
__siginfo_rwin_t
);
sf
=
(
struct
rt_signal_frame
__user
*
)
get_sigframe
(
k
a
,
regs
,
sf_size
);
get_sigframe
(
k
sig
,
regs
,
sf_size
);
if
(
invalid_frame_pointer
(
sf
))
goto
sigill
;
if
(
invalid_frame_pointer
(
sf
))
{
do_exit
(
SIGILL
);
/* won't return, actually */
return
-
EINVAL
;
}
tail
=
(
sf
+
1
);
...
...
@@ -389,7 +385,7 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
/* Setup sigaltstack */
err
|=
__save_altstack
(
&
sf
->
stack
,
regs
->
u_regs
[
UREG_FP
]);
err
|=
copy_to_user
(
&
sf
->
mask
,
oldset
,
sizeof
(
sigset_t
));
err
|=
copy_to_user
(
&
sf
->
mask
,
sigmask_to_save
()
,
sizeof
(
sigset_t
));
if
(
!
wsaved
)
{
err
|=
copy_in_user
((
u64
__user
*
)
sf
,
...
...
@@ -402,18 +398,18 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
rp
=
&
current_thread_info
()
->
reg_window
[
wsaved
-
1
];
err
|=
copy_to_user
(
sf
,
rp
,
sizeof
(
struct
reg_window
));
}
if
(
info
)
err
|=
copy_siginfo_to_user
(
&
sf
->
info
,
info
);
if
(
ksig
->
ka
.
sa
.
sa_flags
&
SA_SIGINFO
)
err
|=
copy_siginfo_to_user
(
&
sf
->
info
,
&
ksig
->
info
);
else
{
err
|=
__put_user
(
signo
,
&
sf
->
info
.
si_signo
);
err
|=
__put_user
(
ksig
->
sig
,
&
sf
->
info
.
si_signo
);
err
|=
__put_user
(
SI_NOINFO
,
&
sf
->
info
.
si_code
);
}
if
(
err
)
goto
sigsegv
;
return
err
;
/* 3. signal handler back-trampoline and parameters */
regs
->
u_regs
[
UREG_FP
]
=
((
unsigned
long
)
sf
)
-
STACK_BIAS
;
regs
->
u_regs
[
UREG_I0
]
=
signo
;
regs
->
u_regs
[
UREG_I0
]
=
ksig
->
sig
;
regs
->
u_regs
[
UREG_I1
]
=
(
unsigned
long
)
&
sf
->
info
;
/* The sigcontext is passed in this way because of how it
...
...
@@ -423,37 +419,15 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
regs
->
u_regs
[
UREG_I2
]
=
(
unsigned
long
)
&
sf
->
info
;
/* 5. signal handler */
regs
->
tpc
=
(
unsigned
long
)
k
a
->
sa
.
sa_handler
;
regs
->
tpc
=
(
unsigned
long
)
k
sig
->
ka
.
sa
.
sa_handler
;
regs
->
tnpc
=
(
regs
->
tpc
+
4
);
if
(
test_thread_flag
(
TIF_32BIT
))
{
regs
->
tpc
&=
0xffffffff
;
regs
->
tnpc
&=
0xffffffff
;
}
/* 4. return to kernel instructions */
regs
->
u_regs
[
UREG_I7
]
=
(
unsigned
long
)
k
a
->
ka_restorer
;
regs
->
u_regs
[
UREG_I7
]
=
(
unsigned
long
)
k
sig
->
ka
.
ka_restorer
;
return
0
;
sigill:
do_exit
(
SIGILL
);
return
-
EINVAL
;
sigsegv:
force_sigsegv
(
signo
,
current
);
return
-
EFAULT
;
}
static
inline
void
handle_signal
(
unsigned
long
signr
,
struct
k_sigaction
*
ka
,
siginfo_t
*
info
,
sigset_t
*
oldset
,
struct
pt_regs
*
regs
)
{
int
err
;
err
=
setup_rt_frame
(
ka
,
regs
,
signr
,
oldset
,
(
ka
->
sa
.
sa_flags
&
SA_SIGINFO
)
?
info
:
NULL
);
if
(
err
)
return
;
signal_delivered
(
signr
,
info
,
ka
,
regs
,
0
);
}
static
inline
void
syscall_restart
(
unsigned
long
orig_i0
,
struct
pt_regs
*
regs
,
...
...
@@ -483,11 +457,9 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
*/
static
void
do_signal
(
struct
pt_regs
*
regs
,
unsigned
long
orig_i0
)
{
struct
k
_sigaction
ka
;
struct
k
signal
ksig
;
int
restart_syscall
;
sigset_t
*
oldset
=
sigmask_to_save
();
siginfo_t
info
;
int
signr
;
bool
has_handler
;
/* It's a lot of work and synchronization to add a new ptrace
* register for GDB to save and restore in order to get
...
...
@@ -513,13 +485,13 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
#ifdef CONFIG_COMPAT
if
(
test_thread_flag
(
TIF_32BIT
))
{
extern
void
do_signal32
(
s
igset_t
*
,
s
truct
pt_regs
*
);
do_signal32
(
oldset
,
regs
);
extern
void
do_signal32
(
struct
pt_regs
*
);
do_signal32
(
regs
);
return
;
}
#endif
signr
=
get_signal_to_deliver
(
&
info
,
&
ka
,
regs
,
NULL
);
has_handler
=
get_signal
(
&
ksig
);
restart_syscall
=
0
;
if
(
pt_regs_is_syscall
(
regs
)
&&
...
...
@@ -528,34 +500,30 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
orig_i0
=
regs
->
u_regs
[
UREG_G6
];
}
if
(
signr
>
0
)
{
if
(
has_handler
)
{
if
(
restart_syscall
)
syscall_restart
(
orig_i0
,
regs
,
&
ka
.
sa
);
handle_signal
(
signr
,
&
ka
,
&
info
,
oldset
,
regs
);
return
;
}
if
(
restart_syscall
&&
(
regs
->
u_regs
[
UREG_I0
]
==
ERESTARTNOHAND
||
regs
->
u_regs
[
UREG_I0
]
==
ERESTARTSYS
||
regs
->
u_regs
[
UREG_I0
]
==
ERESTARTNOINTR
))
{
/* replay the system call when we are done */
regs
->
u_regs
[
UREG_I0
]
=
orig_i0
;
regs
->
tpc
-=
4
;
regs
->
tnpc
-=
4
;
pt_regs_clear_syscall
(
regs
);
}
if
(
restart_syscall
&&
regs
->
u_regs
[
UREG_I0
]
==
ERESTART_RESTARTBLOCK
)
{
regs
->
u_regs
[
UREG_G1
]
=
__NR_restart_syscall
;
regs
->
tpc
-=
4
;
regs
->
tnpc
-=
4
;
pt_regs_clear_syscall
(
regs
);
syscall_restart
(
orig_i0
,
regs
,
&
ksig
.
ka
.
sa
);
signal_setup_done
(
setup_rt_frame
(
&
ksig
,
regs
),
&
ksig
,
0
);
}
else
{
if
(
restart_syscall
)
{
switch
(
regs
->
u_regs
[
UREG_I0
])
{
case
ERESTARTNOHAND
:
case
ERESTARTSYS
:
case
ERESTARTNOINTR
:
/* replay the system call when we are done */
regs
->
u_regs
[
UREG_I0
]
=
orig_i0
;
regs
->
tpc
-=
4
;
regs
->
tnpc
-=
4
;
pt_regs_clear_syscall
(
regs
);
case
ERESTART_RESTARTBLOCK
:
regs
->
u_regs
[
UREG_G1
]
=
__NR_restart_syscall
;
regs
->
tpc
-=
4
;
regs
->
tnpc
-=
4
;
pt_regs_clear_syscall
(
regs
);
}
}
restore_saved_sigmask
();
}
/* If there's no signal to deliver, we just put the saved sigmask
* back
*/
restore_saved_sigmask
();
}
void
do_notify_resume
(
struct
pt_regs
*
regs
,
unsigned
long
orig_i0
,
unsigned
long
thread_info_flags
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment