]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] s390 update (18/27): fpu registers.
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 4 Oct 2002 04:49:01 +0000 (21:49 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Fri, 4 Oct 2002 04:49:01 +0000 (21:49 -0700)
Cleanup load/store of fpu register on s390.

arch/s390/kernel/Makefile
arch/s390/kernel/process.c
arch/s390/kernel/s390fpu.c [deleted file]
arch/s390/kernel/signal.c
arch/s390x/kernel/Makefile
arch/s390x/kernel/process.c
arch/s390x/kernel/s390fpu.c [deleted file]
arch/s390x/kernel/signal.c
arch/s390x/kernel/signal32.c
include/asm-s390/system.h
include/asm-s390x/system.h

index 5b804b0acb3faf34d9a71d8616f1e4a74f8e8e82..839941e154d60741dedce85dc301ca418e29a276 100644 (file)
@@ -8,7 +8,7 @@ EXTRA_AFLAGS    := -traditional
 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
index dd0c32df7485391651caf4ff67057d48f09f9478..72bb0b10cf473248de93c698ef3a50e5a6dc5ac5 100644 (file)
@@ -199,8 +199,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
 
         /* 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 process with ar4 pointing to the correct address space */
        p->thread.ar4 = get_fs().ar4;
@@ -262,20 +267,13 @@ asmlinkage int sys_execve(struct pt_regs regs)
         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 @@ out:
  */
 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 --git a/arch/s390/kernel/s390fpu.c b/arch/s390/kernel/s390fpu.c
deleted file mode 100644 (file)
index cc0de96..0000000
+++ /dev/null
@@ -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
-}
-
index f13b392e0d2367d8a1e30683e8f6d5465ea1de8f..ecc9771858fa1f16356dd8e1fca72a9cf711270b 100644 (file)
@@ -49,13 +49,14 @@ typedef struct
        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 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs)
 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)
index 54c69349197c074493a8077de3d076273839186f..09c0fcf2d6cbc21555c8fdd609ff6467baefa399 100644 (file)
@@ -10,7 +10,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
index 6f536c756351edef042019d45ea7819a25866a6c..20b4223c5a72164da073b9f8fcdbefb16f9f80a0 100644 (file)
@@ -257,15 +257,12 @@ asmlinkage int sys_execve(struct pt_regs regs)
         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 --git a/arch/s390x/kernel/s390fpu.c b/arch/s390x/kernel/s390fpu.c
deleted file mode 100644 (file)
index 7dfea3f..0000000
+++ /dev/null
@@ -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"
-               );
-}
-
-
-
-
-
-
-
-
-
-
-
-
index 0215decea5ba2510b34bf9b06dcf44e5000b595b..6d4d9fe2812f624f3262b526e9c0d882a8dd7223 100644 (file)
@@ -144,40 +144,37 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs)
 
 
 /* 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)
index 7e52bc68df9e33de5bdb2b7a1db3f597ecd803de..c16a04d33eeabed8430f16e00949524581d47e20 100644 (file)
 
 #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 @@ sys32_sigaltstack(const stack_t32 *uss, stack_t32 *uoss, struct pt_regs *regs)
 
 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)
index 3aa63017653a19bed6ba601149236a73c0120cb8..e0a825fdc76384ff0c4d8e4e343738c9499c27be 100644 (file)
 #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 @@ extern void smp_ctl_clear_bit(int cr, int bit);
 #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
 
-
-
index a77c1995018dcc8ea6a371ffb8f7d5c1bdd31cf1..74470fc09eddbd48c7e157ad6ebfdfd4cf93740e 100644 (file)
 #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 @@ extern void smp_ctl_clear_bit(int cr, int bit);
 #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
 
-
-