powerpc: Add support for context switching the TAR register

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>
This commit is contained in:
Ian Munsie 2013-02-07 15:46:58 +00:00 committed by Benjamin Herrenschmidt
parent 14b6f00f8a
commit 2468dcf641
6 changed files with 38 additions and 1 deletions

View File

@ -414,7 +414,7 @@ extern const char *powerpc_base_platform;
CPU_FTR_DSCR | CPU_FTR_SAO | \ CPU_FTR_DSCR | CPU_FTR_SAO | \
CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ 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_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 | \ #define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \

View File

@ -257,6 +257,9 @@ struct thread_struct {
int dscr_inherit; int dscr_inherit;
unsigned long ppr; /* used to save/restore SMT priority */ unsigned long ppr; /* used to save/restore SMT priority */
#endif #endif
#ifdef CONFIG_PPC_BOOK3S_64
unsigned long tar;
#endif
}; };
#define ARCH_MIN_TASKALIGN 16 #define ARCH_MIN_TASKALIGN 16

View File

@ -237,6 +237,9 @@
#define SPRN_HRMOR 0x139 /* Real mode offset register */ #define SPRN_HRMOR 0x139 /* Real mode offset register */
#define SPRN_HSRR0 0x13A /* Hypervisor Save/Restore 0 */ #define SPRN_HSRR0 0x13A /* Hypervisor Save/Restore 0 */
#define SPRN_HSRR1 0x13B /* Hypervisor Save/Restore 1 */ #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 SPRN_LPCR 0x13E /* LPAR Control Register */
#define LPCR_VPM0 (1ul << (63-0)) #define LPCR_VPM0 (1ul << (63-0))
#define LPCR_VPM1 (1ul << (63-1)) #define LPCR_VPM1 (1ul << (63-1))

View File

@ -122,6 +122,10 @@ int main(void)
DEFINE(THREAD_KVM_VCPU, offsetof(struct thread_struct, kvm_vcpu)); DEFINE(THREAD_KVM_VCPU, offsetof(struct thread_struct, kvm_vcpu));
#endif #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_FLAGS, offsetof(struct thread_info, flags));
DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags)); DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));

View File

@ -56,6 +56,7 @@ _GLOBAL(__setup_cpu_power8)
mfspr r3,SPRN_LPCR mfspr r3,SPRN_LPCR
oris r3, r3, LPCR_AIL_3@h oris r3, r3, LPCR_AIL_3@h
bl __init_LPCR bl __init_LPCR
bl __init_FSCR
bl __init_TLB bl __init_TLB
mtlr r11 mtlr r11
blr blr
@ -112,6 +113,12 @@ __init_LPCR:
isync isync
blr blr
__init_FSCR:
mfspr r3,SPRN_FSCR
ori r3,r3,FSCR_TAR
mtspr SPRN_FSCR,r3
blr
__init_TLB: __init_TLB:
/* Clear the TLB */ /* Clear the TLB */
li r6,128 li r6,128

View File

@ -448,6 +448,19 @@ END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
std r23,_CCR(r1) std r23,_CCR(r1)
std r1,KSP(r3) /* Set old stack pointer */ 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 #ifdef CONFIG_SMP
/* We need a sync somewhere here to make sure that if the /* We need a sync somewhere here to make sure that if the
* previous task gets rescheduled on another CPU, it sees all * 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 */ mr r1,r8 /* start using new stack pointer */
std r7,PACAKSAVE(r13) 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 #ifdef CONFIG_ALTIVEC
BEGIN_FTR_SECTION BEGIN_FTR_SECTION
ld r0,THREAD_VRSAVE(r4) ld r0,THREAD_VRSAVE(r4)