Skip to content

Commit dcd3e1d

Browse files
committed
s390/checksum: provide csum_partial_copy_nocheck()
With csum_partial(), which reads all bytes into registers it is easy to also implement csum_partial_copy_nocheck() which copies the buffer while calculating its checksum. For a 512 byte buffer this reduces the runtime by 19%. Compared to the old generic variant (memcpy() + cksm instruction) runtime is reduced by 42%). Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
1 parent cb2a1dd commit dcd3e1d

4 files changed

Lines changed: 112 additions & 13 deletions

File tree

arch/s390/include/asm/checksum.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ static inline __wsum cksm(const void *buff, int len, __wsum sum)
3232

3333
__wsum csum_partial(const void *buff, int len, __wsum sum);
3434

35+
#define _HAVE_ARCH_CSUM_AND_COPY
36+
__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len);
37+
3538
/*
3639
* Fold a partial checksum without adding pseudo headers.
3740
*/

arch/s390/include/asm/fpu-insn-asm.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,16 @@
531531
MRXBOPC 0, 0x37, v1
532532
.endm
533533

534+
/* VECTOR STORE WITH LENGTH */
535+
.macro VSTL v, gr, disp, base
536+
VX_NUM v1, \v
537+
GR_NUM b2, \base
538+
GR_NUM r3, \gr
539+
.word 0xE700 | ((v1&15) << 4) | r3
540+
.word (b2 << 12) | (\disp)
541+
MRXBOPC 0, 0x3f, v1
542+
.endm
543+
534544
/* Vector integer instructions */
535545

536546
/* VECTOR AND */

arch/s390/include/asm/fpu-insn.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,64 @@ static __always_inline void fpu_vlvgf(u8 v, u32 val, u16 index)
241241

242242
#ifdef CONFIG_CC_IS_CLANG
243243

244+
static __always_inline void fpu_vst(u8 v1, const void *vxr)
245+
{
246+
instrument_write(vxr, sizeof(__vector128));
247+
asm volatile("\n"
248+
" la 1,%[vxr]\n"
249+
" VST %[v1],0,,1\n"
250+
: [vxr] "=R" (*(__vector128 *)vxr)
251+
: [v1] "I" (v1)
252+
: "memory", "1");
253+
}
254+
255+
#else /* CONFIG_CC_IS_CLANG */
256+
257+
static __always_inline void fpu_vst(u8 v1, const void *vxr)
258+
{
259+
instrument_write(vxr, sizeof(__vector128));
260+
asm volatile("VST %[v1],%O[vxr],,%R[vxr]\n"
261+
: [vxr] "=Q" (*(__vector128 *)vxr)
262+
: [v1] "I" (v1)
263+
: "memory");
264+
}
265+
266+
#endif /* CONFIG_CC_IS_CLANG */
267+
268+
#ifdef CONFIG_CC_IS_CLANG
269+
270+
static __always_inline void fpu_vstl(u8 v1, u32 index, const void *vxr)
271+
{
272+
unsigned int size;
273+
274+
size = min(index + 1, sizeof(__vector128));
275+
instrument_write(vxr, size);
276+
asm volatile("\n"
277+
" la 1,%[vxr]\n"
278+
" VSTL %[v1],%[index],0,1\n"
279+
: [vxr] "=R" (*(u8 *)vxr)
280+
: [index] "d" (index), [v1] "I" (v1)
281+
: "memory", "1");
282+
}
283+
284+
#else /* CONFIG_CC_IS_CLANG */
285+
286+
static __always_inline void fpu_vstl(u8 v1, u32 index, const void *vxr)
287+
{
288+
unsigned int size;
289+
290+
size = min(index + 1, sizeof(__vector128));
291+
instrument_write(vxr, size);
292+
asm volatile("VSTL %[v1],%[index],%O[vxr],%R[vxr]\n"
293+
: [vxr] "=Q" (*(u8 *)vxr)
294+
: [index] "d" (index), [v1] "I" (v1)
295+
: "memory");
296+
}
297+
298+
#endif /* CONFIG_CC_IS_CLANG */
299+
300+
#ifdef CONFIG_CC_IS_CLANG
301+
244302
#define fpu_vstm(_v1, _v3, _vxrs) \
245303
({ \
246304
unsigned int size = ((_v3) - (_v1) + 1) * sizeof(__vector128); \

arch/s390/lib/csum-partial.c

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,52 +5,69 @@
55
#include <asm/fpu.h>
66

77
/*
8-
* Computes the checksum of a memory block at buff, length len,
9-
* and adds in "sum" (32-bit).
8+
* Computes the checksum of a memory block at src, length len,
9+
* and adds in "sum" (32-bit). If copy is true copies to dst.
1010
*
1111
* Returns a 32-bit number suitable for feeding into itself
1212
* or csum_tcpudp_magic.
1313
*
1414
* This function must be called with even lengths, except
1515
* for the last fragment, which may be odd.
1616
*
17-
* It's best to have buff aligned on a 64-bit boundary.
17+
* It's best to have src and dst aligned on a 64-bit boundary.
1818
*/
19-
__wsum csum_partial(const void *buff, int len, __wsum sum)
19+
static __always_inline __wsum csum_copy(void *dst, const void *src, int len, __wsum sum, bool copy)
2020
{
2121
DECLARE_KERNEL_FPU_ONSTACK8(vxstate);
2222

23-
if (!cpu_has_vx())
24-
return cksm(buff, len, sum);
23+
if (!cpu_has_vx()) {
24+
if (copy)
25+
memcpy(dst, src, len);
26+
return cksm(dst, len, sum);
27+
}
2528
kernel_fpu_begin(&vxstate, KERNEL_VXR_V16V23);
2629
fpu_vlvgf(16, (__force u32)sum, 1);
2730
fpu_vzero(17);
2831
fpu_vzero(18);
2932
fpu_vzero(19);
3033
while (len >= 64) {
31-
fpu_vlm(20, 23, buff);
34+
fpu_vlm(20, 23, src);
35+
if (copy) {
36+
fpu_vstm(20, 23, dst);
37+
dst += 64;
38+
}
3239
fpu_vcksm(16, 20, 16);
3340
fpu_vcksm(17, 21, 17);
3441
fpu_vcksm(18, 22, 18);
3542
fpu_vcksm(19, 23, 19);
36-
buff += 64;
43+
src += 64;
3744
len -= 64;
3845
}
3946
while (len >= 32) {
40-
fpu_vlm(20, 21, buff);
47+
fpu_vlm(20, 21, src);
48+
if (copy) {
49+
fpu_vstm(20, 21, dst);
50+
dst += 32;
51+
}
4152
fpu_vcksm(16, 20, 16);
4253
fpu_vcksm(17, 21, 17);
43-
buff += 32;
54+
src += 32;
4455
len -= 32;
4556
}
4657
while (len >= 16) {
47-
fpu_vl(20, buff);
58+
fpu_vl(20, src);
59+
if (copy) {
60+
fpu_vst(20, dst);
61+
dst += 16;
62+
}
4863
fpu_vcksm(16, 20, 16);
49-
buff += 16;
64+
src += 16;
5065
len -= 16;
5166
}
5267
if (len) {
53-
fpu_vll(20, len - 1, buff);
68+
fpu_vll(20, len - 1, src);
69+
if (copy)
70+
fpu_vstl(20, len - 1, dst);
5471
fpu_vcksm(16, 20, 16);
5572
}
5673
fpu_vcksm(18, 19, 18);
@@ -60,4 +77,15 @@ __wsum csum_partial(const void *buff, int len, __wsum sum)
6077
kernel_fpu_end(&vxstate, KERNEL_VXR_V16V23);
6178
return sum;
6279
}
80+
81+
__wsum csum_partial(const void *buff, int len, __wsum sum)
82+
{
83+
return csum_copy(NULL, buff, len, sum, false);
84+
}
6385
EXPORT_SYMBOL(csum_partial);
86+
87+
__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len)
88+
{
89+
return csum_copy(dst, src, len, 0, true);
90+
}
91+
EXPORT_SYMBOL(csum_partial_copy_nocheck);

0 commit comments

Comments
 (0)