Patchwork powerpc: Add support for context switching the TAR register

login
register
mail settings
Submitter Ian Munsie
Date Dec. 19, 2012, 6:03 a.m.
Message ID <1355897036-13917-1-git-send-email-imunsie@au1.ibm.com>
Download mbox | patch
Permalink /patch/207243/
State Changes Requested
Headers show

Comments

Ian Munsie - Dec. 19, 2012, 6:03 a.m.
From: Ian Munsie <imunsie@au1.ibm.com>

This patch adds support for enabling and context switching the Target
Address Register in Power8. The TAR is a new special purpose register
that can be used for computed branches with the bctar[l] (branch
conditional to TAR) instruction in the same manner as the count and link
registers.

Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
Signed-off-by: Matt Evans <matt@ozlabs.org>
---
 arch/powerpc/include/asm/cputable.h   |    3 ++-
 arch/powerpc/include/asm/processor.h  |    1 +
 arch/powerpc/include/asm/reg.h        |    3 +++
 arch/powerpc/kernel/asm-offsets.c     |    1 +
 arch/powerpc/kernel/cpu_setup_power.S |    7 +++++++
 arch/powerpc/kernel/entry_64.S        |   16 ++++++++++++++++
 6 files changed, 30 insertions(+), 1 deletion(-)
Kumar Gala - Dec. 19, 2012, 3:34 p.m.
On Dec 19, 2012, at 12:03 AM, Ian Munsie wrote:

> From: Ian Munsie <imunsie@au1.ibm.com>
> 
> This patch adds support for enabling and context switching the Target
> Address Register in Power8. The TAR is a new special purpose register
> that can be used for computed branches with the bctar[l] (branch
> conditional to TAR) instruction in the same manner as the count and link
> registers.
> 
> Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
> Signed-off-by: Matt Evans <matt@ozlabs.org>
> ---
> arch/powerpc/include/asm/cputable.h   |    3 ++-
> arch/powerpc/include/asm/processor.h  |    1 +
> arch/powerpc/include/asm/reg.h        |    3 +++
> arch/powerpc/kernel/asm-offsets.c     |    1 +
> arch/powerpc/kernel/cpu_setup_power.S |    7 +++++++
> arch/powerpc/kernel/entry_64.S        |   16 ++++++++++++++++
> 6 files changed, 30 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
> index 74458e69..cbbec56a 100644
> --- a/arch/powerpc/include/asm/cputable.h
> +++ b/arch/powerpc/include/asm/cputable.h
> @@ -172,6 +172,7 @@ extern const char *powerpc_base_platform;
> #define CPU_FTR_ICSWX			LONG_ASM_CONST(0x1000000000000000)
> #define CPU_FTR_VMX_COPY		LONG_ASM_CONST(0x2000000000000000)
> #define CPU_FTR_TM			LONG_ASM_CONST(0x4000000000000000)
> +#define CPU_FTR_BCTAR			LONG_ASM_CONST(0x8000000000000000)
> 
> #ifndef __ASSEMBLY__
> 
> @@ -417,7 +418,7 @@ extern const char *powerpc_base_platform;
> 	    CPU_FTR_DSCR | CPU_FTR_SAO  | \
> 	    CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
> 	    CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
> -	    CPU_FTR_DBELL | CPU_FTR_TM_COMP)
> +	    CPU_FTR_DBELL | CPU_FTR_TM_COMP | CPU_FTR_BCTAR)
> #define CPU_FTRS_CELL	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
> 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
> 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
> diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
> index 8b2bf7a..cbbd82d 100644
> --- a/arch/powerpc/include/asm/processor.h
> +++ b/arch/powerpc/include/asm/processor.h
> @@ -275,6 +275,7 @@ struct thread_struct {
> 	unsigned long	dscr;
> 	int		dscr_inherit;
> #endif
> +	unsigned long	tar;

This needs a #ifdef CONFIG_PPC64 and personally I'd rather it be a CONFIG_PPC_BOOK3S_64.  This will also ripple into other locations like asm-offsets.c.

> };
> 
> #define ARCH_MIN_TASKALIGN 16
> diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
> index 5c9fe38..1fa8a56 100644
> --- a/arch/powerpc/include/asm/reg.h
> +++ b/arch/powerpc/include/asm/reg.h
> @@ -257,6 +257,9 @@
> #define SPRN_HRMOR	0x139	/* Real mode offset register */
> #define SPRN_HSRR0	0x13A	/* Hypervisor Save/Restore 0 */
> #define SPRN_HSRR1	0x13B	/* Hypervisor Save/Restore 1 */
> +#define SPRN_FSCR	0x099	/* Facility Status & Control Register */
> +#define FSCR_TAR	(1<<8)	/* Enable Target Adress Register */
> +#define SPRN_TAR	0x32f	/* Target Address Register */
> #define SPRN_LPCR	0x13E	/* LPAR Control Register */
> #define   LPCR_VPM0	(1ul << (63-0))
> #define   LPCR_VPM1	(1ul << (63-1))
> diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
> index 42a4243..77e941e 100644
> --- a/arch/powerpc/kernel/asm-offsets.c
> +++ b/arch/powerpc/kernel/asm-offsets.c
> @@ -145,6 +145,7 @@ int main(void)
> 	DEFINE(TM_FRAME_SIZE, STACK_FRAME_OVERHEAD +
> 	       sizeof(struct pt_regs) + 16);
> #endif /* CONFIG_TRANSACTIONAL_MEM */
> +	DEFINE(THREAD_TAR, offsetof(struct thread_struct, tar));
> 
> 	DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
> 	DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
> diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S
> index 57cf140..d29facb 100644
> --- a/arch/powerpc/kernel/cpu_setup_power.S
> +++ b/arch/powerpc/kernel/cpu_setup_power.S
> @@ -56,6 +56,7 @@ _GLOBAL(__setup_cpu_power8)
> 	mfspr	r3,SPRN_LPCR
> 	oris	r3, r3, LPCR_AIL_3@h
> 	bl	__init_LPCR
> +	bl	__init_FSCR
> 	bl	__init_TLB
> 	mtlr	r11
> 	blr
> @@ -112,6 +113,12 @@ __init_LPCR:
> 	isync
> 	blr
> 
> +__init_FSCR:
> +	mfspr	r3,SPRN_FSCR
> +	ori	r3,r3,FSCR_TAR
> +	mtspr	SPRN_FSCR,r3
> +	blr
> +
> __init_TLB:
> 	/* Clear the TLB */
> 	li	r6,128
> diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
> index b3590c3..253885d 100644
> --- a/arch/powerpc/kernel/entry_64.S
> +++ b/arch/powerpc/kernel/entry_64.S
> @@ -451,6 +451,17 @@ END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
> 	std	r23,_CCR(r1)
> 	std	r1,KSP(r3)	/* Set old stack pointer */
> 
> +BEGIN_FTR_SECTION
> +	/*
> +	 * Back up the TAR across context switches.  Note that the TAR is not
> +	 * available for use in the kernel.  (To provide this, the TAR should
> +	 * be backed up/restored on exception entry/exit instead, and be in
> +	 * pt_regs.  FIXME, this should be in pt_regs anyway (for debug).)
> +	 */
> +	mfspr	r0,SPRN_TAR
> +	std	r0,THREAD_TAR(r3)
> +END_FTR_SECTION_IFSET(CPU_FTR_BCTAR)
> +
> #ifdef CONFIG_SMP
> 	/* We need a sync somewhere here to make sure that if the
> 	 * previous task gets rescheduled on another CPU, it sees all
> @@ -533,6 +544,11 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
> 	mr	r1,r8		/* start using new stack pointer */
> 	std	r7,PACAKSAVE(r13)
> 
> +BEGIN_FTR_SECTION
> +	ld	r0,THREAD_TAR(r4)
> +	mtspr	SPRN_TAR,r0
> +END_FTR_SECTION_IFSET(CPU_FTR_BCTAR)
> +
> #ifdef CONFIG_ALTIVEC
> BEGIN_FTR_SECTION
> 	ld	r0,THREAD_VRSAVE(r4)
> -- 
> 1.7.10.4
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev

Patch

diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 74458e69..cbbec56a 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -172,6 +172,7 @@  extern const char *powerpc_base_platform;
 #define CPU_FTR_ICSWX			LONG_ASM_CONST(0x1000000000000000)
 #define CPU_FTR_VMX_COPY		LONG_ASM_CONST(0x2000000000000000)
 #define CPU_FTR_TM			LONG_ASM_CONST(0x4000000000000000)
+#define CPU_FTR_BCTAR			LONG_ASM_CONST(0x8000000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -417,7 +418,7 @@  extern const char *powerpc_base_platform;
 	    CPU_FTR_DSCR | CPU_FTR_SAO  | \
 	    CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
 	    CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
-	    CPU_FTR_DBELL | CPU_FTR_TM_COMP)
+	    CPU_FTR_DBELL | CPU_FTR_TM_COMP | CPU_FTR_BCTAR)
 #define CPU_FTRS_CELL	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 8b2bf7a..cbbd82d 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -275,6 +275,7 @@  struct thread_struct {
 	unsigned long	dscr;
 	int		dscr_inherit;
 #endif
+	unsigned long	tar;
 };
 
 #define ARCH_MIN_TASKALIGN 16
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 5c9fe38..1fa8a56 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -257,6 +257,9 @@ 
 #define SPRN_HRMOR	0x139	/* Real mode offset register */
 #define SPRN_HSRR0	0x13A	/* Hypervisor Save/Restore 0 */
 #define SPRN_HSRR1	0x13B	/* Hypervisor Save/Restore 1 */
+#define SPRN_FSCR	0x099	/* Facility Status & Control Register */
+#define FSCR_TAR	(1<<8)	/* Enable Target Adress Register */
+#define SPRN_TAR	0x32f	/* Target Address Register */
 #define SPRN_LPCR	0x13E	/* LPAR Control Register */
 #define   LPCR_VPM0	(1ul << (63-0))
 #define   LPCR_VPM1	(1ul << (63-1))
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 42a4243..77e941e 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -145,6 +145,7 @@  int main(void)
 	DEFINE(TM_FRAME_SIZE, STACK_FRAME_OVERHEAD +
 	       sizeof(struct pt_regs) + 16);
 #endif /* CONFIG_TRANSACTIONAL_MEM */
+	DEFINE(THREAD_TAR, offsetof(struct thread_struct, tar));
 
 	DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
 	DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S
index 57cf140..d29facb 100644
--- a/arch/powerpc/kernel/cpu_setup_power.S
+++ b/arch/powerpc/kernel/cpu_setup_power.S
@@ -56,6 +56,7 @@  _GLOBAL(__setup_cpu_power8)
 	mfspr	r3,SPRN_LPCR
 	oris	r3, r3, LPCR_AIL_3@h
 	bl	__init_LPCR
+	bl	__init_FSCR
 	bl	__init_TLB
 	mtlr	r11
 	blr
@@ -112,6 +113,12 @@  __init_LPCR:
 	isync
 	blr
 
+__init_FSCR:
+	mfspr	r3,SPRN_FSCR
+	ori	r3,r3,FSCR_TAR
+	mtspr	SPRN_FSCR,r3
+	blr
+
 __init_TLB:
 	/* Clear the TLB */
 	li	r6,128
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index b3590c3..253885d 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -451,6 +451,17 @@  END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
 	std	r23,_CCR(r1)
 	std	r1,KSP(r3)	/* Set old stack pointer */
 
+BEGIN_FTR_SECTION
+	/*
+	 * Back up the TAR across context switches.  Note that the TAR is not
+	 * available for use in the kernel.  (To provide this, the TAR should
+	 * be backed up/restored on exception entry/exit instead, and be in
+	 * pt_regs.  FIXME, this should be in pt_regs anyway (for debug).)
+	 */
+	mfspr	r0,SPRN_TAR
+	std	r0,THREAD_TAR(r3)
+END_FTR_SECTION_IFSET(CPU_FTR_BCTAR)
+
 #ifdef CONFIG_SMP
 	/* We need a sync somewhere here to make sure that if the
 	 * previous task gets rescheduled on another CPU, it sees all
@@ -533,6 +544,11 @@  END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
 	mr	r1,r8		/* start using new stack pointer */
 	std	r7,PACAKSAVE(r13)
 
+BEGIN_FTR_SECTION
+	ld	r0,THREAD_TAR(r4)
+	mtspr	SPRN_TAR,r0
+END_FTR_SECTION_IFSET(CPU_FTR_BCTAR)
+
 #ifdef CONFIG_ALTIVEC
 BEGIN_FTR_SECTION
 	ld	r0,THREAD_VRSAVE(r4)