patch-2.1.44 linux/arch/sparc64/kernel/signal32.c

Next file: linux/arch/sparc64/kernel/sparc64_ksyms.c
Previous file: linux/arch/sparc64/kernel/signal.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/signal32.c linux/arch/sparc64/kernel/signal32.c
@@ -1,4 +1,4 @@
-/*  $Id: signal32.c,v 1.13 1997/06/01 05:46:09 davem Exp $
+/*  $Id: signal32.c,v 1.23 1997/07/05 07:09:15 davem Exp $
  *  arch/sparc64/kernel/signal32.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -67,13 +67,12 @@
  * (we have enough in there to work with clone).
  * All the interesting bits are in the info field.
  */
-
 struct new_signal_frame32 {
 	struct sparc_stackf32	ss;
 	__siginfo32_t		info;
 	/* __siginfo_fpu32_t * */ u32 fpu_save;
 	unsigned int		insns [2];
-	__siginfo_fpu32_t	fpu_state;
+	__siginfo_fpu_t		fpu_state;
 };
 
 /* Align macros */
@@ -115,25 +114,12 @@
 	}
 }
 
-static inline void
-restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu32_t *fpu)
+static inline void restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu)
 {
-#ifdef __SMP__
-	if (current->flags & PF_USEDFPU)
-		regs->tstate &= ~(TSTATE_PEF);
-#else
-	if (current == last_task_used_math) {
-		last_task_used_math = 0;
-		regs->tstate &= ~(TSTATE_PEF);
-	}
-#endif
-	current->used_math = 1;
-	current->flags &= ~PF_USEDFPU;
-
-	copy_from_user(&current->tss.float_regs[0],
-		       &fpu->si_float_regs[0],
-		       (sizeof(unsigned int) * 32));
-	__get_user(current->tss.fsr, &fpu->si_fsr);
+	unsigned long *fpregs = (unsigned long *)(regs + 1);
+	copy_from_user(fpregs, &fpu->si_float_regs[0], (sizeof(unsigned int) * 64));
+	__get_user(fpregs[32], &fpu->si_fsr);
+	__get_user(fpregs[33], &fpu->si_gsr);
 }
 
 void do_new_sigreturn32(struct pt_regs *regs)
@@ -142,6 +128,7 @@
 	unsigned int psr;
 	unsigned pc, npc, fpu_save, mask;
 	
+	regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
 	sf = (struct new_signal_frame32 *) regs->u_regs [UREG_FP];
 
 	/* 1. Make sure we are not getting garbage from the user */
@@ -178,12 +165,12 @@
 	__get_user(regs->u_regs[UREG_I6], &sf->info.si_regs.u_regs[UREG_I6]);
 	__get_user(regs->u_regs[UREG_I7], &sf->info.si_regs.u_regs[UREG_I7]);
 
-	/* User can only change condition codes and FPU enabling in %tstate. */
-	regs->tstate &= ~(TSTATE_ICC | TSTATE_PEF);
+	/* User can only change condition codes in %tstate. */
+	regs->tstate &= ~(TSTATE_ICC);
 	regs->tstate |= psr_to_tstate_icc(psr);
 
 	if (psr & PSR_EF)
-		regs->tstate |= TSTATE_PEF;
+		regs->fprs = FPRS_FEF;
 
 	__get_user(fpu_save, &sf->fpu_save);
 	if (fpu_save)
@@ -206,7 +193,8 @@
 	if (current->tss.new_signal)
 		return do_new_sigreturn32(regs);
 
-	scptr = (struct sigcontext32 *) regs->u_regs[UREG_I0];
+	scptr = (struct sigcontext32 *)
+		(regs->u_regs[UREG_I0] & 0x00000000ffffffffUL);
 	/* Check sanity of the user arg. */
 	if(verify_area(VERIFY_READ, scptr, sizeof(struct sigcontext32)) ||
 	   (((unsigned long) scptr) & 3))
@@ -260,6 +248,7 @@
 	int i;
 
 	synchronize_user_stack();
+	regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
 	sframep = (struct signal_sframe32 *) regs->u_regs[UREG_FP];
 	sframep = (struct signal_sframe32 *) (((unsigned long) sframep)-SF_ALIGNEDSZ);
 	if (invalid_frame_pointer (sframep, sizeof(*sframep))){
@@ -285,6 +274,8 @@
 	__put_user(pc, &sc->sigc_pc);
 	__put_user(npc, &sc->sigc_npc);
 	psr = tstate_to_psr (regs->tstate);
+	if(current->flags & PF_USEDFPU)
+		psr |= PSR_EF;
 	__put_user(psr, &sc->sigc_psr);
 	__put_user(regs->u_regs[UREG_G1], &sc->sigc_g1);
 	__put_user(regs->u_regs[UREG_I0], &sc->sigc_o0);
@@ -329,35 +320,17 @@
 }
 
 
-static inline void
-save_fpu_state32(struct pt_regs *regs, __siginfo_fpu32_t *fpu)
+static inline void save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu)
 {
-#ifdef __SMP__
-	if (current->flags & PF_USEDFPU) {
-		fprs_write(FPRS_FEF);
-		fpsave32((unsigned long *)&current->tss.float_regs[0],
-			 &current->tss.fsr);
-		regs->tstate &= ~(TSTATE_PEF);
-		current->flags &= ~(PF_USEDFPU);
-	}
-#else
-	if (current == last_task_used_math) {
-		fprs_write(FPRS_FEF);
-		fpsave32((unsigned long *)&current->tss.float_regs[0],
-			 &current->tss.fsr);
-		last_task_used_math = 0;
-		regs->tstate &= ~(TSTATE_PEF);
-	}
-#endif
-	copy_to_user(&fpu->si_float_regs[0], &current->tss.float_regs[0],
-		     (sizeof(unsigned int) * 32));
-	__put_user(current->tss.fsr, &fpu->si_fsr);
-	current->used_math = 0;
+	unsigned long *fpregs = (unsigned long *)(regs+1);
+	copy_to_user(&fpu->si_float_regs[0], fpregs, (sizeof(unsigned int) * 64));
+	__put_user(fpregs[32], &fpu->si_fsr);
+	__put_user(fpregs[33], &fpu->si_gsr);
+	regs->fprs = 0;
 }
 
-static inline void
-new_setup_frame32(struct sigaction *sa, struct pt_regs *regs,
-		  int signo, unsigned long oldmask)
+static inline void new_setup_frame32(struct sigaction *sa, struct pt_regs *regs,
+				     int signo, unsigned long oldmask)
 {
 	struct new_signal_frame32 *sf;
 	int sigframe_size;
@@ -367,19 +340,26 @@
 	/* 1. Make sure everything is clean */
 	synchronize_user_stack();
 	sigframe_size = NF_ALIGNEDSZ;
-	if (!current->used_math)
-		sigframe_size -= sizeof(__siginfo_fpu32_t);
+	if (!(current->flags & PF_USEDFPU))
+		sigframe_size -= sizeof(__siginfo_fpu_t);
 
+	regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
 	sf = (struct new_signal_frame32 *)(regs->u_regs[UREG_FP] - sigframe_size);
 	
 	if (invalid_frame_pointer (sf, sigframe_size)) {
+#ifdef DEBUG_SIGNALS
+		printk("new_setup_frame32(%s:%d): invalid_frame_pointer(%p, %d)\n",
+		       current->comm, current->pid, sf, sigframe_size);
+#endif
 		lock_kernel ();
 		do_exit(SIGILL);
 	}
 
 	if (current->tss.w_saved != 0) {
+#ifdef DEBUG_SIGNALS
 		printk ("%s[%d]: Invalid user stack frame for "
 			"signal delivery.\n", current->comm, current->pid);
+#endif
 		lock_kernel ();
 		do_exit (SIGILL);
 	}
@@ -389,11 +369,13 @@
 	__put_user(regs->tnpc, &sf->info.si_regs.npc);
 	__put_user(regs->y, &sf->info.si_regs.y);
 	psr = tstate_to_psr (regs->tstate);
+	if(current->flags & PF_USEDFPU)
+		psr |= PSR_EF;
 	__put_user(psr, &sf->info.si_regs.psr);
 	for (i = 0; i < 16; i++)
 		__put_user(regs->u_regs[i], &sf->info.si_regs.u_regs[i]);
 
-	if (current->used_math) {
+	if (psr & PSR_EF) {
 		save_fpu_state32(regs, &sf->fpu_state);
 		__put_user((u64)&sf->fpu_state, &sf->fpu_save);
 	} else {
@@ -425,15 +407,22 @@
 	regs->tnpc = (regs->tpc + 4);
 
 	/* Flush instruction space. */
-	__asm__ __volatile__("
-	membar		#StoreStore
-	stxa		%%g0, [%0] %2
-	stxa		%%g0, [%1] %2
-	flush		%%g4
-	" : /* no outputs */
-	  : "r" (((unsigned long)&(sf->insns[0])) & ~(PAGE_MASK)),
-	    "r" ((((unsigned long)&(sf->insns[0])) & ~(PAGE_MASK)) + PAGE_SIZE),
-	    "i" (ASI_IC_TAG));
+	{
+		unsigned long address = ((unsigned long)&(sf->insns[0]));
+		pgd_t *pgdp = pgd_offset(current->mm, address);
+		pmd_t *pmdp = pmd_offset(pgdp, address);
+		pte_t *ptep = pte_offset(pmdp, address);
+
+		if(pte_present(*ptep)) {
+			unsigned long page = pte_page(*ptep);
+
+			__asm__ __volatile__("
+			membar	#StoreStore
+			flush	%0 + %1"
+			: : "r" (page), "r" (address & (PAGE_SIZE - 1))
+			: "memory");
+		}
+	}
 }
 
 /* Setup a Solaris stack frame */
@@ -454,6 +443,7 @@
 	int i;
 
 	synchronize_user_stack();
+	regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
 	sfp = (svr4_signal_frame_t *) regs->u_regs[UREG_FP] - REGWIN_SZ;
 	sfp = (svr4_signal_frame_t *) (((unsigned long) sfp)-SVR4_SF_ALIGNED);
 
@@ -485,6 +475,8 @@
 	__put_user(regs->tpc, &((*gr) [SVR4_PC]));
 	__put_user(regs->tnpc, &((*gr) [SVR4_NPC]));
 	psr = tstate_to_psr (regs->tstate);
+	if(current->flags & PF_USEDFPU)
+		psr |= PSR_EF;
 	__put_user(psr, &((*gr) [SVR4_PSR]));
 	__put_user(regs->y, &((*gr) [SVR4_Y]));
 	
@@ -546,7 +538,8 @@
 #endif
 	/* Arguments passed to signal handler */
 	if (regs->u_regs [14]){
-		struct reg_window32 *rw = (struct reg_window32 *) regs->u_regs [14];
+		struct reg_window32 *rw = (struct reg_window32 *)
+			(regs->u_regs [14] & 0x00000000ffffffffUL);
 
 		__put_user(signr, &rw->ins [0]);
 		__put_user((u64)si, &rw->ins [1]);
@@ -583,7 +576,9 @@
 	/* Store registers */
 	__put_user(regs->tpc, &uc->mcontext.greg [SVR4_PC]);
 	__put_user(regs->tnpc, &uc->mcontext.greg [SVR4_NPC]);
-	__put_user(tstate_to_psr(regs->tstate), &uc->mcontext.greg [SVR4_PSR]);
+	__put_user((tstate_to_psr(regs->tstate) |
+		    ((current->flags & PF_USEDFPU) ? PSR_EF : 0)),
+		   &uc->mcontext.greg [SVR4_PSR]);
         __put_user(regs->y, &uc->mcontext.greg [SVR4_Y]);
 	
 	/* Copy g [1..7] and o [0..7] registers */
@@ -650,12 +645,14 @@
 	__get_user(psr, &((*gr) [SVR4_PSR]));
 	regs->tstate &= ~(TSTATE_ICC);
 	regs->tstate |= psr_to_tstate_icc(psr);
+	if(psr & PSR_EF)
+		regs->fprs = FPRS_FEF;
 
 	/* Restore g[1..7] and o[0..7] registers */
 	for (i = 0; i < 7; i++)
-		__put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);
+		__get_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);
 	for (i = 0; i < 8; i++)
-		__put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);
+		__get_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);
 
 	return -EINTR;
 }
@@ -805,9 +802,10 @@
 	int cur_status;
 };
 
-asmlinkage int
-sys32_sigstack(struct sigstack32 *ssptr, struct sigstack32 *ossptr)
+asmlinkage int sys32_sigstack(u32 u_ssptr, u32 u_ossptr)
 {
+	struct sigstack32 *ssptr = (struct sigstack32 *)((unsigned long)(u_ssptr));
+	struct sigstack32 *ossptr = (struct sigstack32 *)((unsigned long)(u_ossptr));
 	int ret = -EFAULT;
 
 	lock_kernel();

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov