linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] 2.5.38 s390 fixes: 16_fpu.
@ 2002-09-24 17:22 Martin Schwidefsky
  0 siblings, 0 replies; only message in thread
From: Martin Schwidefsky @ 2002-09-24 17:22 UTC (permalink / raw)
  To: linux-kernel, torvalds

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
 
-
-


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2002-09-24 17:30 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-09-24 17:22 [PATCH] 2.5.38 s390 fixes: 16_fpu Martin Schwidefsky

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).