Skip to content

Commit bc2a940

Browse files
mikeyozbenh
authored andcommitted
powerpc: Hook in new transactional memory code
This hooks the new transactional memory code into context switching, FP/VMX/VMX unavailable and exception return. Signed-off-by: Matt Evans <[email protected]> Signed-off-by: Michael Neuling <[email protected]> Signed-off-by: Benjamin Herrenschmidt <[email protected]>
1 parent f54db64 commit bc2a940

File tree

4 files changed

+115
-4
lines changed

4 files changed

+115
-4
lines changed

arch/powerpc/kernel/exceptions-64s.S

+54-2
Original file line numberDiff line numberDiff line change
@@ -1176,18 +1176,52 @@ fp_unavailable_common:
11761176
addi r3,r1,STACK_FRAME_OVERHEAD
11771177
bl .kernel_fp_unavailable_exception
11781178
BUG_OPCODE
1179-
1: bl .load_up_fpu
1179+
1:
1180+
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1181+
BEGIN_FTR_SECTION
1182+
/* Test if 2 TM state bits are zero. If non-zero (ie. userspace was in
1183+
* transaction), go do TM stuff
1184+
*/
1185+
rldicl. r0, r12, (64-MSR_TS_LG), (64-2)
1186+
bne- 2f
1187+
END_FTR_SECTION_IFSET(CPU_FTR_TM)
1188+
#endif
1189+
bl .load_up_fpu
11801190
b fast_exception_return
1181-
1191+
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1192+
2: /* User process was in a transaction */
1193+
bl .save_nvgprs
1194+
DISABLE_INTS
1195+
addi r3,r1,STACK_FRAME_OVERHEAD
1196+
bl .fp_unavailable_tm
1197+
b .ret_from_except
1198+
#endif
11821199
.align 7
11831200
.globl altivec_unavailable_common
11841201
altivec_unavailable_common:
11851202
EXCEPTION_PROLOG_COMMON(0xf20, PACA_EXGEN)
11861203
#ifdef CONFIG_ALTIVEC
11871204
BEGIN_FTR_SECTION
11881205
beq 1f
1206+
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1207+
BEGIN_FTR_SECTION_NESTED(69)
1208+
/* Test if 2 TM state bits are zero. If non-zero (ie. userspace was in
1209+
* transaction), go do TM stuff
1210+
*/
1211+
rldicl. r0, r12, (64-MSR_TS_LG), (64-2)
1212+
bne- 2f
1213+
END_FTR_SECTION_NESTED(CPU_FTR_TM, CPU_FTR_TM, 69)
1214+
#endif
11891215
bl .load_up_altivec
11901216
b fast_exception_return
1217+
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1218+
2: /* User process was in a transaction */
1219+
bl .save_nvgprs
1220+
DISABLE_INTS
1221+
addi r3,r1,STACK_FRAME_OVERHEAD
1222+
bl .altivec_unavailable_tm
1223+
b .ret_from_except
1224+
#endif
11911225
1:
11921226
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
11931227
#endif
@@ -1204,7 +1238,24 @@ vsx_unavailable_common:
12041238
#ifdef CONFIG_VSX
12051239
BEGIN_FTR_SECTION
12061240
beq 1f
1241+
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1242+
BEGIN_FTR_SECTION_NESTED(69)
1243+
/* Test if 2 TM state bits are zero. If non-zero (ie. userspace was in
1244+
* transaction), go do TM stuff
1245+
*/
1246+
rldicl. r0, r12, (64-MSR_TS_LG), (64-2)
1247+
bne- 2f
1248+
END_FTR_SECTION_NESTED(CPU_FTR_TM, CPU_FTR_TM, 69)
1249+
#endif
12071250
b .load_up_vsx
1251+
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1252+
2: /* User process was in a transaction */
1253+
bl .save_nvgprs
1254+
DISABLE_INTS
1255+
addi r3,r1,STACK_FRAME_OVERHEAD
1256+
bl .vsx_unavailable_tm
1257+
b .ret_from_except
1258+
#endif
12081259
1:
12091260
END_FTR_SECTION_IFSET(CPU_FTR_VSX)
12101261
#endif
@@ -1219,6 +1270,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
12191270
tm_unavailable_common:
12201271
EXCEPTION_PROLOG_COMMON(0xf60, PACA_EXGEN)
12211272
bl .save_nvgprs
1273+
DISABLE_INTS
12221274
addi r3,r1,STACK_FRAME_OVERHEAD
12231275
bl .tm_unavailable_exception
12241276
b .ret_from_except

arch/powerpc/kernel/process.c

+13-2
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ static inline void tm_reclaim_task(struct task_struct *tsk)
515515
tm_save_sprs(thr);
516516
}
517517

518-
static inline void __maybe_unused tm_recheckpoint_new_task(struct task_struct *new)
518+
static inline void tm_recheckpoint_new_task(struct task_struct *new)
519519
{
520520
unsigned long msr;
521521

@@ -590,6 +590,8 @@ struct task_struct *__switch_to(struct task_struct *prev,
590590
struct ppc64_tlb_batch *batch;
591591
#endif
592592

593+
__switch_to_tm(prev);
594+
593595
#ifdef CONFIG_SMP
594596
/* avoid complexity of lazy save/restore of fpu
595597
* by just saving it every time we switch out if
@@ -705,6 +707,9 @@ struct task_struct *__switch_to(struct task_struct *prev,
705707
* of sync. Hard disable here.
706708
*/
707709
hard_irq_disable();
710+
711+
tm_recheckpoint_new_task(new);
712+
708713
last = _switch(old_thread, new_thread);
709714

710715
#ifdef CONFIG_PPC_BOOK3S_64
@@ -1080,7 +1085,6 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
10801085
regs->msr = MSR_USER32;
10811086
}
10821087
#endif
1083-
10841088
discard_lazy_cpu_state();
10851089
#ifdef CONFIG_VSX
10861090
current->thread.used_vsr = 0;
@@ -1100,6 +1104,13 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
11001104
current->thread.spefscr = 0;
11011105
current->thread.used_spe = 0;
11021106
#endif /* CONFIG_SPE */
1107+
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1108+
if (cpu_has_feature(CPU_FTR_TM))
1109+
regs->msr |= MSR_TM;
1110+
current->thread.tm_tfhar = 0;
1111+
current->thread.tm_texasr = 0;
1112+
current->thread.tm_tfiar = 0;
1113+
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
11031114
}
11041115

11051116
#define PR_FP_ALL_EXCEPT (PR_FP_EXC_DIV | PR_FP_EXC_OVF | PR_FP_EXC_UND \

arch/powerpc/kernel/traps.c

+32
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,38 @@ void __kprobes program_check_exception(struct pt_regs *regs)
10291029
_exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
10301030
return;
10311031
}
1032+
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1033+
if (reason & REASON_TM) {
1034+
/* This is a TM "Bad Thing Exception" program check.
1035+
* This occurs when:
1036+
* - An rfid/hrfid/mtmsrd attempts to cause an illegal
1037+
* transition in TM states.
1038+
* - A trechkpt is attempted when transactional.
1039+
* - A treclaim is attempted when non transactional.
1040+
* - A tend is illegally attempted.
1041+
* - writing a TM SPR when transactional.
1042+
*/
1043+
if (!user_mode(regs) &&
1044+
report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) {
1045+
regs->nip += 4;
1046+
return;
1047+
}
1048+
/* If usermode caused this, it's done something illegal and
1049+
* gets a SIGILL slap on the wrist. We call it an illegal
1050+
* operand to distinguish from the instruction just being bad
1051+
* (e.g. executing a 'tend' on a CPU without TM!); it's an
1052+
* illegal /placement/ of a valid instruction.
1053+
*/
1054+
if (user_mode(regs)) {
1055+
_exception(SIGILL, regs, ILL_ILLOPN, regs->nip);
1056+
return;
1057+
} else {
1058+
printk(KERN_EMERG "Unexpected TM Bad Thing exception "
1059+
"at %lx (msr 0x%x)\n", regs->nip, reason);
1060+
die("Unrecoverable exception", regs, SIGABRT);
1061+
}
1062+
}
1063+
#endif
10321064

10331065
/* We restore the interrupt state now */
10341066
if (!arch_irq_disabled_regs(regs))

arch/powerpc/mm/hash_utils_64.c

+16
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include <asm/code-patching.h>
5656
#include <asm/fadump.h>
5757
#include <asm/firmware.h>
58+
#include <asm/tm.h>
5859

5960
#ifdef DEBUG
6061
#define DBG(fmt...) udbg_printf(fmt)
@@ -1171,6 +1172,21 @@ void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize,
11711172
DBG_LOW(" sub %ld: hash=%lx, hidx=%lx\n", index, slot, hidx);
11721173
ppc_md.hpte_invalidate(slot, vpn, psize, ssize, local);
11731174
} pte_iterate_hashed_end();
1175+
1176+
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
1177+
/* Transactions are not aborted by tlbiel, only tlbie.
1178+
* Without, syncing a page back to a block device w/ PIO could pick up
1179+
* transactional data (bad!) so we force an abort here. Before the
1180+
* sync the page will be made read-only, which will flush_hash_page.
1181+
* BIG ISSUE here: if the kernel uses a page from userspace without
1182+
* unmapping it first, it may see the speculated version.
1183+
*/
1184+
if (local && cpu_has_feature(CPU_FTR_TM) &&
1185+
MSR_TM_ACTIVE(current->thread.regs->msr)) {
1186+
tm_enable();
1187+
tm_abort(TM_CAUSE_TLBI);
1188+
}
1189+
#endif
11741190
}
11751191

11761192
void flush_hash_range(unsigned long number, int local)

0 commit comments

Comments
 (0)