tree d5f1ae0d320e6325ed056469773e855fc635c53d
parent 547ee84cea37696d25c93306e909378a87db2f66
author Benjamin Herrenschmidt <[EMAIL PROTECTED]> Sun, 17 Apr 2005 05:24:36 
-0700
committer Linus Torvalds <[EMAIL PROTECTED]> Sun, 17 Apr 2005 05:24:36 -0700

[PATCH] ppc64: Detect altivec via firmware on unknown CPUs

This patch adds detection of the Altivec capability of the CPU via the
firmware in addition to the cpu table.  This allows newer CPUs that aren't
in the table to still have working altivec support in the kernel.

It also fixes a problem where if a CPU isn't recognized as having altivec
features, and takes an altivec unavailable exception due to userland
issuing altivec instructions, the kernel would happily enable it and
context switch the registers ...  but not all of them (it would basically
forget vrsave).  With this patch, the kernel will refuse to enable altivec
when the feature isn't detected for the CPU (SIGILL).

Signed-off-by: Benjamin Herrenschmidt <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>

 ppc64/kernel/head.S  |    2 ++
 ppc64/kernel/prom.c  |   19 ++++++++++++++++++-
 ppc64/kernel/traps.c |    2 --
 3 files changed, 20 insertions(+), 3 deletions(-)

Index: arch/ppc64/kernel/head.S
===================================================================
--- e21a5ce886975623d07add60beb223e6f36bab80/arch/ppc64/kernel/head.S  
(mode:100644 sha1:fe05f3fbf9d059c623c3dc3fb02d9fd18f27b4ca)
+++ d5f1ae0d320e6325ed056469773e855fc635c53d/arch/ppc64/kernel/head.S  
(mode:100644 sha1:92a744c31ab183b2aec6e4532a593cef614bba13)
@@ -922,7 +922,9 @@
 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
Index: arch/ppc64/kernel/prom.c
===================================================================
--- e21a5ce886975623d07add60beb223e6f36bab80/arch/ppc64/kernel/prom.c  
(mode:100644 sha1:01739d5c47c7c0d9897ed04fd8597a80714a0fcd)
+++ d5f1ae0d320e6325ed056469773e855fc635c53d/arch/ppc64/kernel/prom.c  
(mode:100644 sha1:b08aac68baff4a3c2b59f3337ea4b98cf60b64a3)
@@ -885,6 +885,7 @@
                                          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 @@
                }
        }
 
+       /* 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 @@
 
        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
Index: arch/ppc64/kernel/traps.c
===================================================================
--- e21a5ce886975623d07add60beb223e6f36bab80/arch/ppc64/kernel/traps.c  
(mode:100644 sha1:10fc61f3f6a430efbad91835eedcb787bad9a6bf)
+++ d5f1ae0d320e6325ed056469773e855fc635c53d/arch/ppc64/kernel/traps.c  
(mode:100644 sha1:7e52cb2605e02bbf96be3a07e0b2872d8ce12e15)
@@ -450,14 +450,12 @@
 
 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);
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to