summaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/kernel/signal.c')
-rw-r--r--arch/ia64/kernel/signal.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index 19be1f840..a0cca9da7 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -94,7 +94,7 @@ static long
restore_sigcontext (struct sigcontext *sc, struct pt_regs *pt)
{
struct switch_stack *sw = (struct switch_stack *) pt - 1;
- unsigned long ip, flags, nat, um;
+ unsigned long ip, flags, nat, um, cfm;
long err;
/* restore scratch that always needs gets updated during signal delivery: */
@@ -102,20 +102,24 @@ restore_sigcontext (struct sigcontext *sc, struct pt_regs *pt)
err |= __get_user(nat, &sc->sc_nat);
err |= __get_user(ip, &sc->sc_ip); /* instruction pointer */
- err |= __get_user(pt->ar_fpsr, &sc->sc_ar_fpsr);
- err |= __get_user(pt->ar_pfs, &sc->sc_ar_pfs);
+ err |= __get_user(cfm, &sc->sc_cfm);
err |= __get_user(um, &sc->sc_um); /* user mask */
err |= __get_user(pt->ar_rsc, &sc->sc_ar_rsc);
err |= __get_user(pt->ar_ccv, &sc->sc_ar_ccv);
err |= __get_user(pt->ar_unat, &sc->sc_ar_unat);
+ err |= __get_user(pt->ar_fpsr, &sc->sc_ar_fpsr);
+ err |= __get_user(pt->ar_pfs, &sc->sc_ar_pfs);
err |= __get_user(pt->pr, &sc->sc_pr); /* predicates */
err |= __get_user(pt->b0, &sc->sc_br[0]); /* b0 (rp) */
- err |= __get_user(pt->b6, &sc->sc_br[6]);
+ err |= __get_user(pt->b6, &sc->sc_br[6]); /* b6 */
+ err |= __get_user(pt->b7, &sc->sc_br[7]); /* b7 */
err |= __copy_from_user(&pt->r1, &sc->sc_gr[1], 3*8); /* r1-r3 */
err |= __copy_from_user(&pt->r8, &sc->sc_gr[8], 4*8); /* r8-r11 */
err |= __copy_from_user(&pt->r12, &sc->sc_gr[12], 4*8); /* r12-r15 */
err |= __copy_from_user(&pt->r16, &sc->sc_gr[16], 16*8); /* r16-r31 */
+ pt->cr_ifs = cfm | (1UL << 63);
+
/* establish new instruction pointer: */
pt->cr_iip = ip & ~0x3UL;
ia64_psr(pt)->ri = ip & 0x3;
@@ -240,6 +244,7 @@ setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct pt_regs *pt)
nat = ia64_get_nat_bits(pt, sw);
err = __put_user(flags, &sc->sc_flags);
+
err |= __put_user(nat, &sc->sc_nat);
err |= PUT_SIGSET(mask, &sc->sc_mask);
err |= __put_user(pt->cr_ipsr & IA64_PSR_UM, &sc->sc_um);
@@ -255,8 +260,8 @@ setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct pt_regs *pt)
err |= __copy_to_user(&sc->sc_gr[1], &pt->r1, 3*8); /* r1-r3 */
err |= __copy_to_user(&sc->sc_gr[8], &pt->r8, 4*8); /* r8-r11 */
- err |= __copy_to_user(&sc->sc_gr[12], &pt->r12, 4*8); /* r12-r15 */
- err |= __copy_to_user(&sc->sc_gr[16], &pt->r16, 16*8); /* r16-r31 */
+ err |= __copy_to_user(&sc->sc_gr[12], &pt->r12, 4*8); /* r12-r15 */
+ err |= __copy_to_user(&sc->sc_gr[16], &pt->r16, 16*8); /* r16-r31 */
err |= __put_user(pt->cr_iip + ia64_psr(pt)->ri, &sc->sc_ip);
err |= __put_user(pt->r12, &sc->sc_gr[12]); /* r12 */
@@ -415,10 +420,12 @@ ia64_do_signal (sigset_t *oldset, struct pt_regs *pt, long in_syscall)
if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
+ current->thread.siginfo = &info;
set_current_state(TASK_STOPPED);
notify_parent(current, SIGCHLD);
schedule();
signr = current->exit_code;
+ current->thread.siginfo = 0;
/* We're back. Did the debugger cancel the sig? */
if (!signr)