diff options
Diffstat (limited to 'arch/powerpc/kernel/process.c')
-rw-r--r-- | arch/powerpc/kernel/process.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index d645da302bf2..baae104b16c7 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -864,6 +864,25 @@ static void tm_reclaim_thread(struct thread_struct *thr, | |||
864 | if (!MSR_TM_SUSPENDED(mfmsr())) | 864 | if (!MSR_TM_SUSPENDED(mfmsr())) |
865 | return; | 865 | return; |
866 | 866 | ||
867 | /* | ||
868 | * If we are in a transaction and FP is off then we can't have | ||
869 | * used FP inside that transaction. Hence the checkpointed | ||
870 | * state is the same as the live state. We need to copy the | ||
871 | * live state to the checkpointed state so that when the | ||
872 | * transaction is restored, the checkpointed state is correct | ||
873 | * and the aborted transaction sees the correct state. We use | ||
874 | * ckpt_regs.msr here as that's what tm_reclaim will use to | ||
875 | * determine if it's going to write the checkpointed state or | ||
876 | * not. So either this will write the checkpointed registers, | ||
877 | * or reclaim will. Similarly for VMX. | ||
878 | */ | ||
879 | if ((thr->ckpt_regs.msr & MSR_FP) == 0) | ||
880 | memcpy(&thr->ckfp_state, &thr->fp_state, | ||
881 | sizeof(struct thread_fp_state)); | ||
882 | if ((thr->ckpt_regs.msr & MSR_VEC) == 0) | ||
883 | memcpy(&thr->ckvr_state, &thr->vr_state, | ||
884 | sizeof(struct thread_vr_state)); | ||
885 | |||
867 | giveup_all(container_of(thr, struct task_struct, thread)); | 886 | giveup_all(container_of(thr, struct task_struct, thread)); |
868 | 887 | ||
869 | tm_reclaim(thr, thr->ckpt_regs.msr, cause); | 888 | tm_reclaim(thr, thr->ckpt_regs.msr, cause); |