Commit 5e14d21e authored by Kumar Gala's avatar Kumar Gala

[POWERPC] Add cpu feature for SPE handling

Make it so that SPE support can be determined at runtime.  This is similiar
to how we handle AltiVec.  This allows us to have SPE support built in and
work on processors with and without SPE.
Signed-off-by: default avatarKumar Gala <galak@kernel.crashing.org>
parent d8f1324a
...@@ -68,15 +68,6 @@ extern void __restore_cpu_ppc970(void); ...@@ -68,15 +68,6 @@ extern void __restore_cpu_ppc970(void);
#define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \ #define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \
PPC_FEATURE_BOOKE) PPC_FEATURE_BOOKE)
/* We only set the spe features if the kernel was compiled with
* spe support
*/
#ifdef CONFIG_SPE
#define PPC_FEATURE_SPE_COMP PPC_FEATURE_HAS_SPE
#else
#define PPC_FEATURE_SPE_COMP 0
#endif
static struct cpu_spec cpu_specs[] = { static struct cpu_spec cpu_specs[] = {
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
{ /* Power3 */ { /* Power3 */
...@@ -1261,8 +1252,8 @@ static struct cpu_spec cpu_specs[] = { ...@@ -1261,8 +1252,8 @@ static struct cpu_spec cpu_specs[] = {
/* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
.cpu_features = CPU_FTRS_E200, .cpu_features = CPU_FTRS_E200,
.cpu_user_features = COMMON_USER_BOOKE | .cpu_user_features = COMMON_USER_BOOKE |
PPC_FEATURE_SPE_COMP | PPC_FEATURE_HAS_SPE_COMP |
PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_HAS_EFP_SINGLE_COMP |
PPC_FEATURE_UNIFIED_CACHE, PPC_FEATURE_UNIFIED_CACHE,
.dcache_bsize = 32, .dcache_bsize = 32,
.platform = "ppc5554", .platform = "ppc5554",
...@@ -1274,8 +1265,8 @@ static struct cpu_spec cpu_specs[] = { ...@@ -1274,8 +1265,8 @@ static struct cpu_spec cpu_specs[] = {
/* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
.cpu_features = CPU_FTRS_E500, .cpu_features = CPU_FTRS_E500,
.cpu_user_features = COMMON_USER_BOOKE | .cpu_user_features = COMMON_USER_BOOKE |
PPC_FEATURE_SPE_COMP | PPC_FEATURE_HAS_SPE_COMP |
PPC_FEATURE_HAS_EFP_SINGLE, PPC_FEATURE_HAS_EFP_SINGLE_COMP,
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
.num_pmcs = 4, .num_pmcs = 4,
...@@ -1290,9 +1281,9 @@ static struct cpu_spec cpu_specs[] = { ...@@ -1290,9 +1281,9 @@ static struct cpu_spec cpu_specs[] = {
/* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */ /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
.cpu_features = CPU_FTRS_E500_2, .cpu_features = CPU_FTRS_E500_2,
.cpu_user_features = COMMON_USER_BOOKE | .cpu_user_features = COMMON_USER_BOOKE |
PPC_FEATURE_SPE_COMP | PPC_FEATURE_HAS_SPE_COMP |
PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_HAS_EFP_SINGLE_COMP |
PPC_FEATURE_HAS_EFP_DOUBLE, PPC_FEATURE_HAS_EFP_DOUBLE_COMP,
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
.num_pmcs = 4, .num_pmcs = 4,
......
...@@ -504,9 +504,11 @@ BEGIN_FTR_SECTION ...@@ -504,9 +504,11 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
#endif /* CONFIG_ALTIVEC */ #endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_SPE #ifdef CONFIG_SPE
BEGIN_FTR_SECTION
oris r0,r0,MSR_SPE@h /* Disable SPE */ oris r0,r0,MSR_SPE@h /* Disable SPE */
mfspr r12,SPRN_SPEFSCR /* save spefscr register value */ mfspr r12,SPRN_SPEFSCR /* save spefscr register value */
stw r12,THREAD+THREAD_SPEFSCR(r2) stw r12,THREAD+THREAD_SPEFSCR(r2)
END_FTR_SECTION_IFSET(CPU_FTR_SPE)
#endif /* CONFIG_SPE */ #endif /* CONFIG_SPE */
and. r0,r0,r11 /* FP or altivec or SPE enabled? */ and. r0,r0,r11 /* FP or altivec or SPE enabled? */
beq+ 1f beq+ 1f
...@@ -542,8 +544,10 @@ BEGIN_FTR_SECTION ...@@ -542,8 +544,10 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
#endif /* CONFIG_ALTIVEC */ #endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_SPE #ifdef CONFIG_SPE
BEGIN_FTR_SECTION
lwz r0,THREAD+THREAD_SPEFSCR(r2) lwz r0,THREAD+THREAD_SPEFSCR(r2)
mtspr SPRN_SPEFSCR,r0 /* restore SPEFSCR reg */ mtspr SPRN_SPEFSCR,r0 /* restore SPEFSCR reg */
END_FTR_SECTION_IFSET(CPU_FTR_SPE)
#endif /* CONFIG_SPE */ #endif /* CONFIG_SPE */
lwz r0,_CCR(r1) lwz r0,_CCR(r1)
......
...@@ -669,9 +669,13 @@ int set_fpexc_mode(struct task_struct *tsk, unsigned int val) ...@@ -669,9 +669,13 @@ int set_fpexc_mode(struct task_struct *tsk, unsigned int val)
* mode (asyn, precise, disabled) for 'Classic' FP. */ * mode (asyn, precise, disabled) for 'Classic' FP. */
if (val & PR_FP_EXC_SW_ENABLE) { if (val & PR_FP_EXC_SW_ENABLE) {
#ifdef CONFIG_SPE #ifdef CONFIG_SPE
if (cpu_has_feature(CPU_FTR_SPE)) {
tsk->thread.fpexc_mode = val & tsk->thread.fpexc_mode = val &
(PR_FP_EXC_SW_ENABLE | PR_FP_ALL_EXCEPT); (PR_FP_EXC_SW_ENABLE | PR_FP_ALL_EXCEPT);
return 0; return 0;
} else {
return -EINVAL;
}
#else #else
return -EINVAL; return -EINVAL;
#endif #endif
...@@ -697,7 +701,10 @@ int get_fpexc_mode(struct task_struct *tsk, unsigned long adr) ...@@ -697,7 +701,10 @@ int get_fpexc_mode(struct task_struct *tsk, unsigned long adr)
if (tsk->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE) if (tsk->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE)
#ifdef CONFIG_SPE #ifdef CONFIG_SPE
if (cpu_has_feature(CPU_FTR_SPE))
val = tsk->thread.fpexc_mode; val = tsk->thread.fpexc_mode;
else
return -EINVAL;
#else #else
return -EINVAL; return -EINVAL;
#endif #endif
......
...@@ -576,8 +576,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -576,8 +576,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#ifdef CONFIG_SPE #ifdef CONFIG_SPE
case PTRACE_GETEVRREGS: case PTRACE_GETEVRREGS:
/* Get the child spe register state. */ /* Get the child spe register state. */
if (child->thread.regs->msr & MSR_SPE) flush_spe_to_thread(child);
giveup_spe(child);
ret = get_evrregs((unsigned long __user *)data, child); ret = get_evrregs((unsigned long __user *)data, child);
break; break;
...@@ -585,8 +584,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -585,8 +584,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* Set the child spe register state. */ /* Set the child spe register state. */
/* this is to clear the MSR_SPE bit to force a reload /* this is to clear the MSR_SPE bit to force a reload
* of register state from memory */ * of register state from memory */
if (child->thread.regs->msr & MSR_SPE) flush_spe_to_thread(child);
giveup_spe(child);
ret = set_evrregs(child, (unsigned long __user *)data); ret = set_evrregs(child, (unsigned long __user *)data);
break; break;
#endif #endif
......
...@@ -136,6 +136,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, ...@@ -136,6 +136,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
#define CPU_FTR_REAL_LE ASM_CONST(0x0000000000400000) #define CPU_FTR_REAL_LE ASM_CONST(0x0000000000400000)
#define CPU_FTR_FPU_UNAVAILABLE ASM_CONST(0x0000000000800000) #define CPU_FTR_FPU_UNAVAILABLE ASM_CONST(0x0000000000800000)
#define CPU_FTR_UNIFIED_ID_CACHE ASM_CONST(0x0000000001000000) #define CPU_FTR_UNIFIED_ID_CACHE ASM_CONST(0x0000000001000000)
#define CPU_FTR_SPE ASM_CONST(0x0000000002000000)
/* /*
* Add the 64-bit processor unique features in the top half of the word; * Add the 64-bit processor unique features in the top half of the word;
...@@ -180,6 +181,21 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, ...@@ -180,6 +181,21 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
#define PPC_FEATURE_HAS_ALTIVEC_COMP 0 #define PPC_FEATURE_HAS_ALTIVEC_COMP 0
#endif #endif
/* We only set the spe features if the kernel was compiled with spe
* support
*/
#ifdef CONFIG_SPE
#define CPU_FTR_SPE_COMP CPU_FTR_SPE
#define PPC_FEATURE_HAS_SPE_COMP PPC_FEATURE_HAS_SPE
#define PPC_FEATURE_HAS_EFP_SINGLE_COMP PPC_FEATURE_HAS_EFP_SINGLE
#define PPC_FEATURE_HAS_EFP_DOUBLE_COMP PPC_FEATURE_HAS_EFP_DOUBLE
#else
#define CPU_FTR_SPE_COMP 0
#define PPC_FEATURE_HAS_SPE_COMP 0
#define PPC_FEATURE_HAS_EFP_SINGLE_COMP 0
#define PPC_FEATURE_HAS_EFP_DOUBLE_COMP 0
#endif
/* We need to mark all pages as being coherent if we're SMP or we /* We need to mark all pages as being coherent if we're SMP or we
* have a 74[45]x and an MPC107 host bridge. Also 83xx requires * have a 74[45]x and an MPC107 host bridge. Also 83xx requires
* it for PCI "streaming/prefetch" to work properly. * it for PCI "streaming/prefetch" to work properly.
...@@ -310,10 +326,12 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, ...@@ -310,10 +326,12 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
#define CPU_FTRS_8XX (CPU_FTR_USE_TB) #define CPU_FTRS_8XX (CPU_FTR_USE_TB)
#define CPU_FTRS_40X (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN) #define CPU_FTRS_40X (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
#define CPU_FTRS_44X (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN) #define CPU_FTRS_44X (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
#define CPU_FTRS_E200 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \ #define CPU_FTRS_E200 (CPU_FTR_USE_TB | CPU_FTR_SPE_COMP | \
CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE) CPU_FTR_NODSISRALIGN | CPU_FTR_COHERENT_ICACHE | \
#define CPU_FTRS_E500 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN) CPU_FTR_UNIFIED_ID_CACHE)
#define CPU_FTRS_E500_2 (CPU_FTR_USE_TB | \ #define CPU_FTRS_E500 (CPU_FTR_USE_TB | CPU_FTR_SPE_COMP | \
CPU_FTR_NODSISRALIGN)
#define CPU_FTRS_E500_2 (CPU_FTR_USE_TB | CPU_FTR_SPE_COMP | \
CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN) CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN)
#define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN) #define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment