diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/ppc64/kernel/head.S | 2 | ||||
-rw-r--r-- | arch/ppc64/kernel/prom.c | 19 | ||||
-rw-r--r-- | arch/ppc64/kernel/traps.c | 2 |
3 files changed, 20 insertions, 3 deletions
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index fe05f3fbf9d..92a744c31ab 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S @@ -922,7 +922,9 @@ fp_unavailable_common: altivec_unavailable_common: EXCEPTION_PROLOG_COMMON(0xf20, PACA_EXGEN) #ifdef CONFIG_ALTIVEC +BEGIN_FTR_SECTION bne .load_up_altivec /* if from user, just load it up */ +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) #endif bl .save_nvgprs addi r3,r1,STACK_FRAME_OVERHEAD diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index 01739d5c47c..b08aac68baf 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -885,6 +885,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, const char *full_path, void *data) { char *type = get_flat_dt_prop(node, "device_type", NULL); + u32 *prop; /* We are scanning "cpu" nodes only */ if (type == NULL || strcmp(type, "cpu") != 0) @@ -916,6 +917,20 @@ static int __init early_init_dt_scan_cpus(unsigned long node, } } + /* Check if we have a VMX and eventually update CPU features */ + prop = (u32 *)get_flat_dt_prop(node, "ibm,vmx", NULL); + if (prop && (*prop) > 0) { + cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; + cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; + } + + /* Same goes for Apple's "altivec" property */ + prop = (u32 *)get_flat_dt_prop(node, "altivec", NULL); + if (prop) { + cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; + cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; + } + return 0; } @@ -1104,7 +1119,9 @@ void __init early_init_devtree(void *params) DBG("Scanning CPUs ...\n"); - /* Retreive hash table size from flattened tree */ + /* Retreive hash table size from flattened tree plus other + * CPU related informations (altivec support, boot CPU ID, ...) + */ scan_flat_dt(early_init_dt_scan_cpus, NULL); /* If hash size wasn't obtained above, we calculate it now based on diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c index 10fc61f3f6a..7e52cb2605e 100644 --- a/arch/ppc64/kernel/traps.c +++ b/arch/ppc64/kernel/traps.c @@ -450,14 +450,12 @@ void kernel_fp_unavailable_exception(struct pt_regs *regs) void altivec_unavailable_exception(struct pt_regs *regs) { -#ifndef CONFIG_ALTIVEC if (user_mode(regs)) { /* A user program has executed an altivec instruction, but this kernel doesn't support altivec. */ _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); return; } -#endif printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception " "%lx at %lx\n", regs->trap, regs->nip); die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT); |