aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/powerpc/transactional_memory.txt7
-rw-r--r--arch/powerpc/include/asm/reg.h2
-rw-r--r--arch/powerpc/kernel/traps.c29
3 files changed, 36 insertions, 2 deletions
diff --git a/Documentation/powerpc/transactional_memory.txt b/Documentation/powerpc/transactional_memory.txt
index 84e04a0db0f8..c54bf3127651 100644
--- a/Documentation/powerpc/transactional_memory.txt
+++ b/Documentation/powerpc/transactional_memory.txt
@@ -161,9 +161,12 @@ kernel aborted a transaction:
161 transactions for consistency will use this. 161 transactions for consistency will use this.
162 TM_CAUSE_SIGNAL Signal delivered. 162 TM_CAUSE_SIGNAL Signal delivered.
163 TM_CAUSE_MISC Currently unused. 163 TM_CAUSE_MISC Currently unused.
164 TM_CAUSE_ALIGNMENT Alignment fault.
165 TM_CAUSE_EMULATE Emulation that touched memory.
164 166
165These can be checked by the user program's abort handler as TEXASR[0:7]. 167These can be checked by the user program's abort handler as TEXASR[0:7]. If
166 168bit 7 is set, it indicates that the error is consider persistent. For example
169a TM_CAUSE_ALIGNMENT will be persistent while a TM_CAUSE_RESCHED will not.q
167 170
168GDB 171GDB
169=== 172===
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 8f6a94b2dc99..d0528e0d6db8 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -122,6 +122,8 @@
122#define TM_CAUSE_SYSCALL 0xd8 /* future use */ 122#define TM_CAUSE_SYSCALL 0xd8 /* future use */
123#define TM_CAUSE_MISC 0xd6 /* future use */ 123#define TM_CAUSE_MISC 0xd6 /* future use */
124#define TM_CAUSE_SIGNAL 0xd4 124#define TM_CAUSE_SIGNAL 0xd4
125#define TM_CAUSE_ALIGNMENT 0xd2
126#define TM_CAUSE_EMULATE 0xd0
125 127
126#if defined(CONFIG_PPC_BOOK3S_64) 128#if defined(CONFIG_PPC_BOOK3S_64)
127#define MSR_64BIT MSR_SF 129#define MSR_64BIT MSR_SF
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index a7a648f6b750..f18c79c324ef 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -53,6 +53,7 @@
53#ifdef CONFIG_PPC64 53#ifdef CONFIG_PPC64
54#include <asm/firmware.h> 54#include <asm/firmware.h>
55#include <asm/processor.h> 55#include <asm/processor.h>
56#include <asm/tm.h>
56#endif 57#endif
57#include <asm/kexec.h> 58#include <asm/kexec.h>
58#include <asm/ppc-opcode.h> 59#include <asm/ppc-opcode.h>
@@ -932,6 +933,28 @@ static int emulate_isel(struct pt_regs *regs, u32 instword)
932 return 0; 933 return 0;
933} 934}
934 935
936#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
937static inline bool tm_abort_check(struct pt_regs *regs, int cause)
938{
939 /* If we're emulating a load/store in an active transaction, we cannot
940 * emulate it as the kernel operates in transaction suspended context.
941 * We need to abort the transaction. This creates a persistent TM
942 * abort so tell the user what caused it with a new code.
943 */
944 if (MSR_TM_TRANSACTIONAL(regs->msr)) {
945 tm_enable();
946 tm_abort(cause);
947 return true;
948 }
949 return false;
950}
951#else
952static inline bool tm_abort_check(struct pt_regs *regs, int reason)
953{
954 return false;
955}
956#endif
957
935static int emulate_instruction(struct pt_regs *regs) 958static int emulate_instruction(struct pt_regs *regs)
936{ 959{
937 u32 instword; 960 u32 instword;
@@ -971,6 +994,9 @@ static int emulate_instruction(struct pt_regs *regs)
971 994
972 /* Emulate load/store string insn. */ 995 /* Emulate load/store string insn. */
973 if ((instword & PPC_INST_STRING_GEN_MASK) == PPC_INST_STRING) { 996 if ((instword & PPC_INST_STRING_GEN_MASK) == PPC_INST_STRING) {
997 if (tm_abort_check(regs,
998 TM_CAUSE_EMULATE | TM_CAUSE_PERSISTENT))
999 return -EINVAL;
974 PPC_WARN_EMULATED(string, regs); 1000 PPC_WARN_EMULATED(string, regs);
975 return emulate_string_inst(regs, instword); 1001 return emulate_string_inst(regs, instword);
976 } 1002 }
@@ -1148,6 +1174,9 @@ void alignment_exception(struct pt_regs *regs)
1148 if (!arch_irq_disabled_regs(regs)) 1174 if (!arch_irq_disabled_regs(regs))
1149 local_irq_enable(); 1175 local_irq_enable();
1150 1176
1177 if (tm_abort_check(regs, TM_CAUSE_ALIGNMENT | TM_CAUSE_PERSISTENT))
1178 goto bail;
1179
1151 /* we don't implement logging of alignment exceptions */ 1180 /* we don't implement logging of alignment exceptions */
1152 if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS)) 1181 if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
1153 fixed = fix_alignment(regs); 1182 fixed = fix_alignment(regs);