patch-2.3.99-pre7 linux/arch/ppc/kernel/align.c

Next file: linux/arch/ppc/kernel/feature.c
Previous file: linux/arch/ppc/kernel/Makefile
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.99-pre6/linux/arch/ppc/kernel/align.c linux/arch/ppc/kernel/align.c
@@ -14,6 +14,7 @@
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
+#include <asm/cache.h>
 
 struct aligninfo {
 	unsigned char len;
@@ -38,6 +39,8 @@
 #define S	0x40	/* single-precision fp, or byte-swap value */
 #define HARD	0x80	/* string, stwcx. */
 
+#define DCBZ	0x5f	/* 8xx/82xx dcbz faults when cache not enabled */
+
 /*
  * The PowerPC stores certain bits of the instruction that caused the
  * alignment exception in the DSISR register.  This array maps those
@@ -220,9 +223,27 @@
 	areg = regs->dsisr & 0x1f;		/* register to update */
 	instr = (regs->dsisr >> 10) & 0x7f;
 #endif
+
 	nb = aligninfo[instr].len;
-	if (nb == 0)
-		return 0;	/* too hard or invalid instruction bits */
+	if (nb == 0) {
+		long *p;
+		int i;
+
+		if (instr != DCBZ)
+			return 0;	/* too hard or invalid instruction */
+		/*
+		 * The dcbz (data cache block zero) instruction
+		 * gives an alignment fault if used on non-cacheable
+		 * memory.  We handle the fault mainly for the
+		 * case when we are running with the cache disabled
+		 * for debugging.
+		 */
+		p = (long *) (regs->dar & -L1_CACHE_BYTES);
+		for (i = 0; i < L1_CACHE_BYTES / sizeof(long); ++i)
+			p[i] = 0;
+		return 1;
+	}
+
 	flags = aligninfo[instr].flags;
 
 	/* For the 4xx-family processors, the 'dar' field of the

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)