Browse Source

powerpc/85xx: Add AltiVec support for e6500

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>
Kumar Gala 13 years ago
parent
commit
cd66cc2ee5

+ 1 - 1
arch/powerpc/include/asm/cputable.h

@@ -374,7 +374,7 @@ extern const char *powerpc_base_platform;
 #define CPU_FTRS_E6500	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \
 #define CPU_FTRS_E6500	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \
 	    CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
 	    CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
 	    CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
 	    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)
 #define CPU_FTRS_GENERIC_32	(CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
 
 
 /* 64-bit CPUs */
 /* 64-bit CPUs */

+ 4 - 0
arch/powerpc/include/asm/kvm_asm.h

@@ -67,6 +67,10 @@
 #define BOOKE_INTERRUPT_HV_SYSCALL 40
 #define BOOKE_INTERRUPT_HV_SYSCALL 40
 #define BOOKE_INTERRUPT_HV_PRIV 41
 #define BOOKE_INTERRUPT_HV_PRIV 41
 
 
+/* altivec */
+#define BOOKE_INTERRUPT_ALTIVEC_UNAVAIL 42
+#define BOOKE_INTERRUPT_ALTIVEC_ASSIST 43
+
 /* book3s */
 /* book3s */
 
 
 #define BOOK3S_INTERRUPT_SYSTEM_RESET	0x100
 #define BOOK3S_INTERRUPT_SYSTEM_RESET	0x100

+ 16 - 0
arch/powerpc/kernel/cpu_setup_fsl_booke.S

@@ -53,6 +53,15 @@ _GLOBAL(__e500_dcache_setup)
 	isync
 	isync
 	blr
 	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
 #ifdef CONFIG_PPC32
 _GLOBAL(__setup_cpu_e200)
 _GLOBAL(__setup_cpu_e200)
 	/* enable dedicated debug exception handling resources (Debug APU) */
 	/* enable dedicated debug exception handling resources (Debug APU) */
@@ -107,6 +116,13 @@ _GLOBAL(__setup_cpu_e5500)
 #endif
 #endif
 
 
 #ifdef CONFIG_PPC_BOOK3E_64
 #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)
 _GLOBAL(__restore_cpu_e5500)
 	mflr	r4
 	mflr	r4
 	bl	__e500_icache_setup
 	bl	__e500_icache_setup

+ 6 - 3
arch/powerpc/kernel/cputable.c

@@ -74,7 +74,9 @@ extern void __restore_cpu_a2(void);
 #endif /* CONFIG_PPC64 */
 #endif /* CONFIG_PPC64 */
 #if defined(CONFIG_E500)
 #if defined(CONFIG_E500)
 extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec);
 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_e5500(void);
+extern void __restore_cpu_e6500(void);
 #endif /* CONFIG_E500 */
 #endif /* CONFIG_E500 */
 
 
 /* This table only contains "desktop" CPUs, it need to be filled with embedded
 /* 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,
 		.pvr_value		= 0x80400000,
 		.cpu_name		= "e6500",
 		.cpu_name		= "e6500",
 		.cpu_features		= CPU_FTRS_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_features		= MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS |
 			MMU_FTR_USE_TLBILX,
 			MMU_FTR_USE_TLBILX,
 		.icache_bsize		= 64,
 		.icache_bsize		= 64,
@@ -2073,9 +2076,9 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.num_pmcs		= 4,
 		.num_pmcs		= 4,
 		.oprofile_cpu_type	= "ppc/e6500",
 		.oprofile_cpu_type	= "ppc/e6500",
 		.oprofile_type		= PPC_OPROFILE_FSL_EMB,
 		.oprofile_type		= PPC_OPROFILE_FSL_EMB,
-		.cpu_setup		= __setup_cpu_e5500,
+		.cpu_setup		= __setup_cpu_e6500,
 #ifndef CONFIG_PPC32
 #ifndef CONFIG_PPC32
-		.cpu_restore		= __restore_cpu_e5500,
+		.cpu_restore		= __restore_cpu_e6500,
 #endif
 #endif
 		.machine_check		= machine_check_e500mc,
 		.machine_check		= machine_check_e500mc,
 		.platform		= "ppce6500",
 		.platform		= "ppce6500",

+ 47 - 0
arch/powerpc/kernel/exceptions-64e.S

@@ -299,6 +299,8 @@ interrupt_base_book3e:					/* fake trap */
 	EXCEPTION_STUB(0x1a0, watchdog)			/* 0x09f0 */
 	EXCEPTION_STUB(0x1a0, watchdog)			/* 0x09f0 */
 	EXCEPTION_STUB(0x1c0, data_tlb_miss)
 	EXCEPTION_STUB(0x1c0, data_tlb_miss)
 	EXCEPTION_STUB(0x1e0, instruction_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(0x260, perfmon)
 	EXCEPTION_STUB(0x280, doorbell)
 	EXCEPTION_STUB(0x280, doorbell)
 	EXCEPTION_STUB(0x2a0, doorbell_crit)
 	EXCEPTION_STUB(0x2a0, doorbell_crit)
@@ -395,6 +397,45 @@ interrupt_end_book3e:
 	bl	.kernel_fp_unavailable_exception
 	bl	.kernel_fp_unavailable_exception
 	b	.ret_from_except
 	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 */
 /* Decrementer Interrupt */
 	MASKABLE_EXCEPTION(0x900, BOOKE_INTERRUPT_DECREMENTER,
 	MASKABLE_EXCEPTION(0x900, BOOKE_INTERRUPT_DECREMENTER,
 			   decrementer, .timer_interrupt, ACK_DEC)
 			   decrementer, .timer_interrupt, ACK_DEC)
@@ -807,6 +848,7 @@ fast_exception_return:
 BAD_STACK_TRAMPOLINE(0x000)
 BAD_STACK_TRAMPOLINE(0x000)
 BAD_STACK_TRAMPOLINE(0x100)
 BAD_STACK_TRAMPOLINE(0x100)
 BAD_STACK_TRAMPOLINE(0x200)
 BAD_STACK_TRAMPOLINE(0x200)
+BAD_STACK_TRAMPOLINE(0x220)
 BAD_STACK_TRAMPOLINE(0x260)
 BAD_STACK_TRAMPOLINE(0x260)
 BAD_STACK_TRAMPOLINE(0x280)
 BAD_STACK_TRAMPOLINE(0x280)
 BAD_STACK_TRAMPOLINE(0x2a0)
 BAD_STACK_TRAMPOLINE(0x2a0)
@@ -1350,6 +1392,11 @@ _GLOBAL(__setup_base_ivors)
 
 
 	blr
 	blr
 
 
+_GLOBAL(setup_altivec_ivors)
+	SET_IVOR(32, 0x200) /* AltiVec Unavailable */
+	SET_IVOR(33, 0x220) /* AltiVec Assist */
+	blr
+
 _GLOBAL(setup_perfmon_ivor)
 _GLOBAL(setup_perfmon_ivor)
 	SET_IVOR(35, 0x260) /* Performance Monitor */
 	SET_IVOR(35, 0x260) /* Performance Monitor */
 	blr
 	blr

+ 1 - 1
arch/powerpc/platforms/Kconfig.cputype

@@ -232,7 +232,7 @@ config PHYS_64BIT
 
 
 config ALTIVEC
 config ALTIVEC
 	bool "AltiVec Support"
 	bool "AltiVec Support"
-	depends on 6xx || POWER4
+	depends on 6xx || POWER4 || (PPC_E500MC && PPC64)
 	---help---
 	---help---
 	  This option enables kernel support for the Altivec extensions to the
 	  This option enables kernel support for the Altivec extensions to the
 	  PowerPC processor. The kernel currently supports saving and restoring
 	  PowerPC processor. The kernel currently supports saving and restoring