565 lines
12 KiB
Diff
565 lines
12 KiB
Diff
From a9faf34ba120d9d39ff0c7656ee3de12a110e22a Mon Sep 17 00:00:00 2001
|
|
From: Kurt Mahan <kmahan@freescale.com>
|
|
Date: Wed, 31 Oct 2007 16:57:05 -0600
|
|
Subject: [PATCH] Core Coldfire/MCF5445x arch lib changes.
|
|
|
|
LTIBName: mcfv4e-arch-lib-mods
|
|
Signed-off-by: Kurt Mahan <kmahan@freescale.com>
|
|
---
|
|
arch/m68k/lib/checksum.c | 124 +++++++++++++++++++++++
|
|
arch/m68k/lib/muldi3.c | 10 ++
|
|
arch/m68k/lib/semaphore.S | 25 +++++
|
|
arch/m68k/lib/string.c | 64 ++++++++++++
|
|
arch/m68k/lib/uaccess.c | 242 +++++++++++++++++++++++++++++++++++++++++++++
|
|
5 files changed, 465 insertions(+), 0 deletions(-)
|
|
|
|
--- a/arch/m68k/lib/checksum.c
|
|
+++ b/arch/m68k/lib/checksum.c
|
|
@@ -39,8 +39,131 @@
|
|
* computes a partial checksum, e.g. for TCP/UDP fragments
|
|
*/
|
|
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+
|
|
+static inline unsigned short from32to16(unsigned long x)
|
|
+{
|
|
+ /* add up 16-bit and 16-bit for 16+c bit */
|
|
+ x = (x & 0xffff) + (x >> 16);
|
|
+ /* add up carry.. */
|
|
+ x = (x & 0xffff) + (x >> 16);
|
|
+ return x;
|
|
+}
|
|
+
|
|
+static unsigned long do_csum(const unsigned char *buff, int len)
|
|
+{
|
|
+ int odd, count;
|
|
+ unsigned long result = 0;
|
|
+
|
|
+ if (len <= 0)
|
|
+ goto out;
|
|
+ odd = 1 & (unsigned long) buff;
|
|
+ if (odd) {
|
|
+ result = *buff;
|
|
+ len--;
|
|
+ buff++;
|
|
+ }
|
|
+ count = len >> 1; /* nr of 16-bit words.. */
|
|
+ if (count) {
|
|
+ if (2 & (unsigned long) buff) {
|
|
+ result += *(unsigned short *) buff;
|
|
+ count--;
|
|
+ len -= 2;
|
|
+ buff += 2;
|
|
+ }
|
|
+ count >>= 1; /* nr of 32-bit words.. */
|
|
+ if (count) {
|
|
+ unsigned long carry = 0;
|
|
+ do {
|
|
+ unsigned long w = *(unsigned long *) buff;
|
|
+ count--;
|
|
+ buff += 4;
|
|
+ result += carry;
|
|
+ result += w;
|
|
+ carry = (w > result);
|
|
+ } while (count);
|
|
+ result += carry;
|
|
+ result = (result & 0xffff) + (result >> 16);
|
|
+ }
|
|
+ if (len & 2) {
|
|
+ result += *(unsigned short *) buff;
|
|
+ buff += 2;
|
|
+ }
|
|
+ }
|
|
+ if (len & 1)
|
|
+ result += (*buff << 8);
|
|
+ result = from32to16(result);
|
|
+ if (odd)
|
|
+ result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
|
|
+out:
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * This is a version of ip_compute_csum() optimized for IP headers,
|
|
+ * which always checksum on 4 octet boundaries.
|
|
+ */
|
|
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
|
|
+{
|
|
+ return ~do_csum(iph, ihl*4);
|
|
+}
|
|
+EXPORT_SYMBOL(ip_fast_csum);
|
|
+
|
|
+/*
|
|
+ * computes the checksum of a memory block at buff, length len,
|
|
+ * and adds in "sum" (32-bit)
|
|
+ *
|
|
+ * returns a 32-bit number suitable for feeding into itself
|
|
+ * or csum_tcpudp_magic
|
|
+ *
|
|
+ * this function must be called with even lengths, except
|
|
+ * for the last fragment, which may be odd
|
|
+ *
|
|
+ * it's best to have buff aligned on a 32-bit boundary
|
|
+ */
|
|
__wsum csum_partial(const void *buff, int len, __wsum sum)
|
|
{
|
|
+ unsigned int result = do_csum(buff, len);
|
|
+
|
|
+ /* add in old sum, and carry.. */
|
|
+ result += sum;
|
|
+ if (sum > result)
|
|
+ result += 1;
|
|
+ return result;
|
|
+}
|
|
+EXPORT_SYMBOL(csum_partial);
|
|
+
|
|
+/*
|
|
+ * copy from fs while checksumming, otherwise like csum_partial
|
|
+ */
|
|
+
|
|
+__wsum
|
|
+csum_partial_copy_from_user(const void __user *src, void *dst, int len,
|
|
+ __wsum sum, int *csum_err)
|
|
+{
|
|
+ if (csum_err) *csum_err = 0;
|
|
+ memcpy(dst, src, len);
|
|
+ return csum_partial(dst, len, sum);
|
|
+}
|
|
+EXPORT_SYMBOL(csum_partial_copy_from_user);
|
|
+
|
|
+/*
|
|
+ * copy from ds while checksumming, otherwise like csum_partial
|
|
+ */
|
|
+
|
|
+__wsum
|
|
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
|
|
+{
|
|
+ memcpy(dst, src, len);
|
|
+ return csum_partial(dst, len, sum);
|
|
+}
|
|
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
|
|
+
|
|
+#else /* !CONFIG_COLDFIRE */
|
|
+
|
|
+unsigned int
|
|
+csum_partial(const unsigned char *buff, int len, unsigned int sum)
|
|
+{
|
|
unsigned long tmp1, tmp2;
|
|
/*
|
|
* Experiments with ethernet and slip connections show that buff
|
|
@@ -423,3 +546,4 @@ csum_partial_copy_nocheck(const void *sr
|
|
return(sum);
|
|
}
|
|
EXPORT_SYMBOL(csum_partial_copy_nocheck);
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
--- a/arch/m68k/lib/muldi3.c
|
|
+++ b/arch/m68k/lib/muldi3.c
|
|
@@ -21,12 +21,22 @@ Boston, MA 02111-1307, USA. */
|
|
|
|
#define BITS_PER_UNIT 8
|
|
|
|
+#ifdef CONFIG_COLDFIRE
|
|
+#define umul_ppmm(w1, w0, u, v) \
|
|
+ do { \
|
|
+ unsigned long long x; \
|
|
+ x = (unsigned long long)u * v; \
|
|
+ w0 = (unsigned long)(x & 0x00000000ffffffff); \
|
|
+ w1 = (unsigned long)(x & 0xffffffff00000000) >> 32; \
|
|
+ } while (0)
|
|
+#else /* CONFIG_COLDFIRE */
|
|
#define umul_ppmm(w1, w0, u, v) \
|
|
__asm__ ("mulu%.l %3,%1:%0" \
|
|
: "=d" ((USItype)(w0)), \
|
|
"=d" ((USItype)(w1)) \
|
|
: "%0" ((USItype)(u)), \
|
|
"dmi" ((USItype)(v)))
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
|
|
#define __umulsidi3(u, v) \
|
|
({DIunion __w; \
|
|
--- a/arch/m68k/lib/semaphore.S
|
|
+++ b/arch/m68k/lib/semaphore.S
|
|
@@ -16,11 +16,24 @@
|
|
* there is contention on the semaphore.
|
|
*/
|
|
ENTRY(__down_failed)
|
|
+#ifndef CONFIG_COLDFIRE
|
|
moveml %a0/%d0/%d1,-(%sp)
|
|
+#else
|
|
+ movel %a0,-(%sp)
|
|
+ movel %d0,-(%sp)
|
|
+ movel %d1,-(%sp)
|
|
+#endif
|
|
movel %a1,-(%sp)
|
|
jbsr __down
|
|
movel (%sp)+,%a1
|
|
+#ifndef CONFIG_COLDFIRE
|
|
moveml (%sp)+,%a0/%d0/%d1
|
|
+#else
|
|
+ movel (%sp)+,%d1
|
|
+ movel (%sp)+,%d0
|
|
+ movel (%sp)+,%a0
|
|
+#endif
|
|
+
|
|
rts
|
|
|
|
ENTRY(__down_failed_interruptible)
|
|
@@ -44,10 +57,22 @@ ENTRY(__down_failed_trylock)
|
|
rts
|
|
|
|
ENTRY(__up_wakeup)
|
|
+#ifndef CONFIG_COLDFIRE
|
|
moveml %a0/%d0/%d1,-(%sp)
|
|
+#else
|
|
+ movel %a0,-(%sp)
|
|
+ movel %d0,-(%sp)
|
|
+ movel %d1,-(%sp)
|
|
+#endif
|
|
movel %a1,-(%sp)
|
|
jbsr __up
|
|
movel (%sp)+,%a1
|
|
+#ifndef CONFIG_COLDFIRE
|
|
moveml (%sp)+,%a0/%d0/%d1
|
|
+#else
|
|
+ movel (%sp)+,%d1
|
|
+ movel (%sp)+,%d0
|
|
+ movel (%sp)+,%a0
|
|
+#endif
|
|
rts
|
|
|
|
--- a/arch/m68k/lib/string.c
|
|
+++ b/arch/m68k/lib/string.c
|
|
@@ -15,6 +15,7 @@ char *strcpy(char *dest, const char *src
|
|
}
|
|
EXPORT_SYMBOL(strcpy);
|
|
|
|
+#ifndef CONFIG_COLDFIRE
|
|
void *memset(void *s, int c, size_t count)
|
|
{
|
|
void *xs = s;
|
|
@@ -143,6 +144,69 @@ void *memcpy(void *to, const void *from,
|
|
}
|
|
EXPORT_SYMBOL(memcpy);
|
|
|
|
+#else /* CONFIG_COLDFIRE */
|
|
+
|
|
+void *memset(void *s, int c, size_t count)
|
|
+{
|
|
+ unsigned long x;
|
|
+ void *originalTo;
|
|
+
|
|
+ for (x = 0; x < count; x++)
|
|
+ *(unsigned char *)s++ = (unsigned char)c;
|
|
+
|
|
+ return originalTo;
|
|
+}
|
|
+EXPORT_SYMBOL(memset);
|
|
+
|
|
+void *memcpy(void *to, const void *from, size_t n)
|
|
+{
|
|
+ void *xto = to;
|
|
+ size_t temp;
|
|
+
|
|
+ if (!n)
|
|
+ return xto;
|
|
+ if ((long) to & 1) {
|
|
+ char *cto = to;
|
|
+ const char *cfrom = from;
|
|
+ *cto++ = *cfrom++;
|
|
+ to = cto;
|
|
+ from = cfrom;
|
|
+ n--;
|
|
+ }
|
|
+ if (n > 2 && (long) to & 2) {
|
|
+ short *sto = to;
|
|
+ const short *sfrom = from;
|
|
+ *sto++ = *sfrom++;
|
|
+ to = sto;
|
|
+ from = sfrom;
|
|
+ n -= 2;
|
|
+ }
|
|
+ temp = n >> 2;
|
|
+ if (temp) {
|
|
+ long *lto = to;
|
|
+ const long *lfrom = from;
|
|
+ for (; temp; temp--)
|
|
+ *lto++ = *lfrom++;
|
|
+ to = lto;
|
|
+ from = lfrom;
|
|
+ }
|
|
+ if (n & 2) {
|
|
+ short *sto = to;
|
|
+ const short *sfrom = from;
|
|
+ *sto++ = *sfrom++;
|
|
+ to = sto;
|
|
+ from = sfrom;
|
|
+ }
|
|
+ if (n & 1) {
|
|
+ char *cto = to;
|
|
+ const char *cfrom = from;
|
|
+ *cto = *cfrom;
|
|
+ }
|
|
+ return xto;
|
|
+}
|
|
+EXPORT_SYMBOL(memcpy);
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
+
|
|
void *memmove(void *dest, const void *src, size_t n)
|
|
{
|
|
void *xdest = dest;
|
|
--- a/arch/m68k/lib/uaccess.c
|
|
+++ b/arch/m68k/lib/uaccess.c
|
|
@@ -5,6 +5,7 @@
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
+#ifndef CONFIG_COLDFIRE
|
|
#include <asm/uaccess.h>
|
|
|
|
unsigned long __generic_copy_from_user(void *to, const void __user *from,
|
|
@@ -220,3 +221,244 @@ unsigned long __clear_user(void __user *
|
|
return res;
|
|
}
|
|
EXPORT_SYMBOL(__clear_user);
|
|
+
|
|
+#else /* CONFIG_COLDFIRE */
|
|
+
|
|
+#include <asm/cf_uaccess.h>
|
|
+
|
|
+unsigned long __generic_copy_from_user(void *to, const void *from,
|
|
+ unsigned long n)
|
|
+{
|
|
+ unsigned long tmp;
|
|
+ __asm__ __volatile__
|
|
+ (" tstl %2\n"
|
|
+ " jeq 2f\n"
|
|
+ "1: movel (%1)+,%3\n"
|
|
+ " movel %3,(%0)+\n"
|
|
+ " subql #1,%2\n"
|
|
+ " jne 1b\n"
|
|
+ "2: movel %4,%2\n"
|
|
+ " bclr #1,%2\n"
|
|
+ " jeq 4f\n"
|
|
+ "3: movew (%1)+,%3\n"
|
|
+ " movew %3,(%0)+\n"
|
|
+ "4: bclr #0,%2\n"
|
|
+ " jeq 6f\n"
|
|
+ "5: moveb (%1)+,%3\n"
|
|
+ " moveb %3,(%0)+\n"
|
|
+ "6:\n"
|
|
+ ".section .fixup,\"ax\"\n"
|
|
+ " .even\n"
|
|
+ "7: movel %2,%%d0\n"
|
|
+ "71:clrl (%0)+\n"
|
|
+ " subql #1,%%d0\n"
|
|
+ " jne 71b\n"
|
|
+ " lsll #2,%2\n"
|
|
+ " addl %4,%2\n"
|
|
+ " btst #1,%4\n"
|
|
+ " jne 81f\n"
|
|
+ " btst #0,%4\n"
|
|
+ " jne 91f\n"
|
|
+ " jra 6b\n"
|
|
+ "8: addql #2,%2\n"
|
|
+ "81:clrw (%0)+\n"
|
|
+ " btst #0,%4\n"
|
|
+ " jne 91f\n"
|
|
+ " jra 6b\n"
|
|
+ "9: addql #1,%2\n"
|
|
+ "91:clrb (%0)+\n"
|
|
+ " jra 6b\n"
|
|
+ ".previous\n"
|
|
+ ".section __ex_table,\"a\"\n"
|
|
+ " .align 4\n"
|
|
+ " .long 1b,7b\n"
|
|
+ " .long 3b,8b\n"
|
|
+ " .long 5b,9b\n"
|
|
+ ".previous"
|
|
+ : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
|
|
+ : "d"(n & 3), "0"(to), "1"(from), "2"(n/4)
|
|
+ : "d0", "memory");
|
|
+ return n;
|
|
+}
|
|
+EXPORT_SYMBOL(__generic_copy_from_user);
|
|
+
|
|
+
|
|
+unsigned long __generic_copy_to_user(void *to, const void *from,
|
|
+ unsigned long n)
|
|
+{
|
|
+ unsigned long tmp;
|
|
+ __asm__ __volatile__
|
|
+ (" tstl %2\n"
|
|
+ " jeq 3f\n"
|
|
+ "1: movel (%1)+,%3\n"
|
|
+ "22:movel %3,(%0)+\n"
|
|
+ "2: subql #1,%2\n"
|
|
+ " jne 1b\n"
|
|
+ "3: movel %4,%2\n"
|
|
+ " bclr #1,%2\n"
|
|
+ " jeq 4f\n"
|
|
+ " movew (%1)+,%3\n"
|
|
+ "24:movew %3,(%0)+\n"
|
|
+ "4: bclr #0,%2\n"
|
|
+ " jeq 5f\n"
|
|
+ " moveb (%1)+,%3\n"
|
|
+ "25:moveb %3,(%0)+\n"
|
|
+ "5:\n"
|
|
+ ".section .fixup,\"ax\"\n"
|
|
+ " .even\n"
|
|
+ "60:addql #1,%2\n"
|
|
+ "6: lsll #2,%2\n"
|
|
+ " addl %4,%2\n"
|
|
+ " jra 5b\n"
|
|
+ "7: addql #2,%2\n"
|
|
+ " jra 5b\n"
|
|
+ "8: addql #1,%2\n"
|
|
+ " jra 5b\n"
|
|
+ ".previous\n"
|
|
+ ".section __ex_table,\"a\"\n"
|
|
+ " .align 4\n"
|
|
+ " .long 1b,60b\n"
|
|
+ " .long 22b,6b\n"
|
|
+ " .long 2b,6b\n"
|
|
+ " .long 24b,7b\n"
|
|
+ " .long 3b,60b\n"
|
|
+ " .long 4b,7b\n"
|
|
+ " .long 25b,8b\n"
|
|
+ " .long 5b,8b\n"
|
|
+ ".previous"
|
|
+ : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
|
|
+ : "r"(n & 3), "0"(to), "1"(from), "2"(n / 4)
|
|
+ : "memory");
|
|
+ return n;
|
|
+}
|
|
+EXPORT_SYMBOL(__generic_copy_to_user);
|
|
+
|
|
+/*
|
|
+ * Copy a null terminated string from userspace.
|
|
+ */
|
|
+
|
|
+long strncpy_from_user(char *dst, const char *src, long count)
|
|
+{
|
|
+ long res = -EFAULT;
|
|
+ if (!(access_ok(VERIFY_READ, src, 1))) /* --tym-- */
|
|
+ return res;
|
|
+ if (count == 0) return count;
|
|
+ __asm__ __volatile__
|
|
+ ("1: moveb (%2)+,%%d0\n"
|
|
+ "12:moveb %%d0,(%1)+\n"
|
|
+ " jeq 2f\n"
|
|
+ " subql #1,%3\n"
|
|
+ " jne 1b\n"
|
|
+ "2: subl %3,%0\n"
|
|
+ "3:\n"
|
|
+ ".section .fixup,\"ax\"\n"
|
|
+ " .even\n"
|
|
+ "4: movel %4,%0\n"
|
|
+ " jra 3b\n"
|
|
+ ".previous\n"
|
|
+ ".section __ex_table,\"a\"\n"
|
|
+ " .align 4\n"
|
|
+ " .long 1b,4b\n"
|
|
+ " .long 12b,4b\n"
|
|
+ ".previous"
|
|
+ : "=d"(res), "=a"(dst), "=a"(src), "=d"(count)
|
|
+ : "i"(-EFAULT), "0"(count), "1"(dst), "2"(src), "3"(count)
|
|
+ : "d0", "memory");
|
|
+ return res;
|
|
+}
|
|
+EXPORT_SYMBOL(strncpy_from_user);
|
|
+
|
|
+/*
|
|
+ * Return the size of a string (including the ending 0)
|
|
+ *
|
|
+ * Return 0 on exception, a value greater than N if too long
|
|
+ */
|
|
+long strnlen_user(const char *src, long n)
|
|
+{
|
|
+ long res = -EFAULT;
|
|
+ if (!(access_ok(VERIFY_READ, src, 1))) /* --tym-- */
|
|
+ return res;
|
|
+
|
|
+ res = -(long)src;
|
|
+ __asm__ __volatile__
|
|
+ ("1:\n"
|
|
+ " tstl %2\n"
|
|
+ " jeq 3f\n"
|
|
+ "2: moveb (%1)+,%%d0\n"
|
|
+ "22:\n"
|
|
+ " subql #1,%2\n"
|
|
+ " tstb %%d0\n"
|
|
+ " jne 1b\n"
|
|
+ " jra 4f\n"
|
|
+ "3:\n"
|
|
+ " addql #1,%0\n"
|
|
+ "4:\n"
|
|
+ " addl %1,%0\n"
|
|
+ "5:\n"
|
|
+ ".section .fixup,\"ax\"\n"
|
|
+ " .even\n"
|
|
+ "6: moveq %3,%0\n"
|
|
+ " jra 5b\n"
|
|
+ ".previous\n"
|
|
+ ".section __ex_table,\"a\"\n"
|
|
+ " .align 4\n"
|
|
+ " .long 2b,6b\n"
|
|
+ " .long 22b,6b\n"
|
|
+ ".previous"
|
|
+ : "=d"(res), "=a"(src), "=d"(n)
|
|
+ : "i"(0), "0"(res), "1"(src), "2"(n)
|
|
+ : "d0");
|
|
+ return res;
|
|
+}
|
|
+EXPORT_SYMBOL(strnlen_user);
|
|
+
|
|
+
|
|
+/*
|
|
+ * Zero Userspace
|
|
+ */
|
|
+
|
|
+unsigned long __clear_user(void *to, unsigned long n)
|
|
+{
|
|
+ __asm__ __volatile__
|
|
+ (" tstl %1\n"
|
|
+ " jeq 3f\n"
|
|
+ "1: movel %3,(%0)+\n"
|
|
+ "2: subql #1,%1\n"
|
|
+ " jne 1b\n"
|
|
+ "3: movel %2,%1\n"
|
|
+ " bclr #1,%1\n"
|
|
+ " jeq 4f\n"
|
|
+ "24:movew %3,(%0)+\n"
|
|
+ "4: bclr #0,%1\n"
|
|
+ " jeq 5f\n"
|
|
+ "25:moveb %3,(%0)+\n"
|
|
+ "5:\n"
|
|
+ ".section .fixup,\"ax\"\n"
|
|
+ " .even\n"
|
|
+ "61:addql #1,%1\n"
|
|
+ "6: lsll #2,%1\n"
|
|
+ " addl %2,%1\n"
|
|
+ " jra 5b\n"
|
|
+ "7: addql #2,%1\n"
|
|
+ " jra 5b\n"
|
|
+ "8: addql #1,%1\n"
|
|
+ " jra 5b\n"
|
|
+ ".previous\n"
|
|
+ ".section __ex_table,\"a\"\n"
|
|
+ " .align 4\n"
|
|
+ " .long 1b,61b\n"
|
|
+ " .long 2b,6b\n"
|
|
+ " .long 3b,61b\n"
|
|
+ " .long 24b,7b\n"
|
|
+ " .long 4b,7b\n"
|
|
+ " .long 25b,8b\n"
|
|
+ " .long 5b,8b\n"
|
|
+ ".previous"
|
|
+ : "=a"(to), "=d"(n)
|
|
+ : "r"(n & 3), "d"(0), "0"(to), "1"(n/4));
|
|
+ return n;
|
|
+}
|
|
+EXPORT_SYMBOL(__clear_user);
|
|
+
|
|
+#endif /* CONFIG_COLDFIRE */
|
|
+
|