diff options
Diffstat (limited to 'arch/powerpc/kernel')
| -rw-r--r-- | arch/powerpc/kernel/idle_book3s.S | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/kprobes.c | 3 | ||||
| -rw-r--r-- | arch/powerpc/kernel/process.c | 19 |
3 files changed, 22 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/idle_book3s.S b/arch/powerpc/kernel/idle_book3s.S index 07d4e0ad60db..4898d676dcae 100644 --- a/arch/powerpc/kernel/idle_book3s.S +++ b/arch/powerpc/kernel/idle_book3s.S | |||
| @@ -416,7 +416,7 @@ power9_dd1_recover_paca: | |||
| 416 | * which needs to be restored from the stack. | 416 | * which needs to be restored from the stack. |
| 417 | */ | 417 | */ |
| 418 | li r3, 1 | 418 | li r3, 1 |
| 419 | stb r0,PACA_NAPSTATELOST(r13) | 419 | stb r3,PACA_NAPSTATELOST(r13) |
| 420 | blr | 420 | blr |
| 421 | 421 | ||
| 422 | /* | 422 | /* |
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 160ae0fa7d0d..fc4343514bed 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c | |||
| @@ -305,16 +305,17 @@ int kprobe_handler(struct pt_regs *regs) | |||
| 305 | save_previous_kprobe(kcb); | 305 | save_previous_kprobe(kcb); |
| 306 | set_current_kprobe(p, regs, kcb); | 306 | set_current_kprobe(p, regs, kcb); |
| 307 | kprobes_inc_nmissed_count(p); | 307 | kprobes_inc_nmissed_count(p); |
| 308 | prepare_singlestep(p, regs); | ||
| 309 | kcb->kprobe_status = KPROBE_REENTER; | 308 | kcb->kprobe_status = KPROBE_REENTER; |
| 310 | if (p->ainsn.boostable >= 0) { | 309 | if (p->ainsn.boostable >= 0) { |
| 311 | ret = try_to_emulate(p, regs); | 310 | ret = try_to_emulate(p, regs); |
| 312 | 311 | ||
| 313 | if (ret > 0) { | 312 | if (ret > 0) { |
| 314 | restore_previous_kprobe(kcb); | 313 | restore_previous_kprobe(kcb); |
| 314 | preempt_enable_no_resched(); | ||
| 315 | return 1; | 315 | return 1; |
| 316 | } | 316 | } |
| 317 | } | 317 | } |
| 318 | prepare_singlestep(p, regs); | ||
| 318 | return 1; | 319 | return 1; |
| 319 | } else { | 320 | } else { |
| 320 | if (*addr != BREAKPOINT_INSTRUCTION) { | 321 | if (*addr != BREAKPOINT_INSTRUCTION) { |
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); |
