summaryrefslogtreecommitdiff
path: root/arch/powerpc/kernel/exceptions-64e.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/exceptions-64e.S')
-rw-r--r--arch/powerpc/kernel/exceptions-64e.S112
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