Skip to content

Commit 5d176f7

Browse files
cyrilbur-ibmmpe
authored andcommitted
powerpc: tm: Enable transactional memory (TM) lazily for userspace
Currently the MSR TM bit is always set if the hardware is TM capable. This adds extra overhead as it means the TM SPRS (TFHAR, TEXASR and TFAIR) must be swapped for each process regardless of if they use TM. For processes that don't use TM the TM MSR bit can be turned off allowing the kernel to avoid the expensive swap of the TM registers. A TM unavailable exception will occur if a thread does use TM and the kernel will enable MSR_TM and leave it so for some time afterwards. Signed-off-by: Cyril Bur <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent 172f7aa commit 5d176f7

File tree

3 files changed

+33
-5
lines changed

3 files changed

+33
-5
lines changed

arch/powerpc/include/asm/processor.h

+1
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ struct thread_struct {
257257
int used_spe; /* set if process has used spe */
258258
#endif /* CONFIG_SPE */
259259
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
260+
u8 load_tm;
260261
u64 tm_tfhar; /* Transaction fail handler addr */
261262
u64 tm_texasr; /* Transaction exception & summary */
262263
u64 tm_tfiar; /* Transaction fail instr address reg */

arch/powerpc/kernel/process.c

+23-5
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,12 @@ static inline bool hw_brk_match(struct arch_hw_breakpoint *a,
812812
}
813813

814814
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
815+
816+
static inline bool tm_enabled(struct task_struct *tsk)
817+
{
818+
return tsk && tsk->thread.regs && (tsk->thread.regs->msr & MSR_TM);
819+
}
820+
815821
static void tm_reclaim_thread(struct thread_struct *thr,
816822
struct thread_info *ti, uint8_t cause)
817823
{
@@ -892,6 +898,9 @@ void tm_recheckpoint(struct thread_struct *thread,
892898
{
893899
unsigned long flags;
894900

901+
if (!(thread->regs->msr & MSR_TM))
902+
return;
903+
895904
/* We really can't be interrupted here as the TEXASR registers can't
896905
* change and later in the trecheckpoint code, we have a userspace R1.
897906
* So let's hard disable over this region.
@@ -924,7 +933,7 @@ static inline void tm_recheckpoint_new_task(struct task_struct *new)
924933
* unavailable later, we are unable to determine which set of FP regs
925934
* need to be restored.
926935
*/
927-
if (!new->thread.regs)
936+
if (!tm_enabled(new))
928937
return;
929938

930939
if (!MSR_TM_ACTIVE(new->thread.regs->msr)){
@@ -955,8 +964,16 @@ static inline void __switch_to_tm(struct task_struct *prev,
955964
struct task_struct *new)
956965
{
957966
if (cpu_has_feature(CPU_FTR_TM)) {
958-
tm_enable();
959-
tm_reclaim_task(prev);
967+
if (tm_enabled(prev) || tm_enabled(new))
968+
tm_enable();
969+
970+
if (tm_enabled(prev)) {
971+
prev->thread.load_tm++;
972+
tm_reclaim_task(prev);
973+
if (!MSR_TM_ACTIVE(prev->thread.regs->msr) && prev->thread.load_tm == 0)
974+
prev->thread.regs->msr &= ~MSR_TM;
975+
}
976+
960977
tm_recheckpoint_new_task(new);
961978
}
962979
}
@@ -1393,6 +1410,9 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
13931410
* transitions the CPU out of TM mode. Hence we need to call
13941411
* tm_recheckpoint_new_task() (on the same task) to restore the
13951412
* checkpointed state back and the TM mode.
1413+
*
1414+
* Can't pass dst because it isn't ready. Doesn't matter, passing
1415+
* dst is only important for __switch_to()
13961416
*/
13971417
__switch_to_tm(src, src);
13981418

@@ -1636,8 +1656,6 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
16361656
current->thread.used_spe = 0;
16371657
#endif /* CONFIG_SPE */
16381658
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1639-
if (cpu_has_feature(CPU_FTR_TM))
1640-
regs->msr |= MSR_TM;
16411659
current->thread.tm_tfhar = 0;
16421660
current->thread.tm_texasr = 0;
16431661
current->thread.tm_tfiar = 0;

arch/powerpc/kernel/traps.c

+9
Original file line numberDiff line numberDiff line change
@@ -1392,6 +1392,15 @@ void vsx_unavailable_exception(struct pt_regs *regs)
13921392
#ifdef CONFIG_PPC64
13931393
static void tm_unavailable(struct pt_regs *regs)
13941394
{
1395+
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1396+
if (user_mode(regs)) {
1397+
current->thread.load_tm++;
1398+
regs->msr |= MSR_TM;
1399+
tm_enable();
1400+
tm_restore_sprs(&current->thread);
1401+
return;
1402+
}
1403+
#endif
13951404
pr_emerg("Unrecoverable TM Unavailable Exception "
13961405
"%lx at %lx\n", regs->trap, regs->nip);
13971406
die("Unrecoverable TM Unavailable Exception", regs, SIGABRT);

0 commit comments

Comments
 (0)