patch ppc64-detect-altivec-via-firmware-on-unknown-cpus.patch added to -mm tree

Benjamin Herrenschmidt benh at kernel.crashing.org
Thu Apr 7 17:26:19 EST 2005


On Wed, 2005-04-06 at 01:46 -0700, akpm at osdl.org wrote:
> This is a note to let you know that I've just added the
> patch titled
> 
>      ppc64: Detect altivec via firmware on unknown CPUs
> 
> to the -mm tree.  Its filename is
> 
>      ppc64-detect-altivec-via-firmware-on-unknown-cpus.patch

Hi Andrew !

Please replace it with this new version which fixes a problem if altivec
is not detected by the firmware (or forbidden by it) and we still take a
userland altivec exception. The kernel would have panic'd, this makes
sure the error is only reported to the application.

---

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 <benh at kernel.crashing.org>

Index: linux-work/arch/ppc64/kernel/prom.c
===================================================================
--- linux-work.orig/arch/ppc64/kernel/prom.c	2005-04-06 10:22:10.000000000 +1000
+++ linux-work/arch/ppc64/kernel/prom.c	2005-04-07 17:24:08.000000000 +1000
@@ -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: linux-work/arch/ppc64/kernel/head.S
===================================================================
--- linux-work.orig/arch/ppc64/kernel/head.S	2005-04-03 10:02:55.000000000 +1000
+++ linux-work/arch/ppc64/kernel/head.S	2005-04-06 14:27:19.000000000 +1000
@@ -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: linux-work/arch/ppc64/kernel/traps.c
===================================================================
--- linux-work.orig/arch/ppc64/kernel/traps.c	2005-03-15 11:57:29.000000000 +1100
+++ linux-work/arch/ppc64/kernel/traps.c	2005-04-07 17:24:34.000000000 +1000
@@ -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);





More information about the Linuxppc64-dev mailing list