diff options
Diffstat (limited to 'arch/powerpc/kernel/exceptions-64e.S')
-rw-r--r-- | arch/powerpc/kernel/exceptions-64e.S | 112 |
1 files changed, 99 insertions, 13 deletions
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 4684e33..39308c7 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S @@ -298,6 +298,8 @@ interrupt_base_book3e: /* fake trap */ EXCEPTION_STUB(0x1a0, watchdog) /* 0x09f0 */ EXCEPTION_STUB(0x1c0, data_tlb_miss) EXCEPTION_STUB(0x1e0, instruction_tlb_miss) + EXCEPTION_STUB(0x200, altivec_unavailable) /* 0x0f20 */ + EXCEPTION_STUB(0x220, altivec_assist) /* 0x1700 */ EXCEPTION_STUB(0x260, perfmon) EXCEPTION_STUB(0x280, doorbell) EXCEPTION_STUB(0x2a0, doorbell_crit) @@ -394,6 +396,45 @@ interrupt_end_book3e: bl .kernel_fp_unavailable_exception b .ret_from_except +/* Altivec Unavailable Interrupt */ + START_EXCEPTION(altivec_unavailable); + NORMAL_EXCEPTION_PROLOG(0x200, BOOKE_INTERRUPT_ALTIVEC_UNAVAIL, + PROLOG_ADDITION_NONE) + /* we can probably do a shorter exception entry for that one... */ + EXCEPTION_COMMON(0x200, PACA_EXGEN, INTS_KEEP) +#ifdef CONFIG_ALTIVEC +BEGIN_FTR_SECTION + ld r12,_MSR(r1) + andi. r0,r12,MSR_PR; + beq- 1f + bl .load_up_altivec + b fast_exception_return +1: +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) +#endif + INTS_DISABLE + bl .save_nvgprs + addi r3,r1,STACK_FRAME_OVERHEAD + bl .altivec_unavailable_exception + b .ret_from_except + +/* AltiVec Assist */ + START_EXCEPTION(altivec_assist); + NORMAL_EXCEPTION_PROLOG(0x220, BOOKE_INTERRUPT_ALTIVEC_ASSIST, + PROLOG_ADDITION_NONE) + EXCEPTION_COMMON(0x220, PACA_EXGEN, INTS_DISABLE) + bl .save_nvgprs + addi r3,r1,STACK_FRAME_OVERHEAD +#ifdef CONFIG_ALTIVEC +BEGIN_FTR_SECTION + bl .altivec_assist_exception +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) +#else + bl .unknown_exception +#endif + b .ret_from_except + + /* Decrementer Interrupt */ MASKABLE_EXCEPTION(0x900, BOOKE_INTERRUPT_DECREMENTER, decrementer, .timer_interrupt, ACK_DEC) @@ -653,6 +694,7 @@ kernel_dbg_exc: mtcr r11 ld r10,PACA_EXGEN+EX_R10(r13) ld r11,PACA_EXGEN+EX_R11(r13) + fsl_erratum_a006198_restore_srr r13 mfspr r13,SPRN_SPRG_GEN_SCRATCH rfi b . @@ -757,7 +799,7 @@ _GLOBAL(exception_return_book3e) */ .globl fast_exception_return fast_exception_return: - wrteei 0 + fsl_erratum_a006198_wrteei0 r0 r10 1: mr r0,r13 ld r10,_MSR(r1) REST_4GPRS(2, r1) @@ -793,6 +835,7 @@ fast_exception_return: mtspr SPRN_SRR1,r11 ld r10,PACA_EXGEN+EX_R10(r13) ld r11,PACA_EXGEN+EX_R11(r13) + fsl_erratum_a006198_restore_srr r13 mfspr r13,SPRN_SPRG_GEN_SCRATCH rfi @@ -806,6 +849,7 @@ fast_exception_return: BAD_STACK_TRAMPOLINE(0x000) BAD_STACK_TRAMPOLINE(0x100) BAD_STACK_TRAMPOLINE(0x200) +BAD_STACK_TRAMPOLINE(0x220) BAD_STACK_TRAMPOLINE(0x260) BAD_STACK_TRAMPOLINE(0x280) BAD_STACK_TRAMPOLINE(0x2a0) @@ -1277,6 +1321,11 @@ _GLOBAL(book3e_secondary_core_init) /* Init global core bits */ 2: bl .init_core_book3e +BEGIN_FTR_SECTION + /* Start threads */ + bl .fsl_enable_threads +END_FTR_SECTION_IFSET(CPU_FTR_SMT) + /* Init per-thread bits */ 3: bl .init_thread_book3e @@ -1312,12 +1361,44 @@ _STATIC(init_core_book3e) sync blr +_GLOBAL(fsl_enable_threads) +BEGIN_FTR_SECTION + MFTMR(TMRN_TMCFG0, 3) + andi. r3,r3,0x3f + cmpi 0,r3,2 + blt 2f + + /* Disable the other thread */ + li r3,2 + mtspr SPRN_TENC,r3 + +1: mfspr r3,SPRN_TENSR + andi. r3,r3,2 + bne 1b + + /* Configure the MSR per the default */ + LOAD_REG_IMMEDIATE(r3, MSR_KERNEL); + MTTMR(TMRN_IMSR1, 3); + + /* + * Set the NIA for the secondary thread to + * generic_secondary_thread_init + */ + LOAD_REG_IMMEDIATE(r3, .fsl_secondary_thread_init); + MTTMR(TMRN_INIA1, 3); + + /* Release the other thread. It will spin until kick_cpu is called */ + li r3, 2 + mtspr SPRN_TENS, r3 +END_FTR_SECTION_IFSET(CPU_FTR_SMT) +2: blr + _STATIC(init_thread_book3e) lis r3,(SPRN_EPCR_ICM | SPRN_EPCR_GICM)@h mtspr SPRN_EPCR,r3 /* Make sure interrupts are off */ - wrteei 0 + fsl_erratum_a006198_wrteei0 r3 r4 /* disable all timers and clear out status */ li r3,0 @@ -1330,18 +1411,18 @@ _STATIC(init_thread_book3e) _GLOBAL(__setup_base_ivors) SET_IVOR(0, 0x020) /* Critical Input */ SET_IVOR(1, 0x000) /* Machine Check */ - SET_IVOR(2, 0x060) /* Data Storage */ + SET_IVOR(2, 0x060) /* Data Storage */ SET_IVOR(3, 0x080) /* Instruction Storage */ - SET_IVOR(4, 0x0a0) /* External Input */ - SET_IVOR(5, 0x0c0) /* Alignment */ - SET_IVOR(6, 0x0e0) /* Program */ - SET_IVOR(7, 0x100) /* FP Unavailable */ - SET_IVOR(8, 0x120) /* System Call */ - SET_IVOR(9, 0x140) /* Auxiliary Processor Unavailable */ - SET_IVOR(10, 0x160) /* Decrementer */ - SET_IVOR(11, 0x180) /* Fixed Interval Timer */ - SET_IVOR(12, 0x1a0) /* Watchdog Timer */ - SET_IVOR(13, 0x1c0) /* Data TLB Error */ + SET_IVOR(4, 0x0a0) /* External Input */ + SET_IVOR(5, 0x0c0) /* Alignment */ + SET_IVOR(6, 0x0e0) /* Program */ + SET_IVOR(7, 0x100) /* FP Unavailable */ + SET_IVOR(8, 0x120) /* System Call */ + SET_IVOR(9, 0x140) /* Auxiliary Processor Unavailable */ + SET_IVOR(10, 0x160) /* Decrementer */ + SET_IVOR(11, 0x180) /* Fixed Interval Timer */ + SET_IVOR(12, 0x1a0) /* Watchdog Timer */ + SET_IVOR(13, 0x1c0) /* Data TLB Error */ SET_IVOR(14, 0x1e0) /* Instruction TLB Error */ SET_IVOR(15, 0x040) /* Debug */ @@ -1349,6 +1430,11 @@ _GLOBAL(__setup_base_ivors) blr +_GLOBAL(setup_altivec_ivors) + SET_IVOR(32, 0x200) /* AltiVec Unavailable */ + SET_IVOR(33, 0x220) /* AltiVec Assist */ + blr + _GLOBAL(setup_perfmon_ivor) SET_IVOR(35, 0x260) /* Performance Monitor */ blr |