Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sh: Handle calling csum_partial with misaligned data

In rare circumstances csum_partial() can be called with data which is
not 16 or 32 bit aligned. This is been observed with RPC calls for NFS
file systems for example. Add support for handling this without resorting
to the misaligned fixup code (which is why this hasn't been seen as a
problem). This mimics the i386 version, which has had this support for
some time.

Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>

authored by

Stuart Menefy and committed by
Paul Mundt
cadc4e1a 3d22fca7

+50 -19
+50 -19
arch/sh/lib/checksum.S
··· 36 36 */ 37 37 38 38 /* 39 - * unsigned int csum_partial(const unsigned char *buf, int len, 40 - * unsigned int sum); 39 + * asmlinkage __wsum csum_partial(const void *buf, int len, __wsum sum); 41 40 */ 42 41 43 42 .text ··· 48 49 * Fortunately, it is easy to convert 2-byte alignment to 4-byte 49 50 * alignment for the unrolled loop. 50 51 */ 51 - mov r5, r1 52 52 mov r4, r0 53 - tst #2, r0 ! Check alignment. 54 - bt 2f ! Jump if alignment is ok. 53 + tst #3, r0 ! Check alignment. 54 + bt/s 2f ! Jump if alignment is ok. 55 + mov r4, r7 ! Keep a copy to check for alignment 55 56 ! 57 + tst #1, r0 ! Check alignment. 58 + bt 21f ! Jump if alignment is boundary of 2bytes. 59 + 60 + ! buf is odd 61 + tst r5, r5 62 + add #-1, r5 63 + bt 9f 64 + mov.b @r4+, r0 65 + extu.b r0, r0 66 + addc r0, r6 ! t=0 from previous tst 67 + mov r6, r0 68 + shll8 r6 69 + shlr16 r0 70 + shlr8 r0 71 + or r0, r6 72 + mov r4, r0 73 + tst #2, r0 74 + bt 2f 75 + 21: 76 + ! buf is 2 byte aligned (len could be 0) 56 77 add #-2, r5 ! Alignment uses up two bytes. 57 78 cmp/pz r5 ! 58 79 bt/s 1f ! Jump if we had at least two bytes. ··· 80 61 bra 6f 81 62 add #2, r5 ! r5 was < 2. Deal with it. 82 63 1: 83 - mov r5, r1 ! Save new len for later use. 84 64 mov.w @r4+, r0 85 65 extu.w r0, r0 86 66 addc r0, r6 87 67 bf 2f 88 68 add #1, r6 89 69 2: 70 + ! buf is 4 byte aligned (len could be 0) 71 + mov r5, r1 90 72 mov #-5, r0 91 - shld r0, r5 92 - tst r5, r5 73 + shld r0, r1 74 + tst r1, r1 93 75 bt/s 4f ! if it's =0, go to 4f 94 76 clrt 95 77 .align 2 ··· 112 92 addc r0, r6 113 93 addc r2, r6 114 94 movt r0 115 - dt r5 95 + dt r1 116 96 bf/s 3b 117 97 cmp/eq #1, r0 118 - ! here, we know r5==0 119 - addc r5, r6 ! add carry to r6 98 + ! here, we know r1==0 99 + addc r1, r6 ! add carry to r6 120 100 4: 121 - mov r1, r0 101 + mov r5, r0 122 102 and #0x1c, r0 123 103 tst r0, r0 124 - bt/s 6f 125 - mov r0, r5 126 - shlr2 r5 104 + bt 6f 105 + ! 4 bytes or more remaining 106 + mov r0, r1 107 + shlr2 r1 127 108 mov #0, r2 128 109 5: 129 110 addc r2, r6 130 111 mov.l @r4+, r2 131 112 movt r0 132 - dt r5 113 + dt r1 133 114 bf/s 5b 134 115 cmp/eq #1, r0 135 116 addc r2, r6 136 - addc r5, r6 ! r5==0 here, so it means add carry-bit 117 + addc r1, r6 ! r1==0 here, so it means add carry-bit 137 118 6: 138 - mov r1, r5 119 + ! 3 bytes or less remaining 139 120 mov #3, r0 140 121 and r0, r5 141 122 tst r5, r5 ··· 160 139 8: 161 140 addc r0, r6 162 141 mov #0, r0 163 - addc r0, r6 142 + addc r0, r6 164 143 9: 144 + ! Check if the buffer was misaligned, if so realign sum 145 + mov r7, r0 146 + tst #1, r0 147 + bt 10f 148 + mov r6, r0 149 + shll8 r6 150 + shlr16 r0 151 + shlr8 r0 152 + or r0, r6 153 + 10: 165 154 rts 166 155 mov r6, r0 167 156