Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8b3c34cf authored by Michael Neuling's avatar Michael Neuling Committed by Benjamin Herrenschmidt
Browse files

powerpc: New macros for transactional memory support



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: default avatarMatt Evans <matt@ozlabs.org>
Signed-off-by: default avatarMichael Neuling <mikey@neuling.org>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent f4c3aff2
Loading
Loading
Loading
Loading
+83 −0
Original line number Diff line number Diff line
@@ -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)
+1 −0
Original line number Diff line number Diff line
@@ -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 */
+23 −0
Original line number Diff line number Diff line
@@ -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));
+12 −0
Original line number Diff line number Diff line
@@ -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)

/*
+7 −0
Original line number Diff line number Diff line
@@ -57,6 +57,13 @@
#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
Loading