[PATCH] 2.5.38 s390 fixes: 16_fpu.

Martin Schwidefsky (schwidefsky@de.ibm.com)
Tue, 24 Sep 2002 19:22:04 +0200


Cleanup load/store of fpu register on s390.

diff -urN linux-2.5.38/arch/s390/kernel/Makefile linux-2.5.38-s390/arch/s390/kernel/Makefile
--- linux-2.5.38/arch/s390/kernel/Makefile Tue Sep 24 17:42:03 2002
+++ linux-2.5.38-s390/arch/s390/kernel/Makefile Tue Sep 24 17:43:15 2002
@@ -8,7 +8,7 @@
export-objs := debug.o ebcdic.o s390_ext.o smp.o s390_ksyms.o
obj-y := entry.o bitmap.o traps.o time.o process.o \
setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
- semaphore.o s390fpu.o reipl.o s390_ext.o debug.o
+ semaphore.o reipl.o s390_ext.o debug.o

obj-$(CONFIG_MODULES) += s390_ksyms.o
obj-$(CONFIG_SMP) += smp.o
diff -urN linux-2.5.38/arch/s390/kernel/process.c linux-2.5.38-s390/arch/s390/kernel/process.c
--- linux-2.5.38/arch/s390/kernel/process.c Tue Sep 24 17:43:15 2002
+++ linux-2.5.38-s390/arch/s390/kernel/process.c Tue Sep 24 17:43:15 2002
@@ -199,8 +199,13 @@

/* fake return stack for resume(), don't go back to schedule */
frame->gprs[9] = (unsigned long) frame;
- /* save fprs, if used in last task */
- save_fp_regs(&p->thread.fp_regs);
+ /*
+ * save fprs to current->thread.fp_regs to merge them with
+ * the emulated registers and then copy the result to the child.
+ */
+ save_fp_regs(&current->thread.fp_regs);
+ memcpy(&p->thread.fp_regs, &current->thread.fp_regs,
+ sizeof(s390_fp_regs));
p->thread.user_seg = __pa((unsigned long) p->mm->pgd) | _SEGMENT_TABLE;
/* start the new task with ar4 pointing to user space */
p->thread.ar4 = 1;
@@ -262,20 +267,13 @@
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
- error = do_execve(filename, (char **) regs.gprs[3], (char **) regs.gprs[4], &regs);
- if (error == 0)
- {
+ error = do_execve(filename, (char **) regs.gprs[3],
+ (char **) regs.gprs[4], &regs);
+ if (error == 0) {
current->ptrace &= ~PT_DTRACE;
- current->thread.fp_regs.fpc=0;
- if(MACHINE_HAS_IEEE)
- {
- __asm__ __volatile__
- ("sr 0,0\n\t"
- "sfpc 0,0\n\t"
- :
- :
- :"0");
- }
+ current->thread.fp_regs.fpc = 0;
+ if (MACHINE_HAS_IEEE)
+ asm volatile("sfpc %0,%0" : : "d" (0));
}
putname(filename);
out:
@@ -288,7 +286,12 @@
*/
int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs)
{
- save_fp_regs(fpregs);
+ /*
+ * save fprs to current->thread.fp_regs to merge them with
+ * the emulated registers and then copy the result to the dump.
+ */
+ save_fp_regs(&current->thread.fp_regs);
+ memcpy(fpregs, &current->thread.fp_regs, sizeof(s390_fp_regs));
return 1;
}

diff -urN linux-2.5.38/arch/s390/kernel/s390fpu.c linux-2.5.38-s390/arch/s390/kernel/s390fpu.c
--- linux-2.5.38/arch/s390/kernel/s390fpu.c Sun Sep 22 06:25:00 2002
+++ linux-2.5.38-s390/arch/s390/kernel/s390fpu.c Thu Jan 1 01:00:00 1970
@@ -1,138 +0,0 @@
-/*
- * arch/s390/kernel/s390fpu.c
- *
- * S390 version
- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
- *
- * s390fpu.h functions for saving & restoring the fpu state.
- *
- * I couldn't inline these as linux/sched.h included half the world
- * & was required to at the task structure.
- * & the functions were too complex to make macros from.
- * ( & as usual I didn't feel like debugging inline code ).
- */
-
-#include <linux/config.h>
-#include <linux/sched.h>
-
-int save_fp_regs1(s390_fp_regs *fpregs)
-{
- int has_ieee=MACHINE_HAS_IEEE;
-/*
- I don't think we can use STE here as this would load
- fp registers 0 & 2 into memory locations 0 & 1 etc.
- */
- asm volatile ("STD 0,8(%0)\n\t"
- "STD 2,24(%0)\n\t"
- "STD 4,40(%0)\n\t"
- "STD 6,56(%0)"
- :
- : "a" (fpregs)
- : "memory"
- );
- if(has_ieee)
- {
- asm volatile ("STFPC 0(%0)\n\t"
- "STD 1,16(%0)\n\t"
- "STD 3,32(%0)\n\t"
- "STD 5,48(%0)\n\t"
- "STD 7,64(%0)\n\t"
- "STD 8,72(%0)\n\t"
- "STD 9,80(%0)\n\t"
- "STD 10,88(%0)\n\t"
- "STD 11,96(%0)\n\t"
- "STD 12,104(%0)\n\t"
- "STD 13,112(%0)\n\t"
- "STD 14,120(%0)\n\t"
- "STD 15,128(%0)\n\t"
- :
- : "a" (fpregs)
- : "memory"
- );
- }
- return(has_ieee);
-}
-
-
-void save_fp_regs(s390_fp_regs *fpregs)
-{
-#if CONFIG_MATHEMU
- s390_fp_regs *currentfprs;
-
- if(!save_fp_regs1(fpregs))
- {
- currentfprs=&current->thread.fp_regs;
- fpregs->fpc=currentfprs->fpc;
- fpregs->fprs[1].d=currentfprs->fprs[1].d;
- fpregs->fprs[3].d=currentfprs->fprs[3].d;
- fpregs->fprs[5].d=currentfprs->fprs[5].d;
- fpregs->fprs[7].d=currentfprs->fprs[7].d;
- memcpy(&fpregs->fprs[8].d,&currentfprs->fprs[8].d,sizeof(freg_t)*8);
- }
-#else
- save_fp_regs1(fpregs);
-#endif
-}
-
-
-int restore_fp_regs1(s390_fp_regs *fpregs)
-{
- int has_ieee=MACHINE_HAS_IEEE;
-
- /* If we don't mask with the FPC_VALID_MASK here
- * we've got a very quick shutdown -h now command
- * via a kernel specification exception.
- */
- fpregs->fpc&=FPC_VALID_MASK;
- asm volatile ("LD 0,8(%0)\n\t"
- "LD 2,24(%0)\n\t"
- "LD 4,40(%0)\n\t"
- "LD 6,56(%0)"
- :
- : "a" (fpregs)
- : "memory"
- );
- if(has_ieee)
- {
- asm volatile ("LFPC 0(%0)\n\t"
- "LD 1,16(%0)\n\t"
- "LD 3,32(%0)\n\t"
- "LD 5,48(%0)\n\t"
- "LD 7,64(%0)\n\t"
- "LD 8,72(%0)\n\t"
- "LD 9,80(%0)\n\t"
- "LD 10,88(%0)\n\t"
- "LD 11,96(%0)\n\t"
- "LD 12,104(%0)\n\t"
- "LD 13,112(%0)\n\t"
- "LD 14,120(%0)\n\t"
- "LD 15,128(%0)\n\t"
- :
- : "a" (fpregs)
- : "memory"
- );
- }
- return(has_ieee);
-}
-
-void restore_fp_regs(s390_fp_regs *fpregs)
-{
-#if CONFIG_MATHEMU
- s390_fp_regs *currentfprs;
-
- if(!restore_fp_regs1(fpregs))
- {
- currentfprs=&current->thread.fp_regs;
- currentfprs->fpc=fpregs->fpc;
- currentfprs->fprs[1].d=fpregs->fprs[1].d;
- currentfprs->fprs[3].d=fpregs->fprs[3].d;
- currentfprs->fprs[5].d=fpregs->fprs[5].d;
- currentfprs->fprs[7].d=fpregs->fprs[7].d;
- memcpy(&currentfprs->fprs[8].d,&fpregs->fprs[8].d,sizeof(freg_t)*8);
- }
-#else
- restore_fp_regs1(fpregs);
-#endif
-}
-
diff -urN linux-2.5.38/arch/s390/kernel/signal.c linux-2.5.38-s390/arch/s390/kernel/signal.c
--- linux-2.5.38/arch/s390/kernel/signal.c Sun Sep 22 06:25:04 2002
+++ linux-2.5.38-s390/arch/s390/kernel/signal.c Tue Sep 24 17:43:15 2002
@@ -49,13 +49,14 @@
struct ucontext uc;
} rt_sigframe;

-asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
+int do_signal(struct pt_regs *regs, sigset_t *oldset);

/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
asmlinkage int
-sys_sigsuspend(struct pt_regs * regs,int history0, int history1, old_sigset_t mask)
+sys_sigsuspend(struct pt_regs * regs, int history0, int history1,
+ old_sigset_t mask)
{
sigset_t saveset;

@@ -147,37 +148,39 @@
static int save_sigregs(struct pt_regs *regs,_sigregs *sregs)
{
int err;
- s390_fp_regs fpregs;

- err = __copy_to_user(&sregs->regs,regs,sizeof(_s390_regs_common));
- if(!err)
- {
- save_fp_regs(&fpregs);
- err=__copy_to_user(&sregs->fpregs,&fpregs,sizeof(fpregs));
- }
- return(err);
-
+ err = __copy_to_user(&sregs->regs, regs, sizeof(_s390_regs_common));
+ if (err != 0)
+ return err;
+ /*
+ * We have to store the fp registers to current->thread.fp_regs
+ * to merge them with the emulated registers.
+ */
+ save_fp_regs(&current->thread.fp_regs);
+ return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
+ sizeof(s390_fp_regs));
}

/* Returns positive number on error */
static int restore_sigregs(struct pt_regs *regs,_sigregs *sregs)
{
int err;
- s390_fp_regs fpregs;
- psw_t saved_psw=regs->psw;
- err=__copy_from_user(regs,&sregs->regs,sizeof(_s390_regs_common));
- if(!err)
- {
- regs->trap = -1; /* disable syscall checks */
- regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)|
- (regs->psw.mask&PSW_MASK_DEBUGCHANGE);
- regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)|
- (regs->psw.addr&PSW_ADDR_DEBUGCHANGE);
- err=__copy_from_user(&fpregs,&sregs->fpregs,sizeof(fpregs));
- if(!err)
- restore_fp_regs(&fpregs);
- }
- return(err);
+
+ err = __copy_from_user(regs, &sregs->regs, sizeof(_s390_regs_common));
+ regs->psw.mask = _USER_PSW_MASK | (regs->psw.mask & PSW_MASK_DEBUGCHANGE);
+ regs->psw.addr |= _ADDR_31;
+ if (err)
+ return err;
+
+ err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
+ sizeof(s390_fp_regs));
+ current->thread.fp_regs.fpc &= FPC_VALID_MASK;
+ if (err)
+ return err;
+
+ restore_fp_regs(&current->thread.fp_regs);
+ regs->trap = -1; /* disable syscall checks */
+ return 0;
}

asmlinkage long sys_sigreturn(struct pt_regs *regs)
diff -urN linux-2.5.38/arch/s390x/kernel/Makefile linux-2.5.38-s390/arch/s390x/kernel/Makefile
--- linux-2.5.38/arch/s390x/kernel/Makefile Tue Sep 24 17:42:03 2002
+++ linux-2.5.38-s390/arch/s390x/kernel/Makefile Tue Sep 24 17:43:15 2002
@@ -10,7 +10,7 @@

obj-y := entry.o bitmap.o traps.o time.o process.o \
setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
- semaphore.o s390fpu.o reipl.o s390_ext.o debug.o
+ semaphore.o reipl.o s390_ext.o debug.o

obj-$(CONFIG_MODULES) += s390_ksyms.o
obj-$(CONFIG_SMP) += smp.o
diff -urN linux-2.5.38/arch/s390x/kernel/process.c linux-2.5.38-s390/arch/s390x/kernel/process.c
--- linux-2.5.38/arch/s390x/kernel/process.c Tue Sep 24 17:43:15 2002
+++ linux-2.5.38-s390/arch/s390x/kernel/process.c Tue Sep 24 17:43:15 2002
@@ -257,15 +257,12 @@
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
- error = do_execve(filename, (char **) regs.gprs[3], (char **) regs.gprs[4], &regs);
- if (error == 0)
- {
+ error = do_execve(filename, (char **) regs.gprs[3],
+ (char **) regs.gprs[4], &regs);
+ if (error == 0) {
current->ptrace &= ~PT_DTRACE;
- current->thread.fp_regs.fpc=0;
- __asm__ __volatile__
- ("sr 0,0\n\t"
- "sfpc 0,0\n\t"
- : : :"0");
+ current->thread.fp_regs.fpc = 0;
+ asm volatile("sfpc %0,%0" : : "d" (0));
}
putname(filename);
out:
diff -urN linux-2.5.38/arch/s390x/kernel/s390fpu.c linux-2.5.38-s390/arch/s390x/kernel/s390fpu.c
--- linux-2.5.38/arch/s390x/kernel/s390fpu.c Sun Sep 22 06:25:30 2002
+++ linux-2.5.38-s390/arch/s390x/kernel/s390fpu.c Thu Jan 1 01:00:00 1970
@@ -1,87 +0,0 @@
-/*
- * arch/s390/kernel/s390fpu.c
- *
- * S390 version
- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
- *
- * s390fpu.h functions for saving & restoring the fpu state.
- *
- * I couldn't inline these as linux/sched.h included half the world
- * & was required to at the task structure.
- * & the functions were too complex to make macros from.
- * ( & as usual I didn't feel like debugging inline code ).
- */
-
-#include <linux/sched.h>
-
-void save_fp_regs(s390_fp_regs *fpregs)
-{
-/*
- * I don't think we can use STE here as this would load
- * fp registers 0 & 2 into memory locations 0 & 1 etc.
- */
- asm volatile ("STFPC 0(%0)\n\t"
- "STD 0,8(%0)\n\t"
- "STD 1,16(%0)\n\t"
- "STD 2,24(%0)\n\t"
- "STD 3,32(%0)\n\t"
- "STD 4,40(%0)\n\t"
- "STD 5,48(%0)\n\t"
- "STD 6,56(%0)\n\t"
- "STD 7,64(%0)\n\t"
- "STD 8,72(%0)\n\t"
- "STD 9,80(%0)\n\t"
- "STD 10,88(%0)\n\t"
- "STD 11,96(%0)\n\t"
- "STD 12,104(%0)\n\t"
- "STD 13,112(%0)\n\t"
- "STD 14,120(%0)\n\t"
- "STD 15,128(%0)\n\t"
- :
- : "a" (fpregs)
- : "memory"
- );
-}
-
-void restore_fp_regs(s390_fp_regs *fpregs)
-{
- /* If we don't mask with the FPC_VALID_MASK here
- * we've got a very quick shutdown -h now command
- * via a kernel specification exception.
- */
- fpregs->fpc&=FPC_VALID_MASK;
- asm volatile ("LFPC 0(%0)\n\t"
- "LD 0,8(%0)\n\t"
- "LD 1,16(%0)\n\t"
- "LD 2,24(%0)\n\t"
- "LD 3,32(%0)\n\t"
- "LD 4,40(%0)\n\t"
- "LD 5,48(%0)\n\t"
- "LD 6,56(%0)\n\t"
- "LD 7,64(%0)\n\t"
- "LD 8,72(%0)\n\t"
- "LD 9,80(%0)\n\t"
- "LD 10,88(%0)\n\t"
- "LD 11,96(%0)\n\t"
- "LD 12,104(%0)\n\t"
- "LD 13,112(%0)\n\t"
- "LD 14,120(%0)\n\t"
- "LD 15,128(%0)\n\t"
- :
- : "a" (fpregs)
- : "memory"
- );
-}
-
-
-
-
-
-
-
-
-
-
-
-
diff -urN linux-2.5.38/arch/s390x/kernel/signal.c linux-2.5.38-s390/arch/s390x/kernel/signal.c
--- linux-2.5.38/arch/s390x/kernel/signal.c Sun Sep 22 06:25:12 2002
+++ linux-2.5.38-s390/arch/s390x/kernel/signal.c Tue Sep 24 17:43:15 2002
@@ -144,40 +144,37 @@


/* Returns non-zero on fault */
-static int save_sigregs(struct pt_regs *regs,_sigregs *sregs)
+static int save_sigregs(struct pt_regs *regs, _sigregs *sregs)
{
int err;
- s390_fp_regs fpregs;

- err = __copy_to_user(&sregs->regs,regs,sizeof(_s390_regs_common));
- if(!err)
- {
- save_fp_regs(&fpregs);
- err=__copy_to_user(&sregs->fpregs,&fpregs,sizeof(fpregs));
- }
- return(err);
-
+ err = __copy_to_user(&sregs->regs, regs, sizeof(_s390_regs_common));
+ if (err != 0)
+ return err;
+ save_fp_regs(&current->thread.fp_regs);
+ return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
+ sizeof(s390_fp_regs));
}

/* Returns positive number on error */
-static int restore_sigregs(struct pt_regs *regs,_sigregs *sregs)
+static int restore_sigregs(struct pt_regs *regs, _sigregs *sregs)
{
int err;
- s390_fp_regs fpregs;
- psw_t saved_psw=regs->psw;
- err=__copy_from_user(regs,&sregs->regs,sizeof(_s390_regs_common));
- if(!err)
- {
- regs->trap = -1; /* disable syscall checks */
- regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)|
- (regs->psw.mask&PSW_MASK_DEBUGCHANGE);
- regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)|
- (regs->psw.addr&PSW_ADDR_DEBUGCHANGE);
- err=__copy_from_user(&fpregs,&sregs->fpregs,sizeof(fpregs));
- if(!err)
- restore_fp_regs(&fpregs);
- }
- return(err);
+
+ err = __copy_from_user(regs, &sregs->regs, sizeof(_s390_regs_common));
+ regs->psw.mask = _USER_PSW_MASK | (regs->psw.mask & PSW_MASK_DEBUGCHANGE);
+ if (err)
+ return err;
+
+ err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
+ sizeof(s390_fp_regs));
+ current->thread.fp_regs.fpc &= FPC_VALID_MASK;
+ if (err)
+ return err;
+
+ restore_fp_regs(&current->thread.fp_regs);
+ regs->trap = -1; /* disable syscall checks */
+ return 0;
}

asmlinkage long sys_sigreturn(struct pt_regs *regs)
diff -urN linux-2.5.38/arch/s390x/kernel/signal32.c linux-2.5.38-s390/arch/s390x/kernel/signal32.c
--- linux-2.5.38/arch/s390x/kernel/signal32.c Sun Sep 22 06:25:09 2002
+++ linux-2.5.38-s390/arch/s390x/kernel/signal32.c Tue Sep 24 17:43:15 2002
@@ -32,7 +32,11 @@

#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))

+#define _ADDR_31 0x80000000
+#define _USER_PSW_MASK_EMU32 0x070DC000
#define _USER_PSW_MASK32 0x0705C00080000000
+#define PSW_MASK_DEBUGCHANGE32 0x00003000UL
+#define PSW_ADDR_DEBUGCHANGE32 0x7FFFFFFFUL

typedef struct
{
@@ -290,55 +294,48 @@

static int save_sigregs32(struct pt_regs *regs,_sigregs32 *sregs)
{
- int err = 0;
- s390_fp_regs fpregs;
- int i;
-
- for(i=0; i<NUM_GPRS; i++)
- err |= __put_user(regs->gprs[i], &sregs->regs.gprs[i]);
- for(i=0; i<NUM_ACRS; i++)
- err |= __put_user(regs->acrs[i], &sregs->regs.acrs[i]);
- err |= __copy_to_user(&sregs->regs.psw.mask, &regs->psw.mask, 4);
- err |= __copy_to_user(&sregs->regs.psw.addr, ((char*)&regs->psw.addr)+4, 4);
- if(!err)
- {
- save_fp_regs(&fpregs);
- __put_user(fpregs.fpc, &sregs->fpregs.fpc);
- for(i=0; i<NUM_FPRS; i++)
- err |= __put_user(fpregs.fprs[i].d, &sregs->fpregs.fprs[i].d);
- }
- return(err);
-
+ _s390_regs_common32 regs32;
+ int err, i;
+
+ regs32.psw.mask = _USER_PSW_MASK_EMU32 |
+ (__u32)((regs->psw.mask & PSW_MASK_DEBUGCHANGE) >> 32);
+ regs32.psw.addr = _ADDR_31 | (__u32) regs->psw.addr;
+ for (i = 0; i < NUM_GPRS; i++)
+ regs32.gprs[i] = (__u32) regs->gprs[i];
+ memcpy(regs32.acrs, regs->acrs, sizeof(regs32.acrs));
+ err = __copy_to_user(&sregs->regs, &regs32, sizeof(regs32));
+ if (err)
+ return err;
+ save_fp_regs(&current->thread.fp_regs);
+ /* s390_fp_regs and _s390_fp_regs32 are the same ! */
+ return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
+ sizeof(_s390_fp_regs32));
}

static int restore_sigregs32(struct pt_regs *regs,_sigregs32 *sregs)
{
- int err = 0;
- s390_fp_regs fpregs;
- psw_t saved_psw=regs->psw;
- int i;
-
- for(i=0; i<NUM_GPRS; i++)
- err |= __get_user(regs->gprs[i], &sregs->regs.gprs[i]);
- for(i=0; i<NUM_ACRS; i++)
- err |= __get_user(regs->acrs[i], &sregs->regs.acrs[i]);
- err |= __copy_from_user(&regs->psw.mask, &sregs->regs.psw.mask, 4);
- err |= __copy_from_user(((char*)&regs->psw.addr)+4, &sregs->regs.psw.addr, 4);
-
- if(!err)
- {
- regs->trap = -1; /* disable syscall checks */
- regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)|
- (regs->psw.mask&PSW_MASK_DEBUGCHANGE);
- regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)|
- (regs->psw.addr&PSW_ADDR_DEBUGCHANGE);
- __get_user(fpregs.fpc, &sregs->fpregs.fpc);
- for(i=0; i<NUM_FPRS; i++)
- err |= __get_user(fpregs.fprs[i].d, &sregs->fpregs.fprs[i].d);
- if(!err)
- restore_fp_regs(&fpregs);
- }
- return(err);
+ _s390_regs_common32 regs32;
+ int err, i;
+
+ err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
+ if (err)
+ return err;
+ regs->psw.mask = _USER_PSW_MASK32 |
+ (__u64)(regs32.psw.mask & PSW_MASK_DEBUGCHANGE32) << 32;
+ regs->psw.addr = (__u64)(regs32.psw.addr & PSW_ADDR_DEBUGCHANGE32);
+ for (i = 0; i < NUM_GPRS; i++)
+ regs->gprs[i] = (__u64) regs32.gprs[i];
+ memcpy(regs->acrs, regs32.acrs, sizeof(regs32.acrs));
+
+ err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
+ sizeof(_s390_fp_regs32));
+ current->thread.fp_regs.fpc &= FPC_VALID_MASK;
+ if (err)
+ return err;
+
+ restore_fp_regs(&current->thread.fp_regs);
+ regs->trap = -1; /* disable syscall checks */
+ return 0;
}

asmlinkage long sys32_sigreturn(struct pt_regs *regs)
diff -urN linux-2.5.38/include/asm-s390/system.h linux-2.5.38-s390/include/asm-s390/system.h
--- linux-2.5.38/include/asm-s390/system.h Tue Sep 24 17:43:15 2002
+++ linux-2.5.38-s390/include/asm-s390/system.h Tue Sep 24 17:43:15 2002
@@ -12,22 +12,79 @@
#define __ASM_SYSTEM_H

#include <linux/config.h>
+#include <linux/kernel.h>
#include <asm/types.h>
+#include <asm/ptrace.h>
+#include <asm/setup.h>
+
#ifdef __KERNEL__
-#include <asm/lowcore.h>
-#endif
-#include <linux/kernel.h>
+
+struct task_struct;
+
+extern struct task_struct *resume(void *, void *);
+
+static inline void save_fp_regs(s390_fp_regs *fpregs)
+{
+ asm volatile (
+ " std 0,8(%0)\n"
+ " std 2,24(%0)\n"
+ " std 4,40(%0)\n"
+ " std 6,56(%0)"
+ : : "a" (fpregs) : "memory" );
+ if (!MACHINE_HAS_IEEE)
+ return;
+ asm volatile(
+ " stfpc 0(%0)\n"
+ " std 1,16(%0)\n"
+ " std 3,32(%0)\n"
+ " std 5,48(%0)\n"
+ " std 7,64(%0)\n"
+ " std 8,72(%0)\n"
+ " std 9,80(%0)\n"
+ " std 10,88(%0)\n"
+ " std 11,96(%0)\n"
+ " std 12,104(%0)\n"
+ " std 13,112(%0)\n"
+ " std 14,120(%0)\n"
+ " std 15,128(%0)\n"
+ : : "a" (fpregs) : "memory" );
+}
+
+static inline void restore_fp_regs(s390_fp_regs *fpregs)
+{
+ asm volatile (
+ " ld 0,8(%0)\n"
+ " ld 2,24(%0)\n"
+ " ld 4,40(%0)\n"
+ " ld 6,56(%0)"
+ : : "a" (fpregs));
+ if (!MACHINE_HAS_IEEE)
+ return;
+ asm volatile(
+ " lfpc 0(%0)\n"
+ " ld 1,16(%0)\n"
+ " ld 3,32(%0)\n"
+ " ld 5,48(%0)\n"
+ " ld 7,64(%0)\n"
+ " ld 8,72(%0)\n"
+ " ld 9,80(%0)\n"
+ " ld 10,88(%0)\n"
+ " ld 11,96(%0)\n"
+ " ld 12,104(%0)\n"
+ " ld 13,112(%0)\n"
+ " ld 14,120(%0)\n"
+ " ld 15,128(%0)\n"
+ : : "a" (fpregs));
+}

#define switch_to(prev,next,last) do { \
if (prev == next) \
break; \
- save_fp_regs1(&prev->thread.fp_regs); \
- restore_fp_regs1(&next->thread.fp_regs); \
+ save_fp_regs(&prev->thread.fp_regs); \
+ restore_fp_regs(&next->thread.fp_regs); \
resume(prev,next); \
} while (0)

-struct task_struct;
-
#define nop() __asm__ __volatile__ ("nop")

#define xchg(ptr,x) \
@@ -281,23 +338,13 @@
#define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit)
#define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit)

-#endif
-
-#ifdef __KERNEL__
-extern struct task_struct *resume(void *, void *);
-
-extern int save_fp_regs1(s390_fp_regs *fpregs);
-extern void save_fp_regs(s390_fp_regs *fpregs);
-extern int restore_fp_regs1(s390_fp_regs *fpregs);
-extern void restore_fp_regs(s390_fp_regs *fpregs);
+#endif /* CONFIG_SMP */

extern void (*_machine_restart)(char *command);
extern void (*_machine_halt)(void);
extern void (*_machine_power_off)(void);

-#endif
+#endif /* __KERNEL__ */

#endif

-
-
diff -urN linux-2.5.38/include/asm-s390x/system.h linux-2.5.38-s390/include/asm-s390x/system.h
--- linux-2.5.38/include/asm-s390x/system.h Tue Sep 24 17:43:15 2002
+++ linux-2.5.38-s390/include/asm-s390x/system.h Tue Sep 24 17:43:15 2002
@@ -12,11 +12,62 @@
#define __ASM_SYSTEM_H

#include <linux/config.h>
+#include <linux/kernel.h>
#include <asm/types.h>
+#include <asm/ptrace.h>
+#include <asm/setup.h>
+
#ifdef __KERNEL__
-#include <asm/lowcore.h>
-#endif
-#include <linux/kernel.h>
+
+struct task_struct;
+
+extern struct task_struct *resume(void *, void *);
+
+static inline void save_fp_regs(s390_fp_regs *fpregs)
+{
+ asm volatile (
+ " stfpc 0(%0)\n"
+ " std 0,8(%0)\n"
+ " std 1,16(%0)\n"
+ " std 2,24(%0)\n"
+ " std 3,32(%0)\n"
+ " std 4,40(%0)\n"
+ " std 5,48(%0)\n"
+ " std 6,56(%0)\n"
+ " std 7,64(%0)\n"
+ " std 8,72(%0)\n"
+ " std 9,80(%0)\n"
+ " std 10,88(%0)\n"
+ " std 11,96(%0)\n"
+ " std 12,104(%0)\n"
+ " std 13,112(%0)\n"
+ " std 14,120(%0)\n"
+ " std 15,128(%0)\n"
+ : : "a" (fpregs) : "memory" );
+}
+
+static inline void restore_fp_regs(s390_fp_regs *fpregs)
+{
+ asm volatile (
+ " lfpc 0(%0)\n"
+ " ld 0,8(%0)\n"
+ " ld 1,16(%0)\n"
+ " ld 2,24(%0)\n"
+ " ld 3,32(%0)\n"
+ " ld 4,40(%0)\n"
+ " ld 5,48(%0)\n"
+ " ld 6,56(%0)\n"
+ " ld 7,64(%0)\n"
+ " ld 8,72(%0)\n"
+ " ld 9,80(%0)\n"
+ " ld 10,88(%0)\n"
+ " ld 11,96(%0)\n"
+ " ld 12,104(%0)\n"
+ " ld 13,112(%0)\n"
+ " ld 14,120(%0)\n"
+ " ld 15,128(%0)\n"
+ : : "a" (fpregs));
+}

#define switch_to(prev,next,last) do { \
if (prev == next) \
@@ -26,8 +77,6 @@
resume(prev,next); \
} while (0)

-struct task_struct;
-
#define nop() __asm__ __volatile__ ("nop")

#define xchg(ptr,x) \
@@ -297,23 +346,13 @@
#define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit)
#define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit)

-#endif
-
-#ifdef __KERNEL__
-extern struct task_struct *resume(void *, void *);
-
-extern int save_fp_regs1(s390_fp_regs *fpregs);
-extern void save_fp_regs(s390_fp_regs *fpregs);
-extern int restore_fp_regs1(s390_fp_regs *fpregs);
-extern void restore_fp_regs(s390_fp_regs *fpregs);
+#endif /* CONFIG_SMP */

extern void (*_machine_restart)(char *command);
extern void (*_machine_halt)(void);
extern void (*_machine_power_off)(void);

-#endif
+#endif /* __KERNEL __ */

#endif

-
-

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/