aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2013-06-09 07:23:15 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-25 17:07:20 -0400
commitd6ea4422c89da1b08029d4db10635942a3b29b2a (patch)
tree31626b9ef31de6bdc9ec97da98fe901da0492223 /arch
parente544a74525b9accf4919822196f29cd967e7e5c0 (diff)
powerpc/tm: Fix writing top half of MSR on 32 bit signals
commit 1d25f11fdbcc5390d68efd98c28900bfd29b264c upstream. The MSR TM controls are in the top 32 bits of the MSR hence on 32 bit signals, we stick the top half of the MSR in the checkpointed signal context so that the user can access it. Unfortunately, we don't currently write anything to the checkpointed signal context when coming in a from a non transactional process and hence the top MSR bits can contain junk. This updates the 32 bit signal handling code to always write something to the top MSR bits so that users know if the process is transactional or not and the kernel can use it on signal return. Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kernel/signal_32.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 201385c3a1ae..5bc819f50af6 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -407,7 +407,8 @@ inline unsigned long copy_transact_fpr_from_user(struct task_struct *task,
407 * altivec/spe instructions at some point. 407 * altivec/spe instructions at some point.
408 */ 408 */
409static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, 409static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
410 int sigret, int ctx_has_vsx_region) 410 struct mcontext __user *tm_frame, int sigret,
411 int ctx_has_vsx_region)
411{ 412{
412 unsigned long msr = regs->msr; 413 unsigned long msr = regs->msr;
413 414
@@ -475,6 +476,12 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
475 476
476 if (__put_user(msr, &frame->mc_gregs[PT_MSR])) 477 if (__put_user(msr, &frame->mc_gregs[PT_MSR]))
477 return 1; 478 return 1;
479 /* We need to write 0 the MSR top 32 bits in the tm frame so that we
480 * can check it on the restore to see if TM is active
481 */
482 if (tm_frame && __put_user(0, &tm_frame->mc_gregs[PT_MSR]))
483 return 1;
484
478 if (sigret) { 485 if (sigret) {
479 /* Set up the sigreturn trampoline: li r0,sigret; sc */ 486 /* Set up the sigreturn trampoline: li r0,sigret; sc */
480 if (__put_user(0x38000000UL + sigret, &frame->tramp[0]) 487 if (__put_user(0x38000000UL + sigret, &frame->tramp[0])
@@ -952,6 +959,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
952{ 959{
953 struct rt_sigframe __user *rt_sf; 960 struct rt_sigframe __user *rt_sf;
954 struct mcontext __user *frame; 961 struct mcontext __user *frame;
962 struct mcontext __user *tm_frame = NULL;
955 void __user *addr; 963 void __user *addr;
956 unsigned long newsp = 0; 964 unsigned long newsp = 0;
957 int sigret; 965 int sigret;
@@ -985,23 +993,24 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
985 } 993 }
986 994
987#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 995#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
996 tm_frame = &rt_sf->uc_transact.uc_mcontext;
988 if (MSR_TM_ACTIVE(regs->msr)) { 997 if (MSR_TM_ACTIVE(regs->msr)) {
989 if (save_tm_user_regs(regs, &rt_sf->uc.uc_mcontext, 998 if (save_tm_user_regs(regs, frame, tm_frame, sigret))
990 &rt_sf->uc_transact.uc_mcontext, sigret))
991 goto badframe; 999 goto badframe;
992 } 1000 }
993 else 1001 else
994#endif 1002#endif
995 if (save_user_regs(regs, frame, sigret, 1)) 1003 {
1004 if (save_user_regs(regs, frame, tm_frame, sigret, 1))
996 goto badframe; 1005 goto badframe;
1006 }
997 regs->link = tramp; 1007 regs->link = tramp;
998 1008
999#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 1009#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1000 if (MSR_TM_ACTIVE(regs->msr)) { 1010 if (MSR_TM_ACTIVE(regs->msr)) {
1001 if (__put_user((unsigned long)&rt_sf->uc_transact, 1011 if (__put_user((unsigned long)&rt_sf->uc_transact,
1002 &rt_sf->uc.uc_link) 1012 &rt_sf->uc.uc_link)
1003 || __put_user(to_user_ptr(&rt_sf->uc_transact.uc_mcontext), 1013 || __put_user((unsigned long)tm_frame, &rt_sf->uc_transact.uc_regs))
1004 &rt_sf->uc_transact.uc_regs))
1005 goto badframe; 1014 goto badframe;
1006 } 1015 }
1007 else 1016 else
@@ -1170,7 +1179,7 @@ long sys_swapcontext(struct ucontext __user *old_ctx,
1170 mctx = (struct mcontext __user *) 1179 mctx = (struct mcontext __user *)
1171 ((unsigned long) &old_ctx->uc_mcontext & ~0xfUL); 1180 ((unsigned long) &old_ctx->uc_mcontext & ~0xfUL);
1172 if (!access_ok(VERIFY_WRITE, old_ctx, ctx_size) 1181 if (!access_ok(VERIFY_WRITE, old_ctx, ctx_size)
1173 || save_user_regs(regs, mctx, 0, ctx_has_vsx_region) 1182 || save_user_regs(regs, mctx, NULL, 0, ctx_has_vsx_region)
1174 || put_sigset_t(&old_ctx->uc_sigmask, &current->blocked) 1183 || put_sigset_t(&old_ctx->uc_sigmask, &current->blocked)
1175 || __put_user(to_user_ptr(mctx), &old_ctx->uc_regs)) 1184 || __put_user(to_user_ptr(mctx), &old_ctx->uc_regs))
1176 return -EFAULT; 1185 return -EFAULT;
@@ -1392,6 +1401,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
1392{ 1401{
1393 struct sigcontext __user *sc; 1402 struct sigcontext __user *sc;
1394 struct sigframe __user *frame; 1403 struct sigframe __user *frame;
1404 struct mcontext __user *tm_mctx = NULL;
1395 unsigned long newsp = 0; 1405 unsigned long newsp = 0;
1396 int sigret; 1406 int sigret;
1397 unsigned long tramp; 1407 unsigned long tramp;
@@ -1425,6 +1435,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
1425 } 1435 }
1426 1436
1427#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 1437#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1438 tm_mctx = &frame->mctx_transact;
1428 if (MSR_TM_ACTIVE(regs->msr)) { 1439 if (MSR_TM_ACTIVE(regs->msr)) {
1429 if (save_tm_user_regs(regs, &frame->mctx, &frame->mctx_transact, 1440 if (save_tm_user_regs(regs, &frame->mctx, &frame->mctx_transact,
1430 sigret)) 1441 sigret))
@@ -1432,8 +1443,10 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
1432 } 1443 }
1433 else 1444 else
1434#endif 1445#endif
1435 if (save_user_regs(regs, &frame->mctx, sigret, 1)) 1446 {
1447 if (save_user_regs(regs, &frame->mctx, tm_mctx, sigret, 1))
1436 goto badframe; 1448 goto badframe;
1449 }
1437 1450
1438 regs->link = tramp; 1451 regs->link = tramp;
1439 1452