patch-2.1.25 linux/arch/i386/lib/checksum.c

Next file: linux/drivers/cdrom/isp16.c
Previous file: linux/arch/i386/kernel/vm86.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.24/linux/arch/i386/lib/checksum.c linux/arch/i386/lib/checksum.c
@@ -11,6 +11,9 @@
  *		Lots of code moved from tcp.c and ip.c; see those files
  *		for more names.
  *
+ * Changes:     Ingo Molnar, converted csum_partial_copy() to 2.1 exception
+ *			     handling.
+ *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
  *		as published by the Free Software Foundation; either version
@@ -86,7 +89,7 @@
 	    shll $16,%%ecx
 5:	    movb (%%esi),%%cl
 6:	    addl %%ecx,%%eax
-	    adcl $0, %%eax
+	    adcl $0, %%eax 
 7:	    "
 	: "=a"(sum)
 	: "0"(sum), "c"(len), "S"(buff)
@@ -94,96 +97,228 @@
 	return(sum);
 }
 
+/*
+ * Copy from ds while checksumming, otherwise like csum_partial
+ *
+ * The macros SRC and DST specify wether there should be exception handling
+ * for the source and/or the destination addresses.
+ *
+ * FIXME: could someone double check wether i havent mixed up some SRC and
+ *	  DST definitions? It's damn hard to trigger all cases, i hope i got
+ *	  them all but theres no guarantee ...
+ */
 
+#define csum_partial_copy_type(type) \
+unsigned int csum_partial_copy ##type (int * __csum_err, const char *src, char *dst,   \
+				  int len, int sum) {  \
+    __asm__( 									  \
+"		testl $2, %%edi		# Check alignment. 			\n" \
+"		jz 2f			# Jump if alignment is ok. 		\n" \
+"		subl $2, %%ecx		# Alignment uses up two bytes. 		\n" \
+"		jae 1f			# Jump if we had at least two bytes. 	\n" \
+"		addl $2, %%ecx		# ecx was < 2.  Deal with it. 		\n" \
+"		jmp 4f 								\n" \
+"	1000: 									\n" \
+"	 1:	movw (%%esi), %%bx						\n" \
+"		addl $2, %%esi							\n" \
+"	1001:									\n" \
+"		movw %%bx, (%%edi)						\n" \
+"		addl $2, %%edi							\n" \
+"		addw %%bx, %%ax							\n" \
+"		adcl $0, %%eax							\n" \
+"	2:									\n" \
+"		pushl %%ecx							\n" \
+"		shrl $5, %%ecx							\n" \
+"		jz 2f								\n" \
+"		testl %%esi, %%esi						\n" \
+"	1002:									\n" \
+"	1:	movl (%%esi), %%ebx						\n" \
+"	1003:									\n" \
+"		movl 4(%%esi), %%edx						\n" \
+"		adcl %%ebx, %%eax						\n" \
+"	1004:									\n" \
+"		movl %%ebx, (%%edi)						\n" \
+"		adcl %%edx, %%eax						\n" \
+"	1005:									\n" \
+"		movl %%edx, 4(%%edi)						\n" \
+"	 									\n" \
+"	1006:									\n" \
+"		movl 8(%%esi), %%ebx						\n" \
+"	1007:									\n" \
+"		movl 12(%%esi), %%edx						\n" \
+"		adcl %%ebx, %%eax						\n" \
+"	1008:									\n" \
+"		movl %%ebx, 8(%%edi)						\n" \
+"		adcl %%edx, %%eax						\n" \
+"	1009:									\n" \
+"		movl %%edx, 12(%%edi)						\n" \
+"	 									\n" \
+"	1010: 									\n" \
+"		movl 16(%%esi), %%ebx 						\n" \
+"	1011: 									\n" \
+"		movl 20(%%esi), %%edx						\n" \
+"		adcl %%ebx, %%eax						\n" \
+"	1012:									\n" \
+"		movl %%ebx, 16(%%edi)						\n" \
+"		adcl %%edx, %%eax						\n" \
+"	1013:									\n" \
+"		movl %%edx, 20(%%edi)						\n" \
+"										\n" \
+"	1014:									\n" \
+"		movl 24(%%esi), %%ebx						\n" \
+"	1015:									\n" \
+"		movl 28(%%esi), %%edx						\n" \
+"		adcl %%ebx, %%eax						\n" \
+"	1016:									\n" \
+"		movl %%ebx, 24(%%edi)						\n" \
+"		adcl %%edx, %%eax						\n" \
+"	1017:									\n" \
+"		movl %%edx, 28(%%edi)						\n" \
+"	 									\n" \
+"	1018:									\n" \
+"		lea 32(%%esi), %%esi						\n" \
+"	1019:									\n" \
+"		lea 32(%%edi), %%edi						\n" \
+"		dec %%ecx							\n" \
+"		jne 1b								\n" \
+"		adcl $0, %%eax							\n" \
+"	2:	popl %%edx							\n" \
+"		movl %%edx, %%ecx						\n" \
+"		andl $0x1c, %%edx						\n" \
+"		je 4f								\n" \
+"		shrl $2, %%edx		# This clears CF			\n" \
+"	1020:									\n" \
+"	3:	movl (%%esi), %%ebx						\n" \
+"		adcl %%ebx, %%eax						\n" \
+"	1021:									\n" \
+"		movl %%ebx, (%%edi)						\n" \
+"	1022:									\n" \
+"		lea 4(%%esi), %%esi						\n" \
+"	1023:									\n" \
+"		lea 4(%%edi), %%edi						\n" \
+"		dec %%edx							\n" \
+"		jne 3b								\n" \
+"		adcl $0, %%eax							\n" \
+"	4:	andl $3, %%ecx							\n" \
+"		jz 7f								\n" \
+"		cmpl $2, %%ecx							\n" \
+"		jb 5f								\n" \
+"	1024:									\n" \
+"		movw (%%esi), %%cx						\n" \
+"	1025:									\n" \
+"		leal 2(%%esi), %%esi						\n" \
+"	1026:									\n" \
+"		movw %%cx, (%%edi)						\n" \
+"	1027:									\n" \
+"		leal 2(%%edi), %%edi						\n" \
+"		je 6f								\n" \
+"		shll $16,%%ecx							\n" \
+"	1028:									\n" \
+"	5:	movb (%%esi), %%cl						\n" \
+"	1029:									\n" \
+"		movb %%cl, (%%edi)						\n" \
+"	6:	addl %%ecx, %%eax						\n" \
+"		adcl $0, %%eax							\n" \
+"	7:									\n" \
+"	2000:									\n" \
+"     	   .section .fixup,\"ax\"						\n" \
+"	3000:		movl %7,%1						\n" \
+/* FIXME: zero out the rest of the buffer here !!!!!! */			\
+"		jmp 2000b							\n" \
+"		.previous							\n" \
+"		.section __ex_table,\"a\"					\n" \
+"		.align 4                   					\n" \
+"										\n" \
+SRC(  "        .long 1000b,3000b        \n  "    ) \
+DST(  "        .long 1001b,3000b        \n  "    ) \
+SRC(  "        .long 1002b,3000b        \n  "    ) \
+SRC(  "        .long 1003b,3000b        \n  "    ) \
+DST(  "        .long 1004b,3000b        \n  "    ) \
+DST(  "        .long 1005b,3000b        \n  "    ) \
+SRC(  "        .long 1006b,3000b        \n  "    ) \
+SRC(  "        .long 1007b,3000b        \n  "    ) \
+DST(  "        .long 1008b,3000b        \n  "    ) \
+DST(  "        .long 1009b,3000b        \n  "    ) \
+SRC(  "        .long 1010b,3000b        \n  "    ) \
+SRC(  "        .long 1011b,3000b        \n  "    ) \
+DST(  "        .long 1012b,3000b        \n  "    ) \
+DST(  "        .long 1013b,3000b        \n  "    ) \
+SRC(  "        .long 1014b,3000b        \n  "    ) \
+SRC(  "        .long 1015b,3000b        \n  "    ) \
+DST(  "        .long 1016b,3000b        \n  "    ) \
+DST(  "        .long 1017b,3000b        \n  "    ) \
+SRC(  "        .long 1018b,3000b        \n  "    ) \
+DST(  "        .long 1019b,3000b        \n  "    ) \
+SRC(  "        .long 1020b,3000b        \n  "    ) \
+DST(  "        .long 1021b,3000b        \n  "    ) \
+SRC(  "        .long 1022b,3000b        \n  "    ) \
+DST(  "        .long 1023b,3000b        \n  "    ) \
+SRC(  "        .long 1024b,3000b        \n  "    ) \
+SRC(  "        .long 1025b,3000b        \n  "    ) \
+DST(  "        .long 1026b,3000b        \n  "    ) \
+DST(  "        .long 1027b,3000b        \n  "    ) \
+SRC(  "        .long 1028b,3000b        \n  "    ) \
+DST(  "        .long 1029b,3000b        \n  "    ) \
+"        .previous                      \n  " 				\
+	: "=a" (sum), "=r" (*__csum_err)   				\
+	:  "0" (sum), "c" (len), "S" (src), "D" (dst), 			\
+		"1" (*__csum_err), "i" (-EFAULT)   			\
+	: "bx", "cx", "dx", "si", "di" );  				\
+ 									\
+    return(sum);  							\
+}
 
 /*
- * copy from ds while checksumming, otherwise like csum_partial
+ *  Currently we need only 2 out of the 4 possible type combinations:
  */
 
-unsigned int csum_partial_copy(const char *src, char *dst, 
-				  int len, int sum) {
-    __asm__("
-	testl $2, %%edi		# Check alignment.
-	jz 2f			# Jump if alignment is ok.
-	subl $2, %%ecx		# Alignment uses up two bytes.
-	jae 1f			# Jump if we had at least two bytes.
-	addl $2, %%ecx		# ecx was < 2.  Deal with it.
-	jmp 4f
-1:	movw (%%esi), %%bx
-	addl $2, %%esi
-	movw %%bx, (%%edi)
-	addl $2, %%edi
-	addw %%bx, %%ax
-	adcl $0, %%eax
-2:
-	pushl %%ecx
-	shrl $5, %%ecx
-	jz 2f
-	testl %%esi, %%esi
-1:	movl (%%esi), %%ebx
-	movl 4(%%esi), %%edx
-	adcl %%ebx, %%eax
-	movl %%ebx, (%%edi)
-	adcl %%edx, %%eax
-	movl %%edx, 4(%%edi)
-
-	movl 8(%%esi), %%ebx
-	movl 12(%%esi), %%edx
-	adcl %%ebx, %%eax
-	movl %%ebx, 8(%%edi)
-	adcl %%edx, %%eax
-	movl %%edx, 12(%%edi)
-
-	movl 16(%%esi), %%ebx
-	movl 20(%%esi), %%edx
-	adcl %%ebx, %%eax
-	movl %%ebx, 16(%%edi)
-	adcl %%edx, %%eax
-	movl %%edx, 20(%%edi)
-
-	movl 24(%%esi), %%ebx
-	movl 28(%%esi), %%edx
-	adcl %%ebx, %%eax
-	movl %%ebx, 24(%%edi)
-	adcl %%edx, %%eax
-	movl %%edx, 28(%%edi)
-
-	lea 32(%%esi), %%esi
-	lea 32(%%edi), %%edi
-	dec %%ecx
-	jne 1b
-	adcl $0, %%eax
-2:	popl %%edx
-	movl %%edx, %%ecx
-	andl $0x1c, %%edx
-	je 4f
-	shrl $2, %%edx		# This clears CF
-3:	movl (%%esi), %%ebx
-	adcl %%ebx, %%eax
-	movl %%ebx, (%%edi)
-	lea 4(%%esi), %%esi
-	lea 4(%%edi), %%edi
-	dec %%edx
-	jne 3b
-	adcl $0, %%eax
-4:	andl $3, %%ecx
-	jz 7f
-	cmpl $2, %%ecx
-	jb 5f
-	movw (%%esi), %%cx
-	leal 2(%%esi), %%esi
-	movw %%cx, (%%edi)
-	leal 2(%%edi), %%edi
-	je 6f
-	shll $16,%%ecx
-5:	movb (%%esi), %%cl
-	movb %%cl, (%%edi)
-6:	addl %%ecx, %%eax
-	adcl $0, %%eax
-7:
-	"
-	: "=a" (sum)
-	: "0"(sum), "c"(len), "S"(src), "D" (dst)
-	: "bx", "cx", "dx", "si", "di" );
-    return(sum);
+/*
+ * Generate 'csum_partial_copy_from_user()', we need to do exception
+ * handling for source addresses.
+ */
+
+#define SRC(x) x
+#define DST(x)
+csum_partial_copy_type(_from_user)
+#undef SRC
+#undef DST
+
+/*
+ * Generate 'csum_partial_copy_nocheck()', no need to do exception
+ * handling.
+ */
+
+#define SRC(x)
+#define DST(x)
+csum_partial_copy_type(_nocheck_generic)
+#undef SRC
+#undef DST
+
+/*
+ * Generate 'csum_partial_copy_old()', old and slow compability stuff,
+ * full checking.
+ *
+ * tell us if you see something printk-ing on this. This function will be
+ * removed soon.
+ */
+
+#define SRC(x) x
+#define DST(x) x
+csum_partial_copy_type(_old)
+#undef SRC
+#undef DST
+
+unsigned int csum_partial_copy ( const char *src, char *dst, 
+				  int len, int sum)
+{
+	int ret;
+	int error = 0;
+
+	ret = csum_partial_copy_old (&error, src, dst, len, sum);
+
+	if (error)
+		printk("csum_partial_copy_old(): tell mingo to convert me!\n");
+
+	return ret;
 }
+

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov