diff options
Diffstat (limited to 'arch/powerpc/kernel/signal_32.c')
| -rw-r--r-- | arch/powerpc/kernel/signal_32.c | 911 | 
1 files changed, 588 insertions, 323 deletions
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index b96a3a010c2..1bc5a1755ed 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -25,6 +25,7 @@  #include <linux/errno.h>  #include <linux/elf.h>  #include <linux/ptrace.h> +#include <linux/ratelimit.h>  #ifdef CONFIG_PPC64  #include <linux/syscalls.h>  #include <linux/compat.h> @@ -34,7 +35,6 @@  #include <linux/stddef.h>  #include <linux/tty.h>  #include <linux/binfmts.h> -#include <linux/freezer.h>  #endif  #include <asm/uaccess.h> @@ -42,6 +42,8 @@  #include <asm/syscalls.h>  #include <asm/sigcontext.h>  #include <asm/vdso.h> +#include <asm/switch_to.h> +#include <asm/tm.h>  #ifdef CONFIG_PPC64  #include "ppc32.h"  #include <asm/unistd.h> @@ -52,13 +54,9 @@  #include "signal.h" -#undef DEBUG_SIG  #ifdef CONFIG_PPC64 -#define sys_sigsuspend	compat_sys_sigsuspend -#define sys_rt_sigsuspend	compat_sys_rt_sigsuspend  #define sys_rt_sigreturn	compat_sys_rt_sigreturn -#define sys_sigaction	compat_sys_sigaction  #define sys_swapcontext	compat_sys_swapcontext  #define sys_sigreturn	compat_sys_sigreturn @@ -67,6 +65,8 @@  #define mcontext	mcontext32  #define ucontext	ucontext32 +#define __save_altstack __compat_save_altstack +  /*   * Userspace code may pass a ucontext which doesn't include VSX added   * at the end.  We need to check for this case. @@ -96,7 +96,7 @@ static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set)  	compat_sigset_t	cset;  	switch (_NSIG_WORDS) { -	case 4: cset.sig[5] = set->sig[3] & 0xffffffffull; +	case 4: cset.sig[6] = set->sig[3] & 0xffffffffull;  		cset.sig[7] = set->sig[3] >> 32;  	case 3: cset.sig[4] = set->sig[2] & 0xffffffffull;  		cset.sig[5] = set->sig[2] >> 32; @@ -129,23 +129,6 @@ static inline int get_sigset_t(sigset_t *set,  	return 0;  } -static inline int get_old_sigaction(struct k_sigaction *new_ka, -		struct old_sigaction __user *act) -{ -	compat_old_sigset_t mask; -	compat_uptr_t handler, restorer; - -	if (get_user(handler, &act->sa_handler) || -	    __get_user(restorer, &act->sa_restorer) || -	    __get_user(new_ka->sa.sa_flags, &act->sa_flags) || -	    __get_user(mask, &act->sa_mask)) -		return -EFAULT; -	new_ka->sa.sa_handler = compat_ptr(handler); -	new_ka->sa.sa_restorer = compat_ptr(restorer); -	siginitset(&new_ka->sa.sa_mask, mask); -	return 0; -} -  #define to_user_ptr(p)		ptr_to_compat(p)  #define from_user_ptr(p)	compat_ptr(p) @@ -195,21 +178,6 @@ static inline int get_sigset_t(sigset_t *set, const sigset_t __user *uset)  	return copy_from_user(set, uset, sizeof(*uset));  } -static inline int get_old_sigaction(struct k_sigaction *new_ka, -		struct old_sigaction __user *act) -{ -	old_sigset_t mask; - -	if (!access_ok(VERIFY_READ, act, sizeof(*act)) || -			__get_user(new_ka->sa.sa_handler, &act->sa_handler) || -			__get_user(new_ka->sa.sa_restorer, &act->sa_restorer)) -		return -EFAULT; -	__get_user(new_ka->sa.sa_flags, &act->sa_flags); -	__get_user(mask, &act->sa_mask); -	siginitset(&new_ka->sa.sa_mask, mask); -	return 0; -} -  #define to_user_ptr(p)		((unsigned long)(p))  #define from_user_ptr(p)	((void __user *)(p)) @@ -233,58 +201,8 @@ static inline int restore_general_regs(struct pt_regs *regs,  		return -EFAULT;  	return 0;  } - -#endif /* CONFIG_PPC64 */ - -/* - * Atomically swap in the new signal mask, and wait for a signal. - */ -long sys_sigsuspend(old_sigset_t mask) -{ -	mask &= _BLOCKABLE; -	spin_lock_irq(¤t->sighand->siglock); -	current->saved_sigmask = current->blocked; -	siginitset(¤t->blocked, mask); -	recalc_sigpending(); -	spin_unlock_irq(¤t->sighand->siglock); - - 	current->state = TASK_INTERRUPTIBLE; - 	schedule(); -	set_restore_sigmask(); - 	return -ERESTARTNOHAND; -} - -long sys_sigaction(int sig, struct old_sigaction __user *act, -		struct old_sigaction __user *oact) -{ -	struct k_sigaction new_ka, old_ka; -	int ret; - -#ifdef CONFIG_PPC64 -	if (sig < 0) -		sig = -sig;  #endif -	if (act) { -		if (get_old_sigaction(&new_ka, act)) -			return -EFAULT; -	} - -	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); -	if (!ret && oact) { -		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || -		    __put_user(to_user_ptr(old_ka.sa.sa_handler), -			    &oact->sa_handler) || -		    __put_user(to_user_ptr(old_ka.sa.sa_restorer), -			    &oact->sa_restorer) || -		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || -		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) -			return -EFAULT; -	} - -	return ret; -} -  /*   * When we have signals to deliver, we set up on the   * user stack, going down from the original stack pointer: @@ -300,6 +218,10 @@ long sys_sigaction(int sig, struct old_sigaction __user *act,  struct sigframe {  	struct sigcontext sctx;		/* the sigcontext */  	struct mcontext	mctx;		/* all the register values */ +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +	struct sigcontext sctx_transact; +	struct mcontext	mctx_transact; +#endif  	/*  	 * Programs using the rs6000/xcoff abi can save up to 19 gp  	 * regs and 18 fp regs below sp before decrementing it. @@ -328,6 +250,9 @@ struct rt_sigframe {  	struct siginfo info;  #endif  	struct ucontext	uc; +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +	struct ucontext	uc_transact; +#endif  	/*  	 * Programs using the rs6000/xcoff abi can save up to 19 gp  	 * regs and 18 fp regs below sp before decrementing it. @@ -339,27 +264,27 @@ struct rt_sigframe {  unsigned long copy_fpr_to_user(void __user *to,  			       struct task_struct *task)  { -	double buf[ELF_NFPREG]; +	u64 buf[ELF_NFPREG];  	int i;  	/* save FPR copy to local buffer then write to the thread_struct */  	for (i = 0; i < (ELF_NFPREG - 1) ; i++)  		buf[i] = task->thread.TS_FPR(i); -	memcpy(&buf[i], &task->thread.fpscr, sizeof(double)); +	buf[i] = task->thread.fp_state.fpscr;  	return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double));  }  unsigned long copy_fpr_from_user(struct task_struct *task,  				 void __user *from)  { -	double buf[ELF_NFPREG]; +	u64 buf[ELF_NFPREG];  	int i;  	if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double)))  		return 1;  	for (i = 0; i < (ELF_NFPREG - 1) ; i++)  		task->thread.TS_FPR(i) = buf[i]; -	memcpy(&task->thread.fpscr, &buf[i], sizeof(double)); +	task->thread.fp_state.fpscr = buf[i];  	return 0;  } @@ -367,41 +292,112 @@ unsigned long copy_fpr_from_user(struct task_struct *task,  unsigned long copy_vsx_to_user(void __user *to,  			       struct task_struct *task)  { -	double buf[ELF_NVSRHALFREG]; +	u64 buf[ELF_NVSRHALFREG];  	int i;  	/* save FPR copy to local buffer then write to the thread_struct */  	for (i = 0; i < ELF_NVSRHALFREG; i++) -		buf[i] = task->thread.fpr[i][TS_VSRLOWOFFSET]; +		buf[i] = task->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];  	return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double));  }  unsigned long copy_vsx_from_user(struct task_struct *task,  				 void __user *from)  { -	double buf[ELF_NVSRHALFREG]; +	u64 buf[ELF_NVSRHALFREG]; +	int i; + +	if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double))) +		return 1; +	for (i = 0; i < ELF_NVSRHALFREG ; i++) +		task->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i]; +	return 0; +} + +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +unsigned long copy_transact_fpr_to_user(void __user *to, +				  struct task_struct *task) +{ +	u64 buf[ELF_NFPREG]; +	int i; + +	/* save FPR copy to local buffer then write to the thread_struct */ +	for (i = 0; i < (ELF_NFPREG - 1) ; i++) +		buf[i] = task->thread.TS_TRANS_FPR(i); +	buf[i] = task->thread.transact_fp.fpscr; +	return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double)); +} + +unsigned long copy_transact_fpr_from_user(struct task_struct *task, +					  void __user *from) +{ +	u64 buf[ELF_NFPREG]; +	int i; + +	if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double))) +		return 1; +	for (i = 0; i < (ELF_NFPREG - 1) ; i++) +		task->thread.TS_TRANS_FPR(i) = buf[i]; +	task->thread.transact_fp.fpscr = buf[i]; + +	return 0; +} + +unsigned long copy_transact_vsx_to_user(void __user *to, +				  struct task_struct *task) +{ +	u64 buf[ELF_NVSRHALFREG]; +	int i; + +	/* save FPR copy to local buffer then write to the thread_struct */ +	for (i = 0; i < ELF_NVSRHALFREG; i++) +		buf[i] = task->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET]; +	return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double)); +} + +unsigned long copy_transact_vsx_from_user(struct task_struct *task, +					  void __user *from) +{ +	u64 buf[ELF_NVSRHALFREG];  	int i;  	if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double)))  		return 1;  	for (i = 0; i < ELF_NVSRHALFREG ; i++) -		task->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i]; +		task->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET] = buf[i];  	return 0;  } +#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */  #else  inline unsigned long copy_fpr_to_user(void __user *to,  				      struct task_struct *task)  { -	return __copy_to_user(to, task->thread.fpr, +	return __copy_to_user(to, task->thread.fp_state.fpr,  			      ELF_NFPREG * sizeof(double));  }  inline unsigned long copy_fpr_from_user(struct task_struct *task,  					void __user *from)  { -	return __copy_from_user(task->thread.fpr, from, +	return __copy_from_user(task->thread.fp_state.fpr, from,  			      ELF_NFPREG * sizeof(double));  } + +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +inline unsigned long copy_transact_fpr_to_user(void __user *to, +					 struct task_struct *task) +{ +	return __copy_to_user(to, task->thread.transact_fp.fpr, +			      ELF_NFPREG * sizeof(double)); +} + +inline unsigned long copy_transact_fpr_from_user(struct task_struct *task, +						 void __user *from) +{ +	return __copy_from_user(task->thread.transact_fp.fpr, from, +				ELF_NFPREG * sizeof(double)); +} +#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */  #endif  /* @@ -410,7 +406,8 @@ inline unsigned long copy_fpr_from_user(struct task_struct *task,   * altivec/spe instructions at some point.   */  static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, -		int sigret, int ctx_has_vsx_region) +			  struct mcontext __user *tm_frame, int sigret, +			  int ctx_has_vsx_region)  {  	unsigned long msr = regs->msr; @@ -425,7 +422,7 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,  	/* save altivec registers */  	if (current->thread.used_vr) {  		flush_altivec_to_thread(current); -		if (__copy_to_user(&frame->mc_vregs, current->thread.vr, +		if (__copy_to_user(&frame->mc_vregs, ¤t->thread.vr_state,  				   ELF_NVRREG * sizeof(vector128)))  			return 1;  		/* set MSR_VEC in the saved MSR value to indicate that @@ -438,12 +435,21 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,  	 * use altivec. Since VSCR only contains 32 bits saved in the least  	 * significant bits of a vector, we "cheat" and stuff VRSAVE in the  	 * most significant bits of that same vector. --BenH +	 * Note that the current VRSAVE value is in the SPR at this point.  	 */ +	if (cpu_has_feature(CPU_FTR_ALTIVEC)) +		current->thread.vrsave = mfspr(SPRN_VRSAVE);  	if (__put_user(current->thread.vrsave, (u32 __user *)&frame->mc_vregs[32]))  		return 1;  #endif /* CONFIG_ALTIVEC */  	if (copy_fpr_to_user(&frame->mc_fregs, current))  		return 1; + +	/* +	 * Clear the MSR VSX bit to indicate there is no valid state attached +	 * to this context, except in the specific case below where we set it. +	 */ +	msr &= ~MSR_VSX;  #ifdef CONFIG_VSX  	/*  	 * Copy VSR 0-31 upper half from thread_struct to local @@ -478,6 +484,164 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,  	if (__put_user(msr, &frame->mc_gregs[PT_MSR]))  		return 1; +	/* We need to write 0 the MSR top 32 bits in the tm frame so that we +	 * can check it on the restore to see if TM is active +	 */ +	if (tm_frame && __put_user(0, &tm_frame->mc_gregs[PT_MSR])) +		return 1; + +	if (sigret) { +		/* Set up the sigreturn trampoline: li r0,sigret; sc */ +		if (__put_user(0x38000000UL + sigret, &frame->tramp[0]) +		    || __put_user(0x44000002UL, &frame->tramp[1])) +			return 1; +		flush_icache_range((unsigned long) &frame->tramp[0], +				   (unsigned long) &frame->tramp[2]); +	} + +	return 0; +} + +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +/* + * Save the current user registers on the user stack. + * We only save the altivec/spe registers if the process has used + * altivec/spe instructions at some point. + * We also save the transactional registers to a second ucontext in the + * frame. + * + * See save_user_regs() and signal_64.c:setup_tm_sigcontexts(). + */ +static int save_tm_user_regs(struct pt_regs *regs, +			     struct mcontext __user *frame, +			     struct mcontext __user *tm_frame, int sigret) +{ +	unsigned long msr = regs->msr; + +	/* Remove TM bits from thread's MSR.  The MSR in the sigcontext +	 * just indicates to userland that we were doing a transaction, but we +	 * don't want to return in transactional state.  This also ensures +	 * that flush_fp_to_thread won't set TIF_RESTORE_TM again. +	 */ +	regs->msr &= ~MSR_TS_MASK; + +	/* Make sure floating point registers are stored in regs */ +	flush_fp_to_thread(current); + +	/* Save both sets of general registers */ +	if (save_general_regs(¤t->thread.ckpt_regs, frame) +	    || save_general_regs(regs, tm_frame)) +		return 1; + +	/* Stash the top half of the 64bit MSR into the 32bit MSR word +	 * of the transactional mcontext.  This way we have a backward-compatible +	 * MSR in the 'normal' (checkpointed) mcontext and additionally one can +	 * also look at what type of transaction (T or S) was active at the +	 * time of the signal. +	 */ +	if (__put_user((msr >> 32), &tm_frame->mc_gregs[PT_MSR])) +		return 1; + +#ifdef CONFIG_ALTIVEC +	/* save altivec registers */ +	if (current->thread.used_vr) { +		flush_altivec_to_thread(current); +		if (__copy_to_user(&frame->mc_vregs, ¤t->thread.vr_state, +				   ELF_NVRREG * sizeof(vector128))) +			return 1; +		if (msr & MSR_VEC) { +			if (__copy_to_user(&tm_frame->mc_vregs, +					   ¤t->thread.transact_vr, +					   ELF_NVRREG * sizeof(vector128))) +				return 1; +		} else { +			if (__copy_to_user(&tm_frame->mc_vregs, +					   ¤t->thread.vr_state, +					   ELF_NVRREG * sizeof(vector128))) +				return 1; +		} + +		/* set MSR_VEC in the saved MSR value to indicate that +		 * frame->mc_vregs contains valid data +		 */ +		msr |= MSR_VEC; +	} + +	/* We always copy to/from vrsave, it's 0 if we don't have or don't +	 * use altivec. Since VSCR only contains 32 bits saved in the least +	 * significant bits of a vector, we "cheat" and stuff VRSAVE in the +	 * most significant bits of that same vector. --BenH +	 */ +	if (cpu_has_feature(CPU_FTR_ALTIVEC)) +		current->thread.vrsave = mfspr(SPRN_VRSAVE); +	if (__put_user(current->thread.vrsave, +		       (u32 __user *)&frame->mc_vregs[32])) +		return 1; +	if (msr & MSR_VEC) { +		if (__put_user(current->thread.transact_vrsave, +			       (u32 __user *)&tm_frame->mc_vregs[32])) +			return 1; +	} else { +		if (__put_user(current->thread.vrsave, +			       (u32 __user *)&tm_frame->mc_vregs[32])) +			return 1; +	} +#endif /* CONFIG_ALTIVEC */ + +	if (copy_fpr_to_user(&frame->mc_fregs, current)) +		return 1; +	if (msr & MSR_FP) { +		if (copy_transact_fpr_to_user(&tm_frame->mc_fregs, current)) +			return 1; +	} else { +		if (copy_fpr_to_user(&tm_frame->mc_fregs, current)) +			return 1; +	} + +#ifdef CONFIG_VSX +	/* +	 * Copy VSR 0-31 upper half from thread_struct to local +	 * buffer, then write that to userspace.  Also set MSR_VSX in +	 * the saved MSR value to indicate that frame->mc_vregs +	 * contains valid data +	 */ +	if (current->thread.used_vsr) { +		__giveup_vsx(current); +		if (copy_vsx_to_user(&frame->mc_vsregs, current)) +			return 1; +		if (msr & MSR_VSX) { +			if (copy_transact_vsx_to_user(&tm_frame->mc_vsregs, +						      current)) +				return 1; +		} else { +			if (copy_vsx_to_user(&tm_frame->mc_vsregs, current)) +				return 1; +		} + +		msr |= MSR_VSX; +	} +#endif /* CONFIG_VSX */ +#ifdef CONFIG_SPE +	/* SPE regs are not checkpointed with TM, so this section is +	 * simply the same as in save_user_regs(). +	 */ +	if (current->thread.used_spe) { +		flush_spe_to_thread(current); +		if (__copy_to_user(&frame->mc_vregs, current->thread.evr, +				   ELF_NEVRREG * sizeof(u32))) +			return 1; +		/* set MSR_SPE in the saved MSR value to indicate that +		 * frame->mc_vregs contains valid data */ +		msr |= MSR_SPE; +	} + +	/* We always copy to/from spefscr */ +	if (__put_user(current->thread.spefscr, (u32 __user *)&frame->mc_vregs + ELF_NEVRREG)) +		return 1; +#endif /* CONFIG_SPE */ + +	if (__put_user(msr, &frame->mc_gregs[PT_MSR])) +		return 1;  	if (sigret) {  		/* Set up the sigreturn trampoline: li r0,sigret; sc */  		if (__put_user(0x38000000UL + sigret, &frame->tramp[0]) @@ -489,6 +653,7 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,  	return 0;  } +#endif  /*   * Restore the current user register values from the user stack, @@ -539,15 +704,18 @@ static long restore_user_regs(struct pt_regs *regs,  	regs->msr &= ~MSR_VEC;  	if (msr & MSR_VEC) {  		/* restore altivec registers from the stack */ -		if (__copy_from_user(current->thread.vr, &sr->mc_vregs, +		if (__copy_from_user(¤t->thread.vr_state, &sr->mc_vregs,  				     sizeof(sr->mc_vregs)))  			return 1;  	} else if (current->thread.used_vr) -		memset(current->thread.vr, 0, ELF_NVRREG * sizeof(vector128)); +		memset(¤t->thread.vr_state, 0, +		       ELF_NVRREG * sizeof(vector128));  	/* Always get VRSAVE back */  	if (__get_user(current->thread.vrsave, (u32 __user *)&sr->mc_vregs[32]))  		return 1; +	if (cpu_has_feature(CPU_FTR_ALTIVEC)) +		mtspr(SPRN_VRSAVE, current->thread.vrsave);  #endif /* CONFIG_ALTIVEC */  	if (copy_fpr_from_user(current, &sr->mc_fregs))  		return 1; @@ -567,7 +735,7 @@ static long restore_user_regs(struct pt_regs *regs,  			return 1;  	} else if (current->thread.used_vsr)  		for (i = 0; i < 32 ; i++) -			current->thread.fpr[i][TS_VSRLOWOFFSET] = 0; +			current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0;  #endif /* CONFIG_VSX */  	/*  	 * force the process to reload the FP registers from @@ -595,91 +763,151 @@ static long restore_user_regs(struct pt_regs *regs,  	return 0;  } -#ifdef CONFIG_PPC64 -long compat_sys_rt_sigaction(int sig, const struct sigaction32 __user *act, -		struct sigaction32 __user *oact, size_t sigsetsize) +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +/* + * Restore the current user register values from the user stack, except for + * MSR, and recheckpoint the original checkpointed register state for processes + * in transactions. + */ +static long restore_tm_user_regs(struct pt_regs *regs, +				 struct mcontext __user *sr, +				 struct mcontext __user *tm_sr)  { -	struct k_sigaction new_ka, old_ka; -	int ret; +	long err; +	unsigned long msr, msr_hi; +#ifdef CONFIG_VSX +	int i; +#endif -	/* XXX: Don't preclude handling different sized sigset_t's.  */ -	if (sigsetsize != sizeof(compat_sigset_t)) -		return -EINVAL; +	/* +	 * restore general registers but not including MSR or SOFTE. Also +	 * take care of keeping r2 (TLS) intact if not a signal. +	 * See comment in signal_64.c:restore_tm_sigcontexts(); +	 * TFHAR is restored from the checkpointed NIP; TEXASR and TFIAR +	 * were set by the signal delivery. +	 */ +	err = restore_general_regs(regs, tm_sr); +	err |= restore_general_regs(¤t->thread.ckpt_regs, sr); -	if (act) { -		compat_uptr_t handler; +	err |= __get_user(current->thread.tm_tfhar, &sr->mc_gregs[PT_NIP]); -		ret = get_user(handler, &act->sa_handler); -		new_ka.sa.sa_handler = compat_ptr(handler); -		ret |= get_sigset_t(&new_ka.sa.sa_mask, &act->sa_mask); -		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); -		if (ret) -			return -EFAULT; -	} +	err |= __get_user(msr, &sr->mc_gregs[PT_MSR]); +	if (err) +		return 1; -	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); -	if (!ret && oact) { -		ret = put_user(to_user_ptr(old_ka.sa.sa_handler), &oact->sa_handler); -		ret |= put_sigset_t(&oact->sa_mask, &old_ka.sa.sa_mask); -		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); -	} -	return ret; -} +	/* Restore the previous little-endian mode */ +	regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE); -/* - * Note: it is necessary to treat how as an unsigned int, with the - * corresponding cast to a signed int to insure that the proper - * conversion (sign extension) between the register representation - * of a signed int (msr in 32-bit mode) and the register representation - * of a signed int (msr in 64-bit mode) is performed. - */ -long compat_sys_rt_sigprocmask(u32 how, compat_sigset_t __user *set, -		compat_sigset_t __user *oset, size_t sigsetsize) -{ -	sigset_t s; -	sigset_t __user *up; -	int ret; -	mm_segment_t old_fs = get_fs(); +	/* +	 * Do this before updating the thread state in +	 * current->thread.fpr/vr/evr.  That way, if we get preempted +	 * and another task grabs the FPU/Altivec/SPE, it won't be +	 * tempted to save the current CPU state into the thread_struct +	 * and corrupt what we are writing there. +	 */ +	discard_lazy_cpu_state(); -	if (set) { -		if (get_sigset_t(&s, set)) -			return -EFAULT; +#ifdef CONFIG_ALTIVEC +	regs->msr &= ~MSR_VEC; +	if (msr & MSR_VEC) { +		/* restore altivec registers from the stack */ +		if (__copy_from_user(¤t->thread.vr_state, &sr->mc_vregs, +				     sizeof(sr->mc_vregs)) || +		    __copy_from_user(¤t->thread.transact_vr, +				     &tm_sr->mc_vregs, +				     sizeof(sr->mc_vregs))) +			return 1; +	} else if (current->thread.used_vr) { +		memset(¤t->thread.vr_state, 0, +		       ELF_NVRREG * sizeof(vector128)); +		memset(¤t->thread.transact_vr, 0, +		       ELF_NVRREG * sizeof(vector128));  	} -	set_fs(KERNEL_DS); -	/* This is valid because of the set_fs() */ -	up = (sigset_t __user *) &s; -	ret = sys_rt_sigprocmask((int)how, set ? up : NULL, oset ? up : NULL, -				 sigsetsize); -	set_fs(old_fs); -	if (ret) -		return ret; -	if (oset) { -		if (put_sigset_t(oset, &s)) -			return -EFAULT; -	} -	return 0; -} +	/* Always get VRSAVE back */ +	if (__get_user(current->thread.vrsave, +		       (u32 __user *)&sr->mc_vregs[32]) || +	    __get_user(current->thread.transact_vrsave, +		       (u32 __user *)&tm_sr->mc_vregs[32])) +		return 1; +	if (cpu_has_feature(CPU_FTR_ALTIVEC)) +		mtspr(SPRN_VRSAVE, current->thread.vrsave); +#endif /* CONFIG_ALTIVEC */ -long compat_sys_rt_sigpending(compat_sigset_t __user *set, compat_size_t sigsetsize) -{ -	sigset_t s; -	int ret; -	mm_segment_t old_fs = get_fs(); - -	set_fs(KERNEL_DS); -	/* The __user pointer cast is valid because of the set_fs() */ -	ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize); -	set_fs(old_fs); -	if (!ret) { -		if (put_sigset_t(set, &s)) -			return -EFAULT; +	regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); + +	if (copy_fpr_from_user(current, &sr->mc_fregs) || +	    copy_transact_fpr_from_user(current, &tm_sr->mc_fregs)) +		return 1; + +#ifdef CONFIG_VSX +	regs->msr &= ~MSR_VSX; +	if (msr & MSR_VSX) { +		/* +		 * Restore altivec registers from the stack to a local +		 * buffer, then write this out to the thread_struct +		 */ +		if (copy_vsx_from_user(current, &sr->mc_vsregs) || +		    copy_transact_vsx_from_user(current, &tm_sr->mc_vsregs)) +			return 1; +	} else if (current->thread.used_vsr) +		for (i = 0; i < 32 ; i++) { +			current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0; +			current->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET] = 0; +		} +#endif /* CONFIG_VSX */ + +#ifdef CONFIG_SPE +	/* SPE regs are not checkpointed with TM, so this section is +	 * simply the same as in restore_user_regs(). +	 */ +	regs->msr &= ~MSR_SPE; +	if (msr & MSR_SPE) { +		if (__copy_from_user(current->thread.evr, &sr->mc_vregs, +				     ELF_NEVRREG * sizeof(u32))) +			return 1; +	} else if (current->thread.used_spe) +		memset(current->thread.evr, 0, ELF_NEVRREG * sizeof(u32)); + +	/* Always get SPEFSCR back */ +	if (__get_user(current->thread.spefscr, (u32 __user *)&sr->mc_vregs +		       + ELF_NEVRREG)) +		return 1; +#endif /* CONFIG_SPE */ + +	/* Now, recheckpoint.  This loads up all of the checkpointed (older) +	 * registers, including FP and V[S]Rs.  After recheckpointing, the +	 * transactional versions should be loaded. +	 */ +	tm_enable(); +	/* Make sure the transaction is marked as failed */ +	current->thread.tm_texasr |= TEXASR_FS; +	/* This loads the checkpointed FP/VEC state, if used */ +	tm_recheckpoint(¤t->thread, msr); +	/* Get the top half of the MSR */ +	if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR])) +		return 1; +	/* Pull in MSR TM from user context */ +	regs->msr = (regs->msr & ~MSR_TS_MASK) | ((msr_hi<<32) & MSR_TS_MASK); + +	/* This loads the speculative FP/VEC state, if used */ +	if (msr & MSR_FP) { +		do_load_up_transact_fpu(¤t->thread); +		regs->msr |= (MSR_FP | current->thread.fpexc_mode);  	} -	return ret; -} +#ifdef CONFIG_ALTIVEC +	if (msr & MSR_VEC) { +		do_load_up_transact_altivec(¤t->thread); +		regs->msr |= MSR_VEC; +	} +#endif +	return 0; +} +#endif -int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s) +#ifdef CONFIG_PPC64 +int copy_siginfo_to_user32(struct compat_siginfo __user *d, const siginfo_t *s)  {  	int err; @@ -747,79 +975,6 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)  	return 0;  } - -/* - * Note: it is necessary to treat pid and sig as unsigned ints, with the - * corresponding cast to a signed int to insure that the proper conversion - * (sign extension) between the register representation of a signed int - * (msr in 32-bit mode) and the register representation of a signed int - * (msr in 64-bit mode) is performed. - */ -long compat_sys_rt_sigqueueinfo(u32 pid, u32 sig, compat_siginfo_t __user *uinfo) -{ -	siginfo_t info; -	int ret; -	mm_segment_t old_fs = get_fs(); - -	ret = copy_siginfo_from_user32(&info, uinfo); -	if (unlikely(ret)) -		return ret; - -	set_fs (KERNEL_DS); -	/* The __user pointer cast is valid becasuse of the set_fs() */ -	ret = sys_rt_sigqueueinfo((int)pid, (int)sig, (siginfo_t __user *) &info); -	set_fs (old_fs); -	return ret; -} -/* - *  Start Alternate signal stack support - * - *  System Calls - *       sigaltatck               compat_sys_sigaltstack - */ - -int compat_sys_sigaltstack(u32 __new, u32 __old, int r5, -		      int r6, int r7, int r8, struct pt_regs *regs) -{ -	stack_32_t __user * newstack = compat_ptr(__new); -	stack_32_t __user * oldstack = compat_ptr(__old); -	stack_t uss, uoss; -	int ret; -	mm_segment_t old_fs; -	unsigned long sp; -	compat_uptr_t ss_sp; - -	/* -	 * set sp to the user stack on entry to the system call -	 * the system call router sets R9 to the saved registers -	 */ -	sp = regs->gpr[1]; - -	/* Put new stack info in local 64 bit stack struct */ -	if (newstack) { -		if (get_user(ss_sp, &newstack->ss_sp) || -		    __get_user(uss.ss_flags, &newstack->ss_flags) || -		    __get_user(uss.ss_size, &newstack->ss_size)) -			return -EFAULT; -		uss.ss_sp = compat_ptr(ss_sp); -	} - -	old_fs = get_fs(); -	set_fs(KERNEL_DS); -	/* The __user pointer casts are valid because of the set_fs() */ -	ret = do_sigaltstack( -		newstack ? (stack_t __user *) &uss : NULL, -		oldstack ? (stack_t __user *) &uoss : NULL, -		sp); -	set_fs(old_fs); -	/* Copy the stack information to the user output buffer */ -	if (!ret && oldstack  && -		(put_user(ptr_to_compat(uoss.ss_sp), &oldstack->ss_sp) || -		 __put_user(uoss.ss_flags, &oldstack->ss_flags) || -		 __put_user(uoss.ss_size, &oldstack->ss_size))) -		return -EFAULT; -	return ret; -}  #endif /* CONFIG_PPC64 */  /* @@ -832,12 +987,15 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,  {  	struct rt_sigframe __user *rt_sf;  	struct mcontext __user *frame; +	struct mcontext __user *tm_frame = NULL;  	void __user *addr;  	unsigned long newsp = 0; +	int sigret; +	unsigned long tramp;  	/* Set up Signal Frame */  	/* Put a Real Time Context onto stack */ -	rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf), 1); +	rt_sf = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*rt_sf), 1);  	addr = rt_sf;  	if (unlikely(rt_sf == NULL))  		goto badframe; @@ -845,11 +1003,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,  	/* Put the siginfo & fill in most of the ucontext */  	if (copy_siginfo_to_user(&rt_sf->info, info)  	    || __put_user(0, &rt_sf->uc.uc_flags) -	    || __put_user(0, &rt_sf->uc.uc_link) -	    || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp) -	    || __put_user(sas_ss_flags(regs->gpr[1]), -			  &rt_sf->uc.uc_stack.ss_flags) -	    || __put_user(current->sas_ss_size, &rt_sf->uc.uc_stack.ss_size) +	    || __save_altstack(&rt_sf->uc.uc_stack, regs->gpr[1])  	    || __put_user(to_user_ptr(&rt_sf->uc.uc_mcontext),  		    &rt_sf->uc.uc_regs)  	    || put_sigset_t(&rt_sf->uc.uc_sigmask, oldset)) @@ -859,16 +1013,35 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,  	frame = &rt_sf->uc.uc_mcontext;  	addr = frame;  	if (vdso32_rt_sigtramp && current->mm->context.vdso_base) { -		if (save_user_regs(regs, frame, 0, 1)) -			goto badframe; -		regs->link = current->mm->context.vdso_base + vdso32_rt_sigtramp; +		sigret = 0; +		tramp = current->mm->context.vdso_base + vdso32_rt_sigtramp;  	} else { -		if (save_user_regs(regs, frame, __NR_rt_sigreturn, 1)) +		sigret = __NR_rt_sigreturn; +		tramp = (unsigned long) frame->tramp; +	} + +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +	tm_frame = &rt_sf->uc_transact.uc_mcontext; +	if (MSR_TM_ACTIVE(regs->msr)) { +		if (__put_user((unsigned long)&rt_sf->uc_transact, +			       &rt_sf->uc.uc_link) || +		    __put_user((unsigned long)tm_frame, +			       &rt_sf->uc_transact.uc_regs)) +			goto badframe; +		if (save_tm_user_regs(regs, frame, tm_frame, sigret))  			goto badframe; -		regs->link = (unsigned long) frame->tramp;  	} +	else +#endif +	{ +		if (__put_user(0, &rt_sf->uc.uc_link)) +			goto badframe; +		if (save_user_regs(regs, frame, tm_frame, sigret, 1)) +			goto badframe; +	} +	regs->link = tramp; -	current->thread.fpscr.val = 0;	/* turn off all fp exceptions */ +	current->thread.fp_state.fpscr = 0;	/* turn off all fp exceptions */  	/* create a stack frame for the caller of the handler */  	newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16); @@ -883,20 +1056,18 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,  	regs->gpr[5] = (unsigned long) &rt_sf->uc;  	regs->gpr[6] = (unsigned long) rt_sf;  	regs->nip = (unsigned long) ka->sa.sa_handler; -	/* enter the signal handler in big-endian mode */ +	/* enter the signal handler in native-endian mode */  	regs->msr &= ~MSR_LE; +	regs->msr |= (MSR_KERNEL & MSR_LE);  	return 1;  badframe: -#ifdef DEBUG_SIG -	printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n", -	       regs, frame, newsp); -#endif -	if (show_unhandled_signals && printk_ratelimit()) -		printk(KERN_INFO "%s[%d]: bad frame in handle_rt_signal32: " -			"%p nip %08lx lr %08lx\n", -			current->comm, current->pid, -			addr, regs->nip, regs->link); +	if (show_unhandled_signals) +		printk_ratelimited(KERN_INFO +				   "%s[%d]: bad frame in handle_rt_signal32: " +				   "%p nip %08lx lr %08lx\n", +				   current->comm, current->pid, +				   addr, regs->nip, regs->link);  	force_sigsegv(sig, current);  	return 0; @@ -924,13 +1095,42 @@ static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int  	if (!access_ok(VERIFY_READ, mcp, sizeof(*mcp)))  		return -EFAULT;  #endif -	restore_sigmask(&set); +	set_current_blocked(&set);  	if (restore_user_regs(regs, mcp, sig))  		return -EFAULT;  	return 0;  } +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +static int do_setcontext_tm(struct ucontext __user *ucp, +			    struct ucontext __user *tm_ucp, +			    struct pt_regs *regs) +{ +	sigset_t set; +	struct mcontext __user *mcp; +	struct mcontext __user *tm_mcp; +	u32 cmcp; +	u32 tm_cmcp; + +	if (get_sigset_t(&set, &ucp->uc_sigmask)) +		return -EFAULT; + +	if (__get_user(cmcp, &ucp->uc_regs) || +	    __get_user(tm_cmcp, &tm_ucp->uc_regs)) +		return -EFAULT; +	mcp = (struct mcontext __user *)(u64)cmcp; +	tm_mcp = (struct mcontext __user *)(u64)tm_cmcp; +	/* no need to check access_ok(mcp), since mcp < 4GB */ + +	set_current_blocked(&set); +	if (restore_tm_user_regs(regs, mcp, tm_mcp)) +		return -EFAULT; + +	return 0; +} +#endif +  long sys_swapcontext(struct ucontext __user *old_ctx,  		     struct ucontext __user *new_ctx,  		     int ctx_size, int r6, int r7, int r8, struct pt_regs *regs) @@ -992,7 +1192,7 @@ long sys_swapcontext(struct ucontext __user *old_ctx,  		mctx = (struct mcontext __user *)  			((unsigned long) &old_ctx->uc_mcontext & ~0xfUL);  		if (!access_ok(VERIFY_WRITE, old_ctx, ctx_size) -		    || save_user_regs(regs, mctx, 0, ctx_has_vsx_region) +		    || save_user_regs(regs, mctx, NULL, 0, ctx_has_vsx_region)  		    || put_sigset_t(&old_ctx->uc_sigmask, ¤t->blocked)  		    || __put_user(to_user_ptr(mctx), &old_ctx->uc_regs))  			return -EFAULT; @@ -1026,7 +1226,12 @@ long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,  		     struct pt_regs *regs)  {  	struct rt_sigframe __user *rt_sf; - +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +	struct ucontext __user *uc_transact; +	unsigned long msr_hi; +	unsigned long tmp; +	int tm_restore = 0; +#endif  	/* Always make any pending restarted system calls return -EINTR */  	current_thread_info()->restart_block.fn = do_no_restart_syscall; @@ -1034,6 +1239,34 @@ long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,  		(regs->gpr[1] + __SIGNAL_FRAMESIZE + 16);  	if (!access_ok(VERIFY_READ, rt_sf, sizeof(*rt_sf)))  		goto bad; +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +	if (__get_user(tmp, &rt_sf->uc.uc_link)) +		goto bad; +	uc_transact = (struct ucontext __user *)(uintptr_t)tmp; +	if (uc_transact) { +		u32 cmcp; +		struct mcontext __user *mcp; + +		if (__get_user(cmcp, &uc_transact->uc_regs)) +			return -EFAULT; +		mcp = (struct mcontext __user *)(u64)cmcp; +		/* The top 32 bits of the MSR are stashed in the transactional +		 * ucontext. */ +		if (__get_user(msr_hi, &mcp->mc_gregs[PT_MSR])) +			goto bad; + +		if (MSR_TM_ACTIVE(msr_hi<<32)) { +			/* We only recheckpoint on return if we're +			 * transaction. +			 */ +			tm_restore = 1; +			if (do_setcontext_tm(&rt_sf->uc, uc_transact, regs)) +				goto bad; +		} +	} +	if (!tm_restore) +		/* Fall through, for non-TM restore */ +#endif  	if (do_setcontext(&rt_sf->uc, regs, 1))  		goto bad; @@ -1045,24 +1278,22 @@ long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,  	 * change it.  -- paulus  	 */  #ifdef CONFIG_PPC64 -	/* -	 * We use the compat_sys_ version that does the 32/64 bits conversion -	 * and takes userland pointer directly. What about error checking ? -	 * nobody does any... -	 */ -	compat_sys_sigaltstack((u32)(u64)&rt_sf->uc.uc_stack, 0, 0, 0, 0, 0, regs); +	if (compat_restore_altstack(&rt_sf->uc.uc_stack)) +		goto bad;  #else -	do_sigaltstack(&rt_sf->uc.uc_stack, NULL, regs->gpr[1]); +	if (restore_altstack(&rt_sf->uc.uc_stack)) +		goto bad;  #endif  	set_thread_flag(TIF_RESTOREALL);  	return 0;   bad: -	if (show_unhandled_signals && printk_ratelimit()) -		printk(KERN_INFO "%s[%d]: bad frame in sys_rt_sigreturn: " -			"%p nip %08lx lr %08lx\n", -			current->comm, current->pid, -			rt_sf, regs->nip, regs->link); +	if (show_unhandled_signals) +		printk_ratelimited(KERN_INFO +				   "%s[%d]: bad frame in sys_rt_sigreturn: " +				   "%p nip %08lx lr %08lx\n", +				   current->comm, current->pid, +				   rt_sf, regs->nip, regs->link);  	force_sig(SIGSEGV, current);  	return 0; @@ -1079,7 +1310,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx,  	unsigned char tmp;  	unsigned long new_msr = regs->msr;  #ifdef CONFIG_PPC_ADV_DEBUG_REGS -	unsigned long new_dbcr0 = current->thread.dbcr0; +	unsigned long new_dbcr0 = current->thread.debug.dbcr0;  #endif  	for (i=0; i<ndbg; i++) { @@ -1094,7 +1325,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx,  			} else {  				new_dbcr0 &= ~DBCR0_IC;  				if (!DBCR_ACTIVE_EVENTS(new_dbcr0, -						current->thread.dbcr1)) { +						current->thread.debug.dbcr1)) {  					new_msr &= ~MSR_DE;  					new_dbcr0 &= ~DBCR0_IDM;  				} @@ -1129,7 +1360,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx,  	   the user is really doing something wrong. */  	regs->msr = new_msr;  #ifdef CONFIG_PPC_ADV_DEBUG_REGS -	current->thread.dbcr0 = new_dbcr0; +	current->thread.debug.dbcr0 = new_dbcr0;  #endif  	if (!access_ok(VERIFY_READ, ctx, sizeof(*ctx)) @@ -1149,12 +1380,12 @@ int sys_debug_setcontext(struct ucontext __user *ctx,  	 * We kill the task with a SIGSEGV in this situation.  	 */  	if (do_setcontext(ctx, regs, 1)) { -		if (show_unhandled_signals && printk_ratelimit()) -			printk(KERN_INFO "%s[%d]: bad frame in " -				"sys_debug_setcontext: %p nip %08lx " -				"lr %08lx\n", -				current->comm, current->pid, -				ctx, regs->nip, regs->link); +		if (show_unhandled_signals) +			printk_ratelimited(KERN_INFO "%s[%d]: bad frame in " +					   "sys_debug_setcontext: %p nip %08lx " +					   "lr %08lx\n", +					   current->comm, current->pid, +					   ctx, regs->nip, regs->link);  		force_sig(SIGSEGV, current);  		goto out; @@ -1167,7 +1398,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx,  	 * always done it up until now so it is probably better not to  	 * change it.  -- paulus  	 */ -	do_sigaltstack(&ctx->uc_stack, NULL, regs->gpr[1]); +	restore_altstack(&ctx->uc_stack);  	set_thread_flag(TIF_RESTOREALL);   out: @@ -1183,10 +1414,13 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,  {  	struct sigcontext __user *sc;  	struct sigframe __user *frame; +	struct mcontext __user *tm_mctx = NULL;  	unsigned long newsp = 0; +	int sigret; +	unsigned long tramp;  	/* Set up Signal Frame */ -	frame = get_sigframe(ka, regs, sizeof(*frame), 1); +	frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 1);  	if (unlikely(frame == NULL))  		goto badframe;  	sc = (struct sigcontext __user *) &frame->sctx; @@ -1206,16 +1440,30 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,  		goto badframe;  	if (vdso32_sigtramp && current->mm->context.vdso_base) { -		if (save_user_regs(regs, &frame->mctx, 0, 1)) -			goto badframe; -		regs->link = current->mm->context.vdso_base + vdso32_sigtramp; +		sigret = 0; +		tramp = current->mm->context.vdso_base + vdso32_sigtramp;  	} else { -		if (save_user_regs(regs, &frame->mctx, __NR_sigreturn, 1)) +		sigret = __NR_sigreturn; +		tramp = (unsigned long) frame->mctx.tramp; +	} + +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +	tm_mctx = &frame->mctx_transact; +	if (MSR_TM_ACTIVE(regs->msr)) { +		if (save_tm_user_regs(regs, &frame->mctx, &frame->mctx_transact, +				      sigret)) +			goto badframe; +	} +	else +#endif +	{ +		if (save_user_regs(regs, &frame->mctx, tm_mctx, sigret, 1))  			goto badframe; -		regs->link = (unsigned long) frame->mctx.tramp;  	} -	current->thread.fpscr.val = 0;	/* turn off all fp exceptions */ +	regs->link = tramp; + +	current->thread.fp_state.fpscr = 0;	/* turn off all fp exceptions */  	/* create a stack frame for the caller of the handler */  	newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; @@ -1228,19 +1476,15 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,  	regs->nip = (unsigned long) ka->sa.sa_handler;  	/* enter the signal handler in big-endian mode */  	regs->msr &= ~MSR_LE; -  	return 1;  badframe: -#ifdef DEBUG_SIG -	printk("badframe in handle_signal, regs=%p frame=%p newsp=%lx\n", -	       regs, frame, newsp); -#endif -	if (show_unhandled_signals && printk_ratelimit()) -		printk(KERN_INFO "%s[%d]: bad frame in handle_signal32: " -			"%p nip %08lx lr %08lx\n", -			current->comm, current->pid, -			frame, regs->nip, regs->link); +	if (show_unhandled_signals) +		printk_ratelimited(KERN_INFO +				   "%s[%d]: bad frame in handle_signal32: " +				   "%p nip %08lx lr %08lx\n", +				   current->comm, current->pid, +				   frame, regs->nip, regs->link);  	force_sigsegv(sig, current);  	return 0; @@ -1252,16 +1496,22 @@ badframe:  long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,  		       struct pt_regs *regs)  { +	struct sigframe __user *sf;  	struct sigcontext __user *sc;  	struct sigcontext sigctx;  	struct mcontext __user *sr;  	void __user *addr;  	sigset_t set; +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +	struct mcontext __user *mcp, *tm_mcp; +	unsigned long msr_hi; +#endif  	/* Always make any pending restarted system calls return -EINTR */  	current_thread_info()->restart_block.fn = do_no_restart_syscall; -	sc = (struct sigcontext __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); +	sf = (struct sigframe __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); +	sc = &sf->sctx;  	addr = sc;  	if (copy_from_user(&sigctx, sc, sizeof(sigctx)))  		goto badframe; @@ -1276,23 +1526,38 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,  	set.sig[0] = sigctx.oldmask;  	set.sig[1] = sigctx._unused[3];  #endif -	restore_sigmask(&set); +	set_current_blocked(&set); -	sr = (struct mcontext __user *)from_user_ptr(sigctx.regs); -	addr = sr; -	if (!access_ok(VERIFY_READ, sr, sizeof(*sr)) -	    || restore_user_regs(regs, sr, 1)) +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +	mcp = (struct mcontext __user *)&sf->mctx; +	tm_mcp = (struct mcontext __user *)&sf->mctx_transact; +	if (__get_user(msr_hi, &tm_mcp->mc_gregs[PT_MSR]))  		goto badframe; +	if (MSR_TM_ACTIVE(msr_hi<<32)) { +		if (!cpu_has_feature(CPU_FTR_TM)) +			goto badframe; +		if (restore_tm_user_regs(regs, mcp, tm_mcp)) +			goto badframe; +	} else +#endif +	{ +		sr = (struct mcontext __user *)from_user_ptr(sigctx.regs); +		addr = sr; +		if (!access_ok(VERIFY_READ, sr, sizeof(*sr)) +		    || restore_user_regs(regs, sr, 1)) +			goto badframe; +	}  	set_thread_flag(TIF_RESTOREALL);  	return 0;  badframe: -	if (show_unhandled_signals && printk_ratelimit()) -		printk(KERN_INFO "%s[%d]: bad frame in sys_sigreturn: " -			"%p nip %08lx lr %08lx\n", -			current->comm, current->pid, -			addr, regs->nip, regs->link); +	if (show_unhandled_signals) +		printk_ratelimited(KERN_INFO +				   "%s[%d]: bad frame in sys_sigreturn: " +				   "%p nip %08lx lr %08lx\n", +				   current->comm, current->pid, +				   addr, regs->nip, regs->link);  	force_sig(SIGSEGV, current);  	return 0;  | 
