powerpc: Add support for context switching the TAR register
authorIan Munsie <imunsie@au1.ibm.com>
Thu, 7 Feb 2013 15:46:58 +0000 (15:46 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 8 Feb 2013 03:05:50 +0000 (14:05 +1100)
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>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/reg.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/cpu_setup_power.S
arch/powerpc/kernel/entry_64.S

index 06f7fb9..5f1938f 100644 (file)
@@ -414,7 +414,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_HAS_PPR | CPU_FTR_DAWR)
+           CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | 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 | \
index 7938658..42ac53c 100644 (file)
@@ -257,6 +257,9 @@ struct thread_struct {
        int             dscr_inherit;
        unsigned long   ppr;    /* used to save/restore SMT priority */
 #endif
+#ifdef CONFIG_PPC_BOOK3S_64
+       unsigned long   tar;
+#endif
 };
 
 #define ARCH_MIN_TASKALIGN 16
index 1f59fbb..e09ac51 100644 (file)
 #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))
index e39ca55..beddba4 100644 (file)
@@ -122,6 +122,10 @@ int main(void)
        DEFINE(THREAD_KVM_VCPU, offsetof(struct thread_struct, kvm_vcpu));
 #endif
 
+#ifdef CONFIG_PPC_BOOK3S_64
+       DEFINE(THREAD_TAR, offsetof(struct thread_struct, tar));
+#endif
+
        DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
        DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
        DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
index 57cf140..d29facb 100644 (file)
@@ -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
index 44c733f..9ae8451 100644 (file)
@@ -448,6 +448,19 @@ END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
        std     r23,_CCR(r1)
        std     r1,KSP(r3)      /* Set old stack pointer */
 
+#ifdef CONFIG_PPC_BOOK3S_64
+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)
+#endif
+
 #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
@@ -530,6 +543,13 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        mr      r1,r8           /* start using new stack pointer */
        std     r7,PACAKSAVE(r13)
 
+#ifdef CONFIG_PPC_BOOK3S_64
+BEGIN_FTR_SECTION
+       ld      r0,THREAD_TAR(r4)
+       mtspr   SPRN_TAR,r0
+END_FTR_SECTION_IFSET(CPU_FTR_BCTAR)
+#endif
+
 #ifdef CONFIG_ALTIVEC
 BEGIN_FTR_SECTION
        ld      r0,THREAD_VRSAVE(r4)