Skip to contentSkip to conversation

powerpc: Merge align.c (#2)

PATCH In review Benjamin Herrenschmidt 2 participants 2 messages Nov 15, 2005 – Nov 16, 2005 PowerPC

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 powerpc: Merge align.c (#2)

Need testing !!!

This patch merges align.c, the result isn't quite what was in ppc64 nor what was in ppc32 :) It should implement all the functionalities of both though. Kumar, since you played with that in the past, I suppose you have some test cases for verifying that it works properly before I dig out the 601 machine ? :)

Since it's likely that I won't be able to test all scenario, code inspection is much welcome.

---

No difference, just rebased on current -git

arch/powerpc/kernel/Makefile +1 -1
Index: linux-work/arch/powerpc/kernel/Makefile
===================================================================
@@ -12,7 +12,7 @@
 endif
 
 obj-y				:= semaphore.o cputable.o ptrace.o syscalls.o \
-				   irq.o signal_32.o pmc.o vdso.o
+				   irq.o align.o signal_32.o pmc.o vdso.o
 obj-y				+= vdso32/
 obj-$(CONFIG_PPC64)		+= setup_64.o binfmt_elf32.o sys_ppc32.o \
 				   signal_64.o ptrace32.o systbl.o \
arch/powerpc/kernel/align.c new file +513 -0

513 lines not on this page · raw message

arch/ppc/kernel/Makefile +1 -1
Index: linux-work/arch/ppc/kernel/Makefile
===================================================================
@@ -13,7 +13,7 @@
 extra-y				+= vmlinux.lds
 
 obj-y				:= entry.o traps.o idle.o time.o misc.o \
-					process.o align.o \
+					process.o \
 					setup.o \
 					ppc_htab.o
 obj-$(CONFIG_6xx)		+= l2cr.o cpu_setup_6xx.o
arch/ppc64/kernel/Makefile +1 -1
Index: linux-work/arch/ppc64/kernel/Makefile
===================================================================
@@ -2,6 +2,6 @@
 # Makefile for the linux ppc64 kernel.
 #
 
-obj-y               +=	idle.o align.o
+obj-y               +=	idle.o
 
 obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o
include/asm-powerpc/cputable.h +12 -10
Index: linux-work/include/asm-powerpc/cputable.h
===================================================================
@@ -90,6 +90,7 @@
 #define CPU_FTR_NEED_COHERENT		ASM_CONST(0x0000000000020000)
 #define CPU_FTR_NO_BTIC			ASM_CONST(0x0000000000040000)
 #define CPU_FTR_BIG_PHYS		ASM_CONST(0x0000000000080000)
+#define CPU_FTR_NODSISRALIGN  		ASM_CONST(0x0000000000100000)
 
 #ifdef __powerpc64__
 /* Add the 64b processor unique features in the top half of the word */
@@ -97,7 +98,6 @@
 #define CPU_FTR_16M_PAGE      		ASM_CONST(0x0000000200000000)
 #define CPU_FTR_TLBIEL         		ASM_CONST(0x0000000400000000)
 #define CPU_FTR_NOEXECUTE     		ASM_CONST(0x0000000800000000)
-#define CPU_FTR_NODSISRALIGN  		ASM_CONST(0x0000001000000000)
 #define CPU_FTR_IABR  			ASM_CONST(0x0000002000000000)
 #define CPU_FTR_MMCRA  			ASM_CONST(0x0000004000000000)
 #define CPU_FTR_CTRL			ASM_CONST(0x0000008000000000)
@@ -113,7 +113,6 @@
 #define CPU_FTR_16M_PAGE      		ASM_CONST(0x0)
 #define CPU_FTR_TLBIEL         		ASM_CONST(0x0)
 #define CPU_FTR_NOEXECUTE     		ASM_CONST(0x0)
-#define CPU_FTR_NODSISRALIGN  		ASM_CONST(0x0)
 #define CPU_FTR_IABR  			ASM_CONST(0x0)
 #define CPU_FTR_MMCRA  			ASM_CONST(0x0)
 #define CPU_FTR_CTRL			ASM_CONST(0x0)
@@ -273,18 +272,21 @@
 	CPU_FTRS_POWER3_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
 	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
 	CPU_FTRS_POWER4_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
-	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE,
+	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_NODSISRALIGN,
 	CPU_FTRS_970_32 = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE |
 	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_ALTIVEC_COMP |
-	    CPU_FTR_MAYBE_CAN_NAP,
+	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN,
 	CPU_FTRS_8XX = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
-	CPU_FTRS_40X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
-	CPU_FTRS_44X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
-	CPU_FTRS_E200 = CPU_FTR_USE_TB,
-	CPU_FTRS_E500 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
+	CPU_FTRS_40X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+	    CPU_FTR_NODSISRALIGN,
+	CPU_FTRS_44X = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+	    CPU_FTR_NODSISRALIGN,
+	CPU_FTRS_E200 = CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN,
+	CPU_FTRS_E500 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+	    CPU_FTR_NODSISRALIGN,
 	CPU_FTRS_E500_2 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
-	    CPU_FTR_BIG_PHYS,
-	CPU_FTRS_GENERIC_32 = CPU_FTR_COMMON,
+	    CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN,
+	CPU_FTRS_GENERIC_32 = CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN,
 #ifdef __powerpc64__
 	CPU_FTRS_POWER3 = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR,
arch/ppc64/kernel/align.c deleted +0 -396

396 lines not on this page · raw message

#1 lore raw
Quoted 2 lines · Benjamin Herrenschmidt

Since it's likely that I won't be able to test all scenario, code inspection is much welcome.

I think you need this patch on top...

Paul.

arch/powerpc/kernel/align.c +33 -16
diff -urN powerpc/arch/powerpc/kernel/align.c merge-hack/arch/powerpc/kernel/align.c
@@ -198,21 +198,20 @@
 	/* bits  6:15 --> 22:31 */
 	dsisr = (instr & 0x03ff0000) >> 16;
 
-	if ( IS_XFORM(instr) ) {
+	if (IS_XFORM(instr)) {
 		/* bits 29:30 --> 15:16 */
 		dsisr |= (instr & 0x00000006) << 14;
 		/* bit     25 -->    17 */
 		dsisr |= (instr & 0x00000040) << 8;
 		/* bits 21:24 --> 18:21 */
 		dsisr |= (instr & 0x00000780) << 3;
-	}
-	else {
+	} else {
 		/* bit      5 -->    17 */
 		dsisr |= (instr & 0x04000000) >> 12;
 		/* bits  1: 4 --> 18:21 */
 		dsisr |= (instr & 0x78000000) >> 17;
 		/* bits 30:31 --> 12:13 */
-		if ( IS_DSFORM(instr) )
+		if (IS_DSFORM(instr))
 			dsisr |= (instr & 0x00000003) << 18;
 	}
 
@@ -247,13 +246,22 @@
 
 /*
  * Emulate load & store multiple instructions
+ * On 64-bit machines, these instructions only affect/use the
+ * bottom 4 bytes of each register, and the loads clear the
+ * top 4 bytes of the affected register.
  */
+#ifdef CONFIG_PPC64
+#define REG_BYTE(rp, i)		*((u8 *)((rp) + ((i) >> 2)) + ((i) & 3) + 4)
+#else
+#define REG_BYTE(rp, i)		*((u8 *)(rp) + (i))
+#endif
+
 static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
 			    unsigned int reg, unsigned int nb,
 			    unsigned int flags, unsigned int instr)
 {
-	unsigned char *rptr;
-	int nb0, i;
+	unsigned long *rptr;
+	unsigned int nb0, i;
 
 	/*
 	 * We do not try to emulate 8 bytes multiple as they aren't really
@@ -291,29 +299,38 @@
 	if (!access_ok((flags & ST ? VERIFY_WRITE: VERIFY_READ), addr, nb+nb0))
 		return -EFAULT;	/* bad address */
 
-	rptr = (unsigned char *) &regs->gpr[reg];
+	rptr = &regs->gpr[reg];
 	if (flags & LD) {
+		/*
+		 * This zeroes the top 4 bytes of the affected registers
+		 * in 64-bit mode, and also zeroes out any remaining
+		 * bytes of the last register for lsw*.
+		 */
+		memset(rptr, 0, ((nb + 3) / 4) * sizeof(unsigned long));
+		if (nb0 > 0)
+			memset(&regs->gpr[0], 0,
+			       ((nb0 + 3) / 4) * sizeof(unsigned long));
+
 		for (i = 0; i < nb; ++i)
-			if (__get_user(rptr[i], addr + i))
+			if (__get_user(REG_BYTE(rptr, i), addr + i))
 				return -EFAULT;
 		if (nb0 > 0) {
-			rptr = (unsigned char *) &regs->gpr[0];
+			rptr = &regs->gpr[0];
 			addr += nb;
 			for (i = 0; i < nb0; ++i)
-				if (__get_user(rptr[i], addr + i))
+				if (__get_user(REG_BYTE(rptr, i), addr + i))
 					return -EFAULT;
 		}
-		for (; (i & 3) != 0; ++i)
-			rptr[i] = 0;
+
 	} else {
 		for (i = 0; i < nb; ++i)
-			if (__put_user(rptr[i], addr + i))
+			if (__put_user(REG_BYTE(rptr, i), addr + i))
 				return -EFAULT;
 		if (nb0 > 0) {
-			rptr = (unsigned char *) &regs->gpr[0];
+			rptr = &regs->gpr[0];
 			addr += nb;
 			for (i = 0; i < nb0; ++i)
-				if (__put_user(rptr[i], addr + i))
+				if (__put_user(REG_BYTE(rptr, i), addr + i))
 					return -EFAULT;
 		}
 	}
@@ -338,7 +355,7 @@
 	unsigned char __user *p;
 	int ret, t;
 	union {
-		long ll;
+		u64 ll;
 		double dd;
 		unsigned char v[8];
 		struct {