aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2014-04-04 05:19:48 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-04-06 20:33:13 -0400
commite6b8fd028b584ffca7a7255b8971f254932c9fce (patch)
tree4ac41335a6f86f5f69e3dc48d92bec280e5c2c31 /arch/powerpc
parenta08a53ea4c97940fe83fea3eab27618ac0fb5ed1 (diff)
powerpc/tm: Disable IRQ in tm_recheckpoint
We can't take an IRQ when we're about to do a trechkpt as our GPR state is set to user GPR values. We've hit this when running some IBM Java stress tests in the lab resulting in the following dump: cpu 0x3f: Vector: 700 (Program Check) at [c000000007eb3d40] pc: c000000000050074: restore_gprs+0xc0/0x148 lr: 00000000b52a8184 sp: ac57d360 msr: 8000000100201030 current = 0xc00000002c500000 paca = 0xc000000007dbfc00 softe: 0 irq_happened: 0x00 pid = 34535, comm = Pooled Thread # R00 = 00000000b52a8184 R16 = 00000000b3e48fda R01 = 00000000ac57d360 R17 = 00000000ade79bd8 R02 = 00000000ac586930 R18 = 000000000fac9bcc R03 = 00000000ade60000 R19 = 00000000ac57f930 R04 = 00000000f6624918 R20 = 00000000ade79be8 R05 = 00000000f663f238 R21 = 00000000ac218a54 R06 = 0000000000000002 R22 = 000000000f956280 R07 = 0000000000000008 R23 = 000000000000007e R08 = 000000000000000a R24 = 000000000000000c R09 = 00000000b6e69160 R25 = 00000000b424cf00 R10 = 0000000000000181 R26 = 00000000f66256d4 R11 = 000000000f365ec0 R27 = 00000000b6fdcdd0 R12 = 00000000f66400f0 R28 = 0000000000000001 R13 = 00000000ada71900 R29 = 00000000ade5a300 R14 = 00000000ac2185a8 R30 = 00000000f663f238 R15 = 0000000000000004 R31 = 00000000f6624918 pc = c000000000050074 restore_gprs+0xc0/0x148 cfar= c00000000004fe28 dont_restore_vec+0x1c/0x1a4 lr = 00000000b52a8184 msr = 8000000100201030 cr = 24804888 ctr = 0000000000000000 xer = 0000000000000000 trap = 700 This moves tm_recheckpoint to a C function and moves the tm_restore_sprs into that function. It then adds IRQ disabling over the trechkpt critical section. It also sets the TEXASR FS in the signals code to ensure this is never set now that we explictly write the TM sprs in tm_recheckpoint. Signed-off-by: Michael Neuling <mikey@neuling.org> cc: stable@vger.kernel.org Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/process.c34
-rw-r--r--arch/powerpc/kernel/signal_32.c2
-rw-r--r--arch/powerpc/kernel/signal_64.c2
-rw-r--r--arch/powerpc/kernel/tm.S2
4 files changed, 33 insertions, 7 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index af064d28b365..31d021506d21 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -610,6 +610,31 @@ out_and_saveregs:
610 tm_save_sprs(thr); 610 tm_save_sprs(thr);
611} 611}
612 612
613extern void __tm_recheckpoint(struct thread_struct *thread,
614 unsigned long orig_msr);
615
616void tm_recheckpoint(struct thread_struct *thread,
617 unsigned long orig_msr)
618{
619 unsigned long flags;
620
621 /* We really can't be interrupted here as the TEXASR registers can't
622 * change and later in the trecheckpoint code, we have a userspace R1.
623 * So let's hard disable over this region.
624 */
625 local_irq_save(flags);
626 hard_irq_disable();
627
628 /* The TM SPRs are restored here, so that TEXASR.FS can be set
629 * before the trecheckpoint and no explosion occurs.
630 */
631 tm_restore_sprs(thread);
632
633 __tm_recheckpoint(thread, orig_msr);
634
635 local_irq_restore(flags);
636}
637
613static inline void tm_recheckpoint_new_task(struct task_struct *new) 638static inline void tm_recheckpoint_new_task(struct task_struct *new)
614{ 639{
615 unsigned long msr; 640 unsigned long msr;
@@ -628,13 +653,10 @@ static inline void tm_recheckpoint_new_task(struct task_struct *new)
628 if (!new->thread.regs) 653 if (!new->thread.regs)
629 return; 654 return;
630 655
631 /* The TM SPRs are restored here, so that TEXASR.FS can be set 656 if (!MSR_TM_ACTIVE(new->thread.regs->msr)){
632 * before the trecheckpoint and no explosion occurs. 657 tm_restore_sprs(&new->thread);
633 */
634 tm_restore_sprs(&new->thread);
635
636 if (!MSR_TM_ACTIVE(new->thread.regs->msr))
637 return; 658 return;
659 }
638 msr = new->thread.tm_orig_msr; 660 msr = new->thread.tm_orig_msr;
639 /* Recheckpoint to restore original checkpointed register state. */ 661 /* Recheckpoint to restore original checkpointed register state. */
640 TM_DEBUG("*** tm_recheckpoint of pid %d " 662 TM_DEBUG("*** tm_recheckpoint of pid %d "
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index a67e00aa3caa..4e47db686b5d 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -881,6 +881,8 @@ static long restore_tm_user_regs(struct pt_regs *regs,
881 * transactional versions should be loaded. 881 * transactional versions should be loaded.
882 */ 882 */
883 tm_enable(); 883 tm_enable();
884 /* Make sure the transaction is marked as failed */
885 current->thread.tm_texasr |= TEXASR_FS;
884 /* This loads the checkpointed FP/VEC state, if used */ 886 /* This loads the checkpointed FP/VEC state, if used */
885 tm_recheckpoint(&current->thread, msr); 887 tm_recheckpoint(&current->thread, msr);
886 /* Get the top half of the MSR */ 888 /* Get the top half of the MSR */
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 8d253c29649b..d501dc4dc3e6 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -527,6 +527,8 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
527 } 527 }
528#endif 528#endif
529 tm_enable(); 529 tm_enable();
530 /* Make sure the transaction is marked as failed */
531 current->thread.tm_texasr |= TEXASR_FS;
530 /* This loads the checkpointed FP/VEC state, if used */ 532 /* This loads the checkpointed FP/VEC state, if used */
531 tm_recheckpoint(&current->thread, msr); 533 tm_recheckpoint(&current->thread, msr);
532 534
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S
index ef47bcbd4352..03567c05950a 100644
--- a/arch/powerpc/kernel/tm.S
+++ b/arch/powerpc/kernel/tm.S
@@ -307,7 +307,7 @@ dont_backup_fp:
307 * Call with IRQs off, stacks get all out of sync for 307 * Call with IRQs off, stacks get all out of sync for
308 * some periods in here! 308 * some periods in here!
309 */ 309 */
310_GLOBAL(tm_recheckpoint) 310_GLOBAL(__tm_recheckpoint)
311 mfcr r5 311 mfcr r5
312 mflr r0 312 mflr r0
313 stw r5, 8(r1) 313 stw r5, 8(r1)