Subject: 64bit unaligned access on 32bit kernel

From: Atsushi Nemoto <[email-masked]>
Date: Thu, 25 Aug 2005 00:35:48 +0900 (JST)

MIPS kernel has been using asm-generic/unaligned.h since 2.6.12-rc2.
But the generic unaligned.h is not suitable for 32bit kernel because
it uses 'unsigned long' for 64bit values.

How about this fix?

diff -u linux-mips/include/asm-generic/unaligned.h linux/include/asm-generic/unaligned.h
--- linux-mips/include/asm-generic/unaligned.h	2005-05-28 00:40:52.000000000 +0900
+++ linux/include/asm-generic/unaligned.h	2005-08-25 00:26:14.359013720 +0900
@@ -18,7 +18,7 @@
 #define get_unaligned(ptr) \
 	((__typeof__(*(ptr)))__get_unaligned((ptr), sizeof(*(ptr))))
 #define put_unaligned(x,ptr) \
-	__put_unaligned((unsigned long)(x), (ptr), sizeof(*(ptr)))
+	__put_unaligned((__u64)(x), (ptr), sizeof(*(ptr)))
 
 /*
  * This function doesn't actually exist.  The idea is that when
@@ -36,19 +36,19 @@
  * Elemental unaligned loads 
  */
 
-static inline unsigned long __uldq(const __u64 *addr)
+static inline __u64 __uldq(const __u64 *addr)
 {
 	const struct __una_u64 *ptr = (const struct __una_u64 *) addr;
 	return ptr->x;
 }
 
-static inline unsigned long __uldl(const __u32 *addr)
+static inline __u64 __uldl(const __u32 *addr)
 {
 	const struct __una_u32 *ptr = (const struct __una_u32 *) addr;
 	return ptr->x;
 }
 
-static inline unsigned long __uldw(const __u16 *addr)
+static inline __u64 __uldw(const __u16 *addr)
 {
 	const struct __una_u16 *ptr = (const struct __una_u16 *) addr;
 	return ptr->x;
@@ -78,7 +78,7 @@
 
 #define __get_unaligned(ptr, size) ({		\
 	const void *__gu_p = ptr;		\
-	unsigned long val;			\
+	__u64 val;				\
 	switch (size) {				\
 	case 1:					\
 		val = *(const __u8 *)__gu_p;	\

---

From: Atsushi Nemoto <[email-masked]>
Date: Sat, 27 Aug 2005 22:57:40 +0900 (JST)

>>>>> On Thu, 25 Aug 2005 00:35:48 +0900 (JST), Atsushi Nemoto <[email-masked]> said:

anemo> MIPS kernel has been using asm-generic/unaligned.h since
anemo> 2.6.12-rc2.  But the generic unaligned.h is not suitable for
anemo> 32bit kernel because it uses 'unsigned long' for 64bit values.

FYI, I found this problem while debugging why usbhid does not work
with 2.6.12 kernel (though it worked with 2.6.11) on big endian
platform.  The usbhid use put_unaligned/get_unaligned for __u64
variables.

---
Atsushi Nemoto

---

From: Atsushi Nemoto <[email-masked]>
Date: Sat, 27 Aug 2005 23:54:07 +0900 (JST)

Since This is not MIPS specific, I report it to a bugzilla on kernel.org.

http://bugzilla.kernel.org/show_bug.cgi?id=5138

---
Atsushi Nemoto