powerpc: New macros for transactional memory support
authorMichael Neuling <mikey@neuling.org>
Wed, 13 Feb 2013 16:21:32 +0000 (16:21 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 15 Feb 2013 05:58:50 +0000 (16:58 +1100)
This adds new macros for saving and restoring checkpointed architected state
from and to the thread_struct.

It also adds some debugging macros for when your brain explodes trying to debug
your transactional memory enabled kernel.

Signed-off-by: Matt Evans <matt@ozlabs.org>
Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/include/asm/ppc_asm.h
arch/powerpc/include/asm/processor.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/fpu.S
arch/powerpc/kernel/process.c
arch/powerpc/kernel/traps.c

index c2d0e58aba3169d81052c7e2a47847eb986f752b..54219cea9e88bbdce78518e74dcc022e1779c2be 100644 (file)
@@ -123,6 +123,89 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
 #define REST_16VRS(n,b,base)   REST_8VRS(n,b,base); REST_8VRS(n+8,b,base)
 #define REST_32VRS(n,b,base)   REST_16VRS(n,b,base); REST_16VRS(n+16,b,base)
 
+/* Save/restore FPRs, VRs and VSRs from their checkpointed backups in
+ * thread_struct:
+ */
+#define SAVE_FPR_TRANSACT(n, base)     stfd n,THREAD_TRANSACT_FPR0+    \
+                                       8*TS_FPRWIDTH*(n)(base)
+#define SAVE_2FPRS_TRANSACT(n, base)   SAVE_FPR_TRANSACT(n, base);     \
+                                       SAVE_FPR_TRANSACT(n+1, base)
+#define SAVE_4FPRS_TRANSACT(n, base)   SAVE_2FPRS_TRANSACT(n, base);   \
+                                       SAVE_2FPRS_TRANSACT(n+2, base)
+#define SAVE_8FPRS_TRANSACT(n, base)   SAVE_4FPRS_TRANSACT(n, base);   \
+                                       SAVE_4FPRS_TRANSACT(n+4, base)
+#define SAVE_16FPRS_TRANSACT(n, base)  SAVE_8FPRS_TRANSACT(n, base);   \
+                                       SAVE_8FPRS_TRANSACT(n+8, base)
+#define SAVE_32FPRS_TRANSACT(n, base)  SAVE_16FPRS_TRANSACT(n, base);  \
+                                       SAVE_16FPRS_TRANSACT(n+16, base)
+
+#define REST_FPR_TRANSACT(n, base)     lfd     n,THREAD_TRANSACT_FPR0+ \
+                                       8*TS_FPRWIDTH*(n)(base)
+#define REST_2FPRS_TRANSACT(n, base)   REST_FPR_TRANSACT(n, base);     \
+                                       REST_FPR_TRANSACT(n+1, base)
+#define REST_4FPRS_TRANSACT(n, base)   REST_2FPRS_TRANSACT(n, base);   \
+                                       REST_2FPRS_TRANSACT(n+2, base)
+#define REST_8FPRS_TRANSACT(n, base)   REST_4FPRS_TRANSACT(n, base);   \
+                                       REST_4FPRS_TRANSACT(n+4, base)
+#define REST_16FPRS_TRANSACT(n, base)  REST_8FPRS_TRANSACT(n, base);   \
+                                       REST_8FPRS_TRANSACT(n+8, base)
+#define REST_32FPRS_TRANSACT(n, base)  REST_16FPRS_TRANSACT(n, base);  \
+                                       REST_16FPRS_TRANSACT(n+16, base)
+
+
+#define SAVE_VR_TRANSACT(n,b,base)     li b,THREAD_TRANSACT_VR0+(16*(n)); \
+                                       stvx n,b,base
+#define SAVE_2VRS_TRANSACT(n,b,base)   SAVE_VR_TRANSACT(n,b,base);     \
+                                       SAVE_VR_TRANSACT(n+1,b,base)
+#define SAVE_4VRS_TRANSACT(n,b,base)   SAVE_2VRS_TRANSACT(n,b,base);   \
+                                       SAVE_2VRS_TRANSACT(n+2,b,base)
+#define SAVE_8VRS_TRANSACT(n,b,base)   SAVE_4VRS_TRANSACT(n,b,base);   \
+                                       SAVE_4VRS_TRANSACT(n+4,b,base)
+#define SAVE_16VRS_TRANSACT(n,b,base)  SAVE_8VRS_TRANSACT(n,b,base);   \
+                                       SAVE_8VRS_TRANSACT(n+8,b,base)
+#define SAVE_32VRS_TRANSACT(n,b,base)  SAVE_16VRS_TRANSACT(n,b,base);  \
+                                       SAVE_16VRS_TRANSACT(n+16,b,base)
+
+#define REST_VR_TRANSACT(n,b,base)     li b,THREAD_TRANSACT_VR0+(16*(n)); \
+                                       lvx n,b,base
+#define REST_2VRS_TRANSACT(n,b,base)   REST_VR_TRANSACT(n,b,base);     \
+                                       REST_VR_TRANSACT(n+1,b,base)
+#define REST_4VRS_TRANSACT(n,b,base)   REST_2VRS_TRANSACT(n,b,base);   \
+                                       REST_2VRS_TRANSACT(n+2,b,base)
+#define REST_8VRS_TRANSACT(n,b,base)   REST_4VRS_TRANSACT(n,b,base);   \
+                                       REST_4VRS_TRANSACT(n+4,b,base)
+#define REST_16VRS_TRANSACT(n,b,base)  REST_8VRS_TRANSACT(n,b,base);   \
+                                       REST_8VRS_TRANSACT(n+8,b,base)
+#define REST_32VRS_TRANSACT(n,b,base)  REST_16VRS_TRANSACT(n,b,base);  \
+                                       REST_16VRS_TRANSACT(n+16,b,base)
+
+
+#define SAVE_VSR_TRANSACT(n,b,base)    li b,THREAD_TRANSACT_VSR0+(16*(n)); \
+                                       STXVD2X(n,R##base,R##b)
+#define SAVE_2VSRS_TRANSACT(n,b,base)  SAVE_VSR_TRANSACT(n,b,base);    \
+                                       SAVE_VSR_TRANSACT(n+1,b,base)
+#define SAVE_4VSRS_TRANSACT(n,b,base)  SAVE_2VSRS_TRANSACT(n,b,base);  \
+                                       SAVE_2VSRS_TRANSACT(n+2,b,base)
+#define SAVE_8VSRS_TRANSACT(n,b,base)  SAVE_4VSRS_TRANSACT(n,b,base);  \
+                                       SAVE_4VSRS_TRANSACT(n+4,b,base)
+#define SAVE_16VSRS_TRANSACT(n,b,base) SAVE_8VSRS_TRANSACT(n,b,base);  \
+                                       SAVE_8VSRS_TRANSACT(n+8,b,base)
+#define SAVE_32VSRS_TRANSACT(n,b,base) SAVE_16VSRS_TRANSACT(n,b,base); \
+                                       SAVE_16VSRS_TRANSACT(n+16,b,base)
+
+#define REST_VSR_TRANSACT(n,b,base)    li b,THREAD_TRANSACT_VSR0+(16*(n)); \
+                                       LXVD2X(n,R##base,R##b)
+#define REST_2VSRS_TRANSACT(n,b,base)  REST_VSR_TRANSACT(n,b,base);    \
+                                       REST_VSR_TRANSACT(n+1,b,base)
+#define REST_4VSRS_TRANSACT(n,b,base)  REST_2VSRS_TRANSACT(n,b,base);  \
+                                       REST_2VSRS_TRANSACT(n+2,b,base)
+#define REST_8VSRS_TRANSACT(n,b,base)  REST_4VSRS_TRANSACT(n,b,base);  \
+                                       REST_4VSRS_TRANSACT(n+4,b,base)
+#define REST_16VSRS_TRANSACT(n,b,base) REST_8VSRS_TRANSACT(n,b,base);  \
+                                       REST_8VSRS_TRANSACT(n+8,b,base)
+#define REST_32VSRS_TRANSACT(n,b,base) REST_16VSRS_TRANSACT(n,b,base); \
+                                       REST_16VSRS_TRANSACT(n+16,b,base)
+
 /* Save the lower 32 VSRs in the thread VSR region */
 #define SAVE_VSR(n,b,base)     li b,THREAD_VSR0+(16*(n));  STXVD2X(n,R##base,R##b)
 #define SAVE_2VSRS(n,b,base)   SAVE_VSR(n,b,base); SAVE_VSR(n+1,b,base)
index fc41ab3aa114f53f7e17961d26f9e43c2bedac27..7ff9eaa3ea6cf14531c154211b49770c6aec50a0 100644 (file)
@@ -152,6 +152,7 @@ typedef struct {
 #define TS_FPROFFSET 0
 #define TS_VSRLOWOFFSET 1
 #define TS_FPR(i) fpr[i][TS_FPROFFSET]
+#define TS_TRANS_FPR(i) transact_fpr[i][TS_FPROFFSET]
 
 struct thread_struct {
        unsigned long   ksp;            /* Kernel stack pointer */
index e295a09b1f061ec29d6448709d6a677578d9f351..0fdc97496d7cd87ee4c4d7755687e7bc67a806e7 100644 (file)
@@ -125,6 +125,29 @@ int main(void)
 #ifdef CONFIG_PPC_BOOK3S_64
        DEFINE(THREAD_TAR, offsetof(struct thread_struct, tar));
 #endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       DEFINE(THREAD_TM_TFHAR, offsetof(struct thread_struct, tm_tfhar));
+       DEFINE(THREAD_TM_TEXASR, offsetof(struct thread_struct, tm_texasr));
+       DEFINE(THREAD_TM_TFIAR, offsetof(struct thread_struct, tm_tfiar));
+       DEFINE(PT_CKPT_REGS, offsetof(struct thread_struct, ckpt_regs));
+       DEFINE(THREAD_TRANSACT_VR0, offsetof(struct thread_struct,
+                                        transact_vr[0]));
+       DEFINE(THREAD_TRANSACT_VSCR, offsetof(struct thread_struct,
+                                         transact_vscr));
+       DEFINE(THREAD_TRANSACT_VRSAVE, offsetof(struct thread_struct,
+                                           transact_vrsave));
+       DEFINE(THREAD_TRANSACT_FPR0, offsetof(struct thread_struct,
+                                         transact_fpr[0]));
+       DEFINE(THREAD_TRANSACT_FPSCR, offsetof(struct thread_struct,
+                                          transact_fpscr));
+#ifdef CONFIG_VSX
+       DEFINE(THREAD_TRANSACT_VSR0, offsetof(struct thread_struct,
+                                         transact_fpr[0]));
+#endif
+       /* Local pt_regs on stack for Transactional Memory funcs. */
+       DEFINE(TM_FRAME_SIZE, STACK_FRAME_OVERHEAD +
+              sizeof(struct pt_regs) + 16);
+#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
 
        DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
        DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
index e0ada05f2df31f16f61e07259bce6d4549d8aa25..adb15519539417207c56136d2843cd0b007322a7 100644 (file)
@@ -35,6 +35,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX);                                  \
 2:     REST_32VSRS(n,c,base);                                          \
 3:
 
+#define __REST_32FPVSRS_TRANSACT(n,c,base)                             \
+BEGIN_FTR_SECTION                                                      \
+       b       2f;                                                     \
+END_FTR_SECTION_IFSET(CPU_FTR_VSX);                                    \
+       REST_32FPRS_TRANSACT(n,base);                                   \
+       b       3f;                                                     \
+2:     REST_32VSRS_TRANSACT(n,c,base);                                 \
+3:
+
 #define __SAVE_32FPVSRS(n,c,base)                                      \
 BEGIN_FTR_SECTION                                                      \
        b       2f;                                                     \
@@ -45,9 +54,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX);                                  \
 3:
 #else
 #define __REST_32FPVSRS(n,b,base)      REST_32FPRS(n, base)
+#define __REST_32FPVSRS_TRANSACT(n,b,base)     REST_32FPRS(n, base)
 #define __SAVE_32FPVSRS(n,b,base)      SAVE_32FPRS(n, base)
 #endif
 #define REST_32FPVSRS(n,c,base) __REST_32FPVSRS(n,__REG_##c,__REG_##base)
+#define REST_32FPVSRS_TRANSACT(n,c,base) \
+       __REST_32FPVSRS_TRANSACT(n,__REG_##c,__REG_##base)
 #define SAVE_32FPVSRS(n,c,base) __SAVE_32FPVSRS(n,__REG_##c,__REG_##base)
 
 /*
index 96e31de89b431663ba4341422c4f0bf7f4c61ee0..b0a0321e4bb6370c8b50fac1b7858303c47fb51d 100644 (file)
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
 
+/* Transactional Memory debug */
+#ifdef TM_DEBUG_SW
+#define TM_DEBUG(x...) printk(KERN_INFO x)
+#else
+#define TM_DEBUG(x...) do { } while(0)
+#endif
+
 extern unsigned long _get_SP(void);
 
 #ifndef CONFIG_SMP
index a008cf5c0fcec6f8073f28a935c40f1ef268249a..bd5de5deaf5157b1991b5b970427c691539a1287 100644 (file)
@@ -78,6 +78,13 @@ EXPORT_SYMBOL(__debugger_break_match);
 EXPORT_SYMBOL(__debugger_fault_handler);
 #endif
 
+/* Transactional Memory trap debug */
+#ifdef TM_DEBUG_SW
+#define TM_DEBUG(x...) printk(KERN_INFO x)
+#else
+#define TM_DEBUG(x...) do { } while(0)
+#endif
+
 /*
  * Trap & Exception support
  */
@@ -350,6 +357,7 @@ static inline int check_io_access(struct pt_regs *regs)
    exception is in the MSR. */
 #define get_reason(regs)       ((regs)->msr)
 #define get_mc_reason(regs)    ((regs)->msr)
+#define REASON_TM              0x200000
 #define REASON_FP              0x100000
 #define REASON_ILLEGAL         0x80000
 #define REASON_PRIVILEGED      0x40000