aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/processor.h2
-rw-r--r--arch/powerpc/include/asm/thread_info.h5
-rw-r--r--arch/powerpc/include/asm/tm.h1
-rw-r--r--arch/powerpc/kernel/entry_64.S12
-rw-r--r--arch/powerpc/kernel/fpu.S16
-rw-r--r--arch/powerpc/kernel/process.c146
-rw-r--r--arch/powerpc/kernel/signal.c3
-rw-r--r--arch/powerpc/kernel/signal_32.c21
-rw-r--r--arch/powerpc/kernel/signal_64.c14
-rw-r--r--arch/powerpc/kernel/traps.c12
-rw-r--r--arch/powerpc/kernel/vector.S10
11 files changed, 195 insertions, 47 deletions
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index fc14a38c7ccf..232a2fa5b483 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -373,6 +373,8 @@ extern int set_endian(struct task_struct *tsk, unsigned int val);
373extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr); 373extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr);
374extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val); 374extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val);
375 375
376extern void fp_enable(void);
377extern void vec_enable(void);
376extern void load_fp_state(struct thread_fp_state *fp); 378extern void load_fp_state(struct thread_fp_state *fp);
377extern void store_fp_state(struct thread_fp_state *fp); 379extern void store_fp_state(struct thread_fp_state *fp);
378extern void load_vr_state(struct thread_vr_state *vr); 380extern void load_vr_state(struct thread_vr_state *vr);
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h
index fc2bf414c584..b034ecdb7c74 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -91,6 +91,7 @@ static inline struct thread_info *current_thread_info(void)
91#define TIF_POLLING_NRFLAG 3 /* true if poll_idle() is polling 91#define TIF_POLLING_NRFLAG 3 /* true if poll_idle() is polling
92 TIF_NEED_RESCHED */ 92 TIF_NEED_RESCHED */
93#define TIF_32BIT 4 /* 32 bit binary */ 93#define TIF_32BIT 4 /* 32 bit binary */
94#define TIF_RESTORE_TM 5 /* need to restore TM FP/VEC/VSX */
94#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ 95#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */
95#define TIF_SINGLESTEP 8 /* singlestepping active */ 96#define TIF_SINGLESTEP 8 /* singlestepping active */
96#define TIF_NOHZ 9 /* in adaptive nohz mode */ 97#define TIF_NOHZ 9 /* in adaptive nohz mode */
@@ -113,6 +114,7 @@ static inline struct thread_info *current_thread_info(void)
113#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) 114#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
114#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) 115#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
115#define _TIF_32BIT (1<<TIF_32BIT) 116#define _TIF_32BIT (1<<TIF_32BIT)
117#define _TIF_RESTORE_TM (1<<TIF_RESTORE_TM)
116#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) 118#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
117#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP) 119#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
118#define _TIF_SECCOMP (1<<TIF_SECCOMP) 120#define _TIF_SECCOMP (1<<TIF_SECCOMP)
@@ -128,7 +130,8 @@ static inline struct thread_info *current_thread_info(void)
128 _TIF_NOHZ) 130 _TIF_NOHZ)
129 131
130#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ 132#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
131 _TIF_NOTIFY_RESUME | _TIF_UPROBE) 133 _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
134 _TIF_RESTORE_TM)
132#define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR) 135#define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR)
133 136
134/* Bits in local_flags */ 137/* Bits in local_flags */
diff --git a/arch/powerpc/include/asm/tm.h b/arch/powerpc/include/asm/tm.h
index 9dfbc34bdbf5..0c9f8b74dd97 100644
--- a/arch/powerpc/include/asm/tm.h
+++ b/arch/powerpc/include/asm/tm.h
@@ -15,6 +15,7 @@ extern void do_load_up_transact_altivec(struct thread_struct *thread);
15extern void tm_enable(void); 15extern void tm_enable(void);
16extern void tm_reclaim(struct thread_struct *thread, 16extern void tm_reclaim(struct thread_struct *thread,
17 unsigned long orig_msr, uint8_t cause); 17 unsigned long orig_msr, uint8_t cause);
18extern void tm_reclaim_current(uint8_t cause);
18extern void tm_recheckpoint(struct thread_struct *thread, 19extern void tm_recheckpoint(struct thread_struct *thread,
19 unsigned long orig_msr); 20 unsigned long orig_msr);
20extern void tm_abort(uint8_t cause); 21extern void tm_abort(uint8_t cause);
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index bbfb0294b354..662c6dd98072 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -664,8 +664,16 @@ _GLOBAL(ret_from_except_lite)
664 bl .restore_interrupts 664 bl .restore_interrupts
665 SCHEDULE_USER 665 SCHEDULE_USER
666 b .ret_from_except_lite 666 b .ret_from_except_lite
667 6672:
6682: bl .save_nvgprs 668#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
669 andi. r0,r4,_TIF_USER_WORK_MASK & ~_TIF_RESTORE_TM
670 bne 3f /* only restore TM if nothing else to do */
671 addi r3,r1,STACK_FRAME_OVERHEAD
672 bl .restore_tm_state
673 b restore
6743:
675#endif
676 bl .save_nvgprs
669 bl .restore_interrupts 677 bl .restore_interrupts
670 addi r3,r1,STACK_FRAME_OVERHEAD 678 addi r3,r1,STACK_FRAME_OVERHEAD
671 bl .do_notify_resume 679 bl .do_notify_resume
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S
index f7f5b8bed68f..9ad236e5d2c9 100644
--- a/arch/powerpc/kernel/fpu.S
+++ b/arch/powerpc/kernel/fpu.S
@@ -81,6 +81,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
81#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ 81#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
82 82
83/* 83/*
84 * Enable use of the FPU, and VSX if possible, for the caller.
85 */
86_GLOBAL(fp_enable)
87 mfmsr r3
88 ori r3,r3,MSR_FP
89#ifdef CONFIG_VSX
90BEGIN_FTR_SECTION
91 oris r3,r3,MSR_VSX@h
92END_FTR_SECTION_IFSET(CPU_FTR_VSX)
93#endif
94 SYNC
95 MTMSRD(r3)
96 isync /* (not necessary for arch 2.02 and later) */
97 blr
98
99/*
84 * Load state from memory into FP registers including FPSCR. 100 * Load state from memory into FP registers including FPSCR.
85 * Assumes the caller has enabled FP in the MSR. 101 * Assumes the caller has enabled FP in the MSR.
86 */ 102 */
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index bf8e136316e2..3573d186505f 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -73,6 +73,48 @@ struct task_struct *last_task_used_vsx = NULL;
73struct task_struct *last_task_used_spe = NULL; 73struct task_struct *last_task_used_spe = NULL;
74#endif 74#endif
75 75
76#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
77void giveup_fpu_maybe_transactional(struct task_struct *tsk)
78{
79 /*
80 * If we are saving the current thread's registers, and the
81 * thread is in a transactional state, set the TIF_RESTORE_TM
82 * bit so that we know to restore the registers before
83 * returning to userspace.
84 */
85 if (tsk == current && tsk->thread.regs &&
86 MSR_TM_ACTIVE(tsk->thread.regs->msr) &&
87 !test_thread_flag(TIF_RESTORE_TM)) {
88 tsk->thread.tm_orig_msr = tsk->thread.regs->msr;
89 set_thread_flag(TIF_RESTORE_TM);
90 }
91
92 giveup_fpu(tsk);
93}
94
95void giveup_altivec_maybe_transactional(struct task_struct *tsk)
96{
97 /*
98 * If we are saving the current thread's registers, and the
99 * thread is in a transactional state, set the TIF_RESTORE_TM
100 * bit so that we know to restore the registers before
101 * returning to userspace.
102 */
103 if (tsk == current && tsk->thread.regs &&
104 MSR_TM_ACTIVE(tsk->thread.regs->msr) &&
105 !test_thread_flag(TIF_RESTORE_TM)) {
106 tsk->thread.tm_orig_msr = tsk->thread.regs->msr;
107 set_thread_flag(TIF_RESTORE_TM);
108 }
109
110 giveup_altivec(tsk);
111}
112
113#else
114#define giveup_fpu_maybe_transactional(tsk) giveup_fpu(tsk)
115#define giveup_altivec_maybe_transactional(tsk) giveup_altivec(tsk)
116#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
117
76#ifdef CONFIG_PPC_FPU 118#ifdef CONFIG_PPC_FPU
77/* 119/*
78 * Make sure the floating-point register state in the 120 * Make sure the floating-point register state in the
@@ -101,13 +143,13 @@ void flush_fp_to_thread(struct task_struct *tsk)
101 */ 143 */
102 BUG_ON(tsk != current); 144 BUG_ON(tsk != current);
103#endif 145#endif
104 giveup_fpu(tsk); 146 giveup_fpu_maybe_transactional(tsk);
105 } 147 }
106 preempt_enable(); 148 preempt_enable();
107 } 149 }
108} 150}
109EXPORT_SYMBOL_GPL(flush_fp_to_thread); 151EXPORT_SYMBOL_GPL(flush_fp_to_thread);
110#endif 152#endif /* CONFIG_PPC_FPU */
111 153
112void enable_kernel_fp(void) 154void enable_kernel_fp(void)
113{ 155{
@@ -115,11 +157,11 @@ void enable_kernel_fp(void)
115 157
116#ifdef CONFIG_SMP 158#ifdef CONFIG_SMP
117 if (current->thread.regs && (current->thread.regs->msr & MSR_FP)) 159 if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
118 giveup_fpu(current); 160 giveup_fpu_maybe_transactional(current);
119 else 161 else
120 giveup_fpu(NULL); /* just enables FP for kernel */ 162 giveup_fpu(NULL); /* just enables FP for kernel */
121#else 163#else
122 giveup_fpu(last_task_used_math); 164 giveup_fpu_maybe_transactional(last_task_used_math);
123#endif /* CONFIG_SMP */ 165#endif /* CONFIG_SMP */
124} 166}
125EXPORT_SYMBOL(enable_kernel_fp); 167EXPORT_SYMBOL(enable_kernel_fp);
@@ -131,11 +173,11 @@ void enable_kernel_altivec(void)
131 173
132#ifdef CONFIG_SMP 174#ifdef CONFIG_SMP
133 if (current->thread.regs && (current->thread.regs->msr & MSR_VEC)) 175 if (current->thread.regs && (current->thread.regs->msr & MSR_VEC))
134 giveup_altivec(current); 176 giveup_altivec_maybe_transactional(current);
135 else 177 else
136 giveup_altivec_notask(); 178 giveup_altivec_notask();
137#else 179#else
138 giveup_altivec(last_task_used_altivec); 180 giveup_altivec_maybe_transactional(last_task_used_altivec);
139#endif /* CONFIG_SMP */ 181#endif /* CONFIG_SMP */
140} 182}
141EXPORT_SYMBOL(enable_kernel_altivec); 183EXPORT_SYMBOL(enable_kernel_altivec);
@@ -152,7 +194,7 @@ void flush_altivec_to_thread(struct task_struct *tsk)
152#ifdef CONFIG_SMP 194#ifdef CONFIG_SMP
153 BUG_ON(tsk != current); 195 BUG_ON(tsk != current);
154#endif 196#endif
155 giveup_altivec(tsk); 197 giveup_altivec_maybe_transactional(tsk);
156 } 198 }
157 preempt_enable(); 199 preempt_enable();
158 } 200 }
@@ -181,8 +223,8 @@ EXPORT_SYMBOL(enable_kernel_vsx);
181 223
182void giveup_vsx(struct task_struct *tsk) 224void giveup_vsx(struct task_struct *tsk)
183{ 225{
184 giveup_fpu(tsk); 226 giveup_fpu_maybe_transactional(tsk);
185 giveup_altivec(tsk); 227 giveup_altivec_maybe_transactional(tsk);
186 __giveup_vsx(tsk); 228 __giveup_vsx(tsk);
187} 229}
188 230
@@ -478,7 +520,48 @@ static inline bool hw_brk_match(struct arch_hw_breakpoint *a,
478 return false; 520 return false;
479 return true; 521 return true;
480} 522}
523
481#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 524#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
525static void tm_reclaim_thread(struct thread_struct *thr,
526 struct thread_info *ti, uint8_t cause)
527{
528 unsigned long msr_diff = 0;
529
530 /*
531 * If FP/VSX registers have been already saved to the
532 * thread_struct, move them to the transact_fp array.
533 * We clear the TIF_RESTORE_TM bit since after the reclaim
534 * the thread will no longer be transactional.
535 */
536 if (test_ti_thread_flag(ti, TIF_RESTORE_TM)) {
537 msr_diff = thr->tm_orig_msr & ~thr->regs->msr;
538 if (msr_diff & MSR_FP)
539 memcpy(&thr->transact_fp, &thr->fp_state,
540 sizeof(struct thread_fp_state));
541 if (msr_diff & MSR_VEC)
542 memcpy(&thr->transact_vr, &thr->vr_state,
543 sizeof(struct thread_vr_state));
544 clear_ti_thread_flag(ti, TIF_RESTORE_TM);
545 msr_diff &= MSR_FP | MSR_VEC | MSR_VSX | MSR_FE0 | MSR_FE1;
546 }
547
548 tm_reclaim(thr, thr->regs->msr, cause);
549
550 /* Having done the reclaim, we now have the checkpointed
551 * FP/VSX values in the registers. These might be valid
552 * even if we have previously called enable_kernel_fp() or
553 * flush_fp_to_thread(), so update thr->regs->msr to
554 * indicate their current validity.
555 */
556 thr->regs->msr |= msr_diff;
557}
558
559void tm_reclaim_current(uint8_t cause)
560{
561 tm_enable();
562 tm_reclaim_thread(&current->thread, current_thread_info(), cause);
563}
564
482static inline void tm_reclaim_task(struct task_struct *tsk) 565static inline void tm_reclaim_task(struct task_struct *tsk)
483{ 566{
484 /* We have to work out if we're switching from/to a task that's in the 567 /* We have to work out if we're switching from/to a task that's in the
@@ -501,9 +584,11 @@ static inline void tm_reclaim_task(struct task_struct *tsk)
501 584
502 /* Stash the original thread MSR, as giveup_fpu et al will 585 /* Stash the original thread MSR, as giveup_fpu et al will
503 * modify it. We hold onto it to see whether the task used 586 * modify it. We hold onto it to see whether the task used
504 * FP & vector regs. 587 * FP & vector regs. If the TIF_RESTORE_TM flag is set,
588 * tm_orig_msr is already set.
505 */ 589 */
506 thr->tm_orig_msr = thr->regs->msr; 590 if (!test_ti_thread_flag(task_thread_info(tsk), TIF_RESTORE_TM))
591 thr->tm_orig_msr = thr->regs->msr;
507 592
508 TM_DEBUG("--- tm_reclaim on pid %d (NIP=%lx, " 593 TM_DEBUG("--- tm_reclaim on pid %d (NIP=%lx, "
509 "ccr=%lx, msr=%lx, trap=%lx)\n", 594 "ccr=%lx, msr=%lx, trap=%lx)\n",
@@ -511,7 +596,7 @@ static inline void tm_reclaim_task(struct task_struct *tsk)
511 thr->regs->ccr, thr->regs->msr, 596 thr->regs->ccr, thr->regs->msr,
512 thr->regs->trap); 597 thr->regs->trap);
513 598
514 tm_reclaim(thr, thr->regs->msr, TM_CAUSE_RESCHED); 599 tm_reclaim_thread(thr, task_thread_info(tsk), TM_CAUSE_RESCHED);
515 600
516 TM_DEBUG("--- tm_reclaim on pid %d complete\n", 601 TM_DEBUG("--- tm_reclaim on pid %d complete\n",
517 tsk->pid); 602 tsk->pid);
@@ -587,6 +672,43 @@ static inline void __switch_to_tm(struct task_struct *prev)
587 tm_reclaim_task(prev); 672 tm_reclaim_task(prev);
588 } 673 }
589} 674}
675
676/*
677 * This is called if we are on the way out to userspace and the
678 * TIF_RESTORE_TM flag is set. It checks if we need to reload
679 * FP and/or vector state and does so if necessary.
680 * If userspace is inside a transaction (whether active or
681 * suspended) and FP/VMX/VSX instructions have ever been enabled
682 * inside that transaction, then we have to keep them enabled
683 * and keep the FP/VMX/VSX state loaded while ever the transaction
684 * continues. The reason is that if we didn't, and subsequently
685 * got a FP/VMX/VSX unavailable interrupt inside a transaction,
686 * we don't know whether it's the same transaction, and thus we
687 * don't know which of the checkpointed state and the transactional
688 * state to use.
689 */
690void restore_tm_state(struct pt_regs *regs)
691{
692 unsigned long msr_diff;
693
694 clear_thread_flag(TIF_RESTORE_TM);
695 if (!MSR_TM_ACTIVE(regs->msr))
696 return;
697
698 msr_diff = current->thread.tm_orig_msr & ~regs->msr;
699 msr_diff &= MSR_FP | MSR_VEC | MSR_VSX;
700 if (msr_diff & MSR_FP) {
701 fp_enable();
702 load_fp_state(&current->thread.fp_state);
703 regs->msr |= current->thread.fpexc_mode;
704 }
705 if (msr_diff & MSR_VEC) {
706 vec_enable();
707 load_vr_state(&current->thread.vr_state);
708 }
709 regs->msr |= msr_diff;
710}
711
590#else 712#else
591#define tm_recheckpoint_new_task(new) 713#define tm_recheckpoint_new_task(new)
592#define __switch_to_tm(prev) 714#define __switch_to_tm(prev)
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index 457e97aa2945..8fc4177ed65a 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -203,8 +203,7 @@ unsigned long get_tm_stackpointer(struct pt_regs *regs)
203 203
204#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 204#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
205 if (MSR_TM_ACTIVE(regs->msr)) { 205 if (MSR_TM_ACTIVE(regs->msr)) {
206 tm_enable(); 206 tm_reclaim_current(TM_CAUSE_SIGNAL);
207 tm_reclaim(&current->thread, regs->msr, TM_CAUSE_SIGNAL);
208 if (MSR_TM_TRANSACTIONAL(regs->msr)) 207 if (MSR_TM_TRANSACTIONAL(regs->msr))
209 return current->thread.ckpt_regs.gpr[1]; 208 return current->thread.ckpt_regs.gpr[1];
210 } 209 }
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 68027bfa5f8e..6ce69e6f1fcb 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -519,6 +519,13 @@ static int save_tm_user_regs(struct pt_regs *regs,
519{ 519{
520 unsigned long msr = regs->msr; 520 unsigned long msr = regs->msr;
521 521
522 /* Remove TM bits from thread's MSR. The MSR in the sigcontext
523 * just indicates to userland that we were doing a transaction, but we
524 * don't want to return in transactional state. This also ensures
525 * that flush_fp_to_thread won't set TIF_RESTORE_TM again.
526 */
527 regs->msr &= ~MSR_TS_MASK;
528
522 /* Make sure floating point registers are stored in regs */ 529 /* Make sure floating point registers are stored in regs */
523 flush_fp_to_thread(current); 530 flush_fp_to_thread(current);
524 531
@@ -1056,13 +1063,6 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
1056 /* enter the signal handler in native-endian mode */ 1063 /* enter the signal handler in native-endian mode */
1057 regs->msr &= ~MSR_LE; 1064 regs->msr &= ~MSR_LE;
1058 regs->msr |= (MSR_KERNEL & MSR_LE); 1065 regs->msr |= (MSR_KERNEL & MSR_LE);
1059#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1060 /* Remove TM bits from thread's MSR. The MSR in the sigcontext
1061 * just indicates to userland that we were doing a transaction, but we
1062 * don't want to return in transactional state:
1063 */
1064 regs->msr &= ~MSR_TS_MASK;
1065#endif
1066 return 1; 1066 return 1;
1067 1067
1068badframe: 1068badframe:
@@ -1484,13 +1484,6 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
1484 regs->nip = (unsigned long) ka->sa.sa_handler; 1484 regs->nip = (unsigned long) ka->sa.sa_handler;
1485 /* enter the signal handler in big-endian mode */ 1485 /* enter the signal handler in big-endian mode */
1486 regs->msr &= ~MSR_LE; 1486 regs->msr &= ~MSR_LE;
1487#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1488 /* Remove TM bits from thread's MSR. The MSR in the sigcontext
1489 * just indicates to userland that we were doing a transaction, but we
1490 * don't want to return in transactional state:
1491 */
1492 regs->msr &= ~MSR_TS_MASK;
1493#endif
1494 return 1; 1487 return 1;
1495 1488
1496badframe: 1489badframe:
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 42991045349f..e35bf773df7a 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -192,6 +192,13 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,
192 192
193 BUG_ON(!MSR_TM_ACTIVE(regs->msr)); 193 BUG_ON(!MSR_TM_ACTIVE(regs->msr));
194 194
195 /* Remove TM bits from thread's MSR. The MSR in the sigcontext
196 * just indicates to userland that we were doing a transaction, but we
197 * don't want to return in transactional state. This also ensures
198 * that flush_fp_to_thread won't set TIF_RESTORE_TM again.
199 */
200 regs->msr &= ~MSR_TS_MASK;
201
195 flush_fp_to_thread(current); 202 flush_fp_to_thread(current);
196 203
197#ifdef CONFIG_ALTIVEC 204#ifdef CONFIG_ALTIVEC
@@ -749,13 +756,6 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
749 756
750 /* Make sure signal handler doesn't get spurious FP exceptions */ 757 /* Make sure signal handler doesn't get spurious FP exceptions */
751 current->thread.fp_state.fpscr = 0; 758 current->thread.fp_state.fpscr = 0;
752#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
753 /* Remove TM bits from thread's MSR. The MSR in the sigcontext
754 * just indicates to userland that we were doing a transaction, but we
755 * don't want to return in transactional state:
756 */
757 regs->msr &= ~MSR_TS_MASK;
758#endif
759 759
760 /* Set up to return from userspace. */ 760 /* Set up to return from userspace. */
761 if (vdso64_rt_sigtramp && current->mm->context.vdso_base) { 761 if (vdso64_rt_sigtramp && current->mm->context.vdso_base) {
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 330841766b09..26e1358ff0bc 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1399,7 +1399,6 @@ void fp_unavailable_tm(struct pt_regs *regs)
1399 1399
1400 TM_DEBUG("FP Unavailable trap whilst transactional at 0x%lx, MSR=%lx\n", 1400 TM_DEBUG("FP Unavailable trap whilst transactional at 0x%lx, MSR=%lx\n",
1401 regs->nip, regs->msr); 1401 regs->nip, regs->msr);
1402 tm_enable();
1403 1402
1404 /* We can only have got here if the task started using FP after 1403 /* We can only have got here if the task started using FP after
1405 * beginning the transaction. So, the transactional regs are just a 1404 * beginning the transaction. So, the transactional regs are just a
@@ -1408,8 +1407,7 @@ void fp_unavailable_tm(struct pt_regs *regs)
1408 * transaction, and probably retry but now with FP enabled. So the 1407 * transaction, and probably retry but now with FP enabled. So the
1409 * checkpointed FP registers need to be loaded. 1408 * checkpointed FP registers need to be loaded.
1410 */ 1409 */
1411 tm_reclaim(&current->thread, current->thread.regs->msr, 1410 tm_reclaim_current(TM_CAUSE_FAC_UNAV);
1412 TM_CAUSE_FAC_UNAV);
1413 /* Reclaim didn't save out any FPRs to transact_fprs. */ 1411 /* Reclaim didn't save out any FPRs to transact_fprs. */
1414 1412
1415 /* Enable FP for the task: */ 1413 /* Enable FP for the task: */
@@ -1432,9 +1430,7 @@ void altivec_unavailable_tm(struct pt_regs *regs)
1432 TM_DEBUG("Vector Unavailable trap whilst transactional at 0x%lx," 1430 TM_DEBUG("Vector Unavailable trap whilst transactional at 0x%lx,"
1433 "MSR=%lx\n", 1431 "MSR=%lx\n",
1434 regs->nip, regs->msr); 1432 regs->nip, regs->msr);
1435 tm_enable(); 1433 tm_reclaim_current(TM_CAUSE_FAC_UNAV);
1436 tm_reclaim(&current->thread, current->thread.regs->msr,
1437 TM_CAUSE_FAC_UNAV);
1438 regs->msr |= MSR_VEC; 1434 regs->msr |= MSR_VEC;
1439 tm_recheckpoint(&current->thread, regs->msr); 1435 tm_recheckpoint(&current->thread, regs->msr);
1440 current->thread.used_vr = 1; 1436 current->thread.used_vr = 1;
@@ -1455,10 +1451,8 @@ void vsx_unavailable_tm(struct pt_regs *regs)
1455 "MSR=%lx\n", 1451 "MSR=%lx\n",
1456 regs->nip, regs->msr); 1452 regs->nip, regs->msr);
1457 1453
1458 tm_enable();
1459 /* This reclaims FP and/or VR regs if they're already enabled */ 1454 /* This reclaims FP and/or VR regs if they're already enabled */
1460 tm_reclaim(&current->thread, current->thread.regs->msr, 1455 tm_reclaim_current(TM_CAUSE_FAC_UNAV);
1461 TM_CAUSE_FAC_UNAV);
1462 1456
1463 regs->msr |= MSR_VEC | MSR_FP | current->thread.fpexc_mode | 1457 regs->msr |= MSR_VEC | MSR_FP | current->thread.fpexc_mode |
1464 MSR_VSX; 1458 MSR_VSX;
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S
index 0458a9aaba9d..74f8050518d6 100644
--- a/arch/powerpc/kernel/vector.S
+++ b/arch/powerpc/kernel/vector.S
@@ -37,6 +37,16 @@ _GLOBAL(do_load_up_transact_altivec)
37#endif 37#endif
38 38
39/* 39/*
40 * Enable use of VMX/Altivec for the caller.
41 */
42_GLOBAL(vec_enable)
43 mfmsr r3
44 oris r3,r3,MSR_VEC@h
45 MTMSRD(r3)
46 isync
47 blr
48
49/*
40 * Load state from memory into VMX registers including VSCR. 50 * Load state from memory into VMX registers including VSCR.
41 * Assumes the caller has enabled VMX in the MSR. 51 * Assumes the caller has enabled VMX in the MSR.
42 */ 52 */