patch-2.1.53 linux/arch/sparc64/kernel/signal.c
Next file: linux/arch/sparc64/kernel/signal32.c
Previous file: linux/arch/sparc64/kernel/setup.c
Back to the patch index
Back to the overall index
- Lines: 146
- Date:
Thu Sep 4 12:54:48 1997
- Orig file:
v2.1.52/linux/arch/sparc64/kernel/signal.c
- Orig date:
Mon Aug 18 18:19:45 1997
diff -u --recursive --new-file v2.1.52/linux/arch/sparc64/kernel/signal.c linux/arch/sparc64/kernel/signal.c
@@ -1,4 +1,4 @@
-/* $Id: signal.c,v 1.22 1997/08/05 19:19:36 davem Exp $
+/* $Id: signal.c,v 1.24 1997/09/02 20:53:03 davem Exp $
* arch/sparc64/kernel/signal.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
@@ -67,7 +67,7 @@
regs->tpc = pc;
regs->tnpc = npc;
__get_user(regs->y, &((*grp)[MC_Y]));
- __get_user(tstate, &((*grp)[MC_Y]));
+ __get_user(tstate, &((*grp)[MC_TSTATE]));
regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC));
__get_user(regs->u_regs[UREG_G1], (&(*grp)[MC_G1]));
@@ -94,11 +94,18 @@
__get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));
if(fenab) {
unsigned long *fpregs = (unsigned long *)(regs+1);
- copy_from_user(fpregs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs),
- (sizeof(unsigned long) * 32));
+ unsigned long fprs;
+ __get_user(fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs));
+ if (fprs & FPRS_DL)
+ copy_from_user(fpregs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs),
+ (sizeof(unsigned int) * 32));
+ if (fprs & FPRS_DU)
+ copy_from_user(fpregs+16, ((unsigned long *)&(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs))+16,
+ (sizeof(unsigned int) * 32));
__get_user(fpregs[32], &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
__get_user(fpregs[33], &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
- regs->fprs = FPRS_FEF;
+ regs->fprs = fprs;
+ regs->tstate |= TSTATE_PEF;
}
return;
do_sigsegv:
@@ -113,7 +120,7 @@
mc_gregset_t *grp;
mcontext_t *mcp;
unsigned long fp, i7;
- unsigned char fenab = (current->flags & PF_USEDFPU);
+ unsigned char fenab = (current->tss.flags & SPARC_FLAG_USEDFPU);
synchronize_user_stack();
if(tp->w_saved || clear_user(ucp, sizeof(*ucp)))
@@ -154,11 +161,25 @@
__put_user(fenab, &(mcp->mc_fpregs.mcfpu_enab));
if(fenab) {
unsigned long *fpregs = (unsigned long *)(regs+1);
- copy_to_user(&(mcp->mc_fpregs.mcfpu_fregs), fpregs,
- (sizeof(unsigned long) * 32));
+ unsigned long fprs;
+
+ fprs = (regs->fprs & FPRS_FEF) |
+ (current->tss.flags & (SPARC_FLAG_USEDFPUL | SPARC_FLAG_USEDFPUU));
+ if (fprs & FPRS_DL)
+ copy_to_user(&(mcp->mc_fpregs.mcfpu_fregs), fpregs,
+ (sizeof(unsigned int) * 32));
+ else
+ clear_user(&(mcp->mc_fpregs.mcfpu_fregs),
+ (sizeof(unsigned int) * 32));
+ if (fprs & FPRS_DU)
+ copy_to_user(((unsigned long *)&(mcp->mc_fpregs.mcfpu_fregs))+16, fpregs+16,
+ (sizeof(unsigned int) * 32));
+ else
+ clear_user(((unsigned long *)&(mcp->mc_fpregs.mcfpu_fregs))+16,
+ (sizeof(unsigned int) * 32));
__put_user(fpregs[32], &(mcp->mc_fpregs.mcfpu_fsr));
__put_user(fpregs[33], &(mcp->mc_fpregs.mcfpu_gsr));
- __put_user(FPRS_FEF, &(mcp->mc_fpregs.mcfpu_fprs));
+ __put_user(fprs, &(mcp->mc_fpregs.mcfpu_fprs));
}
return;
do_sigsegv:
@@ -241,11 +262,19 @@
restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
{
unsigned long *fpregs = (unsigned long *)(regs+1);
- copy_from_user(fpregs, &fpu->si_float_regs[0],
- (sizeof(unsigned int) * 64));
+ unsigned long fprs;
+
+ __get_user(fprs, &fpu->si_fprs);
+ if (fprs & FPRS_DL)
+ copy_from_user(fpregs, &fpu->si_float_regs[0],
+ (sizeof(unsigned int) * 32));
+ if (fprs & FPRS_DU)
+ copy_from_user(fpregs+16, &fpu->si_float_regs[32],
+ (sizeof(unsigned int) * 32));
__get_user(fpregs[32], &fpu->si_fsr);
__get_user(fpregs[33], &fpu->si_gsr);
- regs->fprs = FPRS_FEF;
+ regs->fprs = fprs;
+ regs->tstate |= TSTATE_PEF;
}
void do_sigreturn(struct pt_regs *regs)
@@ -312,11 +341,26 @@
save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
{
unsigned long *fpregs = (unsigned long *)(regs+1);
- copy_to_user(&fpu->si_float_regs[0], fpregs,
- (sizeof(unsigned int) * 64));
+ unsigned long fprs;
+
+ fprs = (regs->fprs & FPRS_FEF) |
+ (current->tss.flags & (SPARC_FLAG_USEDFPUL | SPARC_FLAG_USEDFPUU));
+ if (fprs & FPRS_DL)
+ copy_to_user(&fpu->si_float_regs[0], fpregs,
+ (sizeof(unsigned int) * 32));
+ else
+ clear_user(&fpu->si_float_regs[0],
+ (sizeof(unsigned int) * 32));
+ if (fprs & FPRS_DU)
+ copy_to_user(&fpu->si_float_regs[32], fpregs+16,
+ (sizeof(unsigned int) * 32));
+ else
+ clear_user(&fpu->si_float_regs[32],
+ (sizeof(unsigned int) * 32));
__put_user(fpregs[32], &fpu->si_fsr);
__put_user(fpregs[33], &fpu->si_gsr);
- regs->fprs = 0;
+ __put_user(fprs, &fpu->si_fprs);
+ regs->tstate &= ~TSTATE_PEF;
}
static inline void
@@ -329,7 +373,7 @@
/* 1. Make sure everything is clean */
synchronize_user_stack();
sigframe_size = NF_ALIGNEDSZ;
- if (!(current->flags & PF_USEDFPU))
+ if (!(current->tss.flags & SPARC_FLAG_USEDFPU))
sigframe_size -= sizeof(__siginfo_fpu_t);
sf = (struct new_signal_frame *)
@@ -347,7 +391,7 @@
/* 2. Save the current process state */
copy_to_user(&sf->info.si_regs, regs, sizeof (*regs));
- if (current->flags & PF_USEDFPU) {
+ if (current->tss.flags & SPARC_FLAG_USEDFPU) {
save_fpu_state(regs, &sf->fpu_state);
__put_user((u64)&sf->fpu_state, &sf->fpu_save);
} else {
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov