Skip to content

Commit 621b506

Browse files
mikeyozbenh
authored andcommitted
powerpc/tm: Fix crash when forking inside a transaction
When we fork/clone we currently don't copy any of the TM state to the new thread. This results in a TM bad thing (program check) when the new process is switched in as the kernel does a tmrechkpt with TEXASR FS not set. Also, since R1 is from userspace, we trigger the bad kernel stack pointer detection. So we end up with something like this: Bad kernel stack pointer 0 at c0000000000404fc cpu 0x2: Vector: 700 (Program Check) at [c00000003ffefd40] pc: c0000000000404fc: restore_gprs+0xc0/0x148 lr: 0000000000000000 sp: 0 msr: 9000000100201030 current = 0xc000001dd1417c30 paca = 0xc00000000fe00800 softe: 0 irq_happened: 0x01 pid = 0, comm = swapper/2 WARNING: exception is not recoverable, can't continue The below fixes this by flushing the TM state before we copy the task_struct to the clone. To do this we go through the tmreclaim patch, which removes the checkpointed registers from the CPU and transitions the CPU out of TM suspend mode. Hence we need to call tmrechkpt after to restore the checkpointed state and the TM mode for the current task. To make this fail from userspace is simply: tbegin li r0, 2 sc <boom> Kudos to Adhemerval Zanella Neto for finding this. Signed-off-by: Michael Neuling <mikey@neuling.org> cc: Adhemerval Zanella Neto <azanella@br.ibm.com> cc: stable@vger.kernel.org Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
1 parent e0cf957 commit 621b506

File tree

1 file changed

+9
-0
lines changed

1 file changed

+9
-0
lines changed

Diff for: arch/powerpc/kernel/process.c

+9
Original file line numberDiff line numberDiff line change
@@ -1048,6 +1048,15 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
10481048
flush_altivec_to_thread(src);
10491049
flush_vsx_to_thread(src);
10501050
flush_spe_to_thread(src);
1051+
/*
1052+
* Flush TM state out so we can copy it. __switch_to_tm() does this
1053+
* flush but it removes the checkpointed state from the current CPU and
1054+
* transitions the CPU out of TM mode. Hence we need to call
1055+
* tm_recheckpoint_new_task() (on the same task) to restore the
1056+
* checkpointed state back and the TM mode.
1057+
*/
1058+
__switch_to_tm(src);
1059+
tm_recheckpoint_new_task(src);
10511060

10521061
*dst = *src;
10531062

0 commit comments

Comments
 (0)