powerpc/85xx: Add AltiVec support for e6500
authorKumar Gala <galak@kernel.crashing.org>
Fri, 7 Sep 2012 20:57:17 +0000 (15:57 -0500)
committerKumar Gala <galak@kernel.crashing.org>
Tue, 12 Mar 2013 20:59:26 +0000 (15:59 -0500)
The e6500 core adds support for AltiVec on a Book-E class processor.
Connect up all the various exception handling code and build config
mechanisms to allow user spaces apps to utilize AltiVec.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/kvm_asm.h
arch/powerpc/kernel/cpu_setup_fsl_booke.S
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/exceptions-64e.S
arch/powerpc/platforms/Kconfig.cputype

index fb3245e..f326444 100644 (file)
@@ -374,7 +374,7 @@ extern const char *powerpc_base_platform;
 #define CPU_FTRS_E6500 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \
            CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
            CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
-           CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV)
+           CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV | CPU_FTR_ALTIVEC_COMP)
 #define CPU_FTRS_GENERIC_32    (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
 
 /* 64-bit CPUs */
index aabcdba..b9dd382 100644 (file)
 #define BOOKE_INTERRUPT_HV_SYSCALL 40
 #define BOOKE_INTERRUPT_HV_PRIV 41
 
+/* altivec */
+#define BOOKE_INTERRUPT_ALTIVEC_UNAVAIL 42
+#define BOOKE_INTERRUPT_ALTIVEC_ASSIST 43
+
 /* book3s */
 
 #define BOOK3S_INTERRUPT_SYSTEM_RESET  0x100
index dcd8819..0b9af01 100644 (file)
@@ -53,6 +53,15 @@ _GLOBAL(__e500_dcache_setup)
        isync
        blr
 
+_GLOBAL(__setup_cpu_e6500)
+       mflr    r6
+#ifdef CONFIG_PPC64
+       bl      .setup_altivec_ivors
+#endif
+       bl      __setup_cpu_e5500
+       mtlr    r6
+       blr
+
 #ifdef CONFIG_PPC32
 _GLOBAL(__setup_cpu_e200)
        /* enable dedicated debug exception handling resources (Debug APU) */
@@ -107,6 +116,13 @@ _GLOBAL(__setup_cpu_e5500)
 #endif
 
 #ifdef CONFIG_PPC_BOOK3E_64
+_GLOBAL(__restore_cpu_e6500)
+       mflr    r5
+       bl      .setup_altivec_ivors
+       bl      __restore_cpu_e5500
+       mtlr    r5
+       blr
+
 _GLOBAL(__restore_cpu_e5500)
        mflr    r4
        bl      __e500_icache_setup
index 75a3d71..cc39139 100644 (file)
@@ -74,7 +74,9 @@ extern void __restore_cpu_a2(void);
 #endif /* CONFIG_PPC64 */
 #if defined(CONFIG_E500)
 extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec);
+extern void __setup_cpu_e6500(unsigned long offset, struct cpu_spec* spec);
 extern void __restore_cpu_e5500(void);
+extern void __restore_cpu_e6500(void);
 #endif /* CONFIG_E500 */
 
 /* This table only contains "desktop" CPUs, it need to be filled with embedded
@@ -2065,7 +2067,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .pvr_value              = 0x80400000,
                .cpu_name               = "e6500",
                .cpu_features           = CPU_FTRS_E6500,
-               .cpu_user_features      = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
+               .cpu_user_features      = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU |
+                       PPC_FEATURE_HAS_ALTIVEC_COMP,
                .mmu_features           = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS |
                        MMU_FTR_USE_TLBILX,
                .icache_bsize           = 64,
@@ -2073,9 +2076,9 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .num_pmcs               = 4,
                .oprofile_cpu_type      = "ppc/e6500",
                .oprofile_type          = PPC_OPROFILE_FSL_EMB,
-               .cpu_setup              = __setup_cpu_e5500,
+               .cpu_setup              = __setup_cpu_e6500,
 #ifndef CONFIG_PPC32
-               .cpu_restore            = __restore_cpu_e5500,
+               .cpu_restore            = __restore_cpu_e6500,
 #endif
                .machine_check          = machine_check_e500mc,
                .platform               = "ppce6500",
index ae54553..42a756e 100644 (file)
@@ -299,6 +299,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)
@@ -395,6 +397,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)
@@ -807,6 +848,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)
@@ -1350,6 +1392,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
index cea2f09..6dfdb65 100644 (file)
@@ -232,7 +232,7 @@ config PHYS_64BIT
 
 config ALTIVEC
        bool "AltiVec Support"
-       depends on 6xx || POWER4
+       depends on 6xx || POWER4 || (PPC_E500MC && PPC64)
        ---help---
          This option enables kernel support for the Altivec extensions to the
          PowerPC processor. The kernel currently supports saving and restoring