1*dd165a65SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2cc4589ebSDavid Woodhouse /* -*- linux-c -*- ------------------------------------------------------- *
3cc4589ebSDavid Woodhouse *
4cc4589ebSDavid Woodhouse * Copyright 2002 H. Peter Anvin - All Rights Reserved
5cc4589ebSDavid Woodhouse *
6cc4589ebSDavid Woodhouse * ----------------------------------------------------------------------- */
7cc4589ebSDavid Woodhouse
8cc4589ebSDavid Woodhouse /*
9a8e026c7SNeilBrown * raid6/mmx.c
10cc4589ebSDavid Woodhouse *
11cc4589ebSDavid Woodhouse * MMX implementation of RAID-6 syndrome functions
12cc4589ebSDavid Woodhouse */
13cc4589ebSDavid Woodhouse
144f8c55c5SYuanhan Liu #ifdef CONFIG_X86_32
15cc4589ebSDavid Woodhouse
16cc4589ebSDavid Woodhouse #include <linux/raid/pq.h>
17a8e026c7SNeilBrown #include "x86.h"
18cc4589ebSDavid Woodhouse
19a8e026c7SNeilBrown /* Shared with raid6/sse1.c */
20cc4589ebSDavid Woodhouse const struct raid6_mmx_constants {
21cc4589ebSDavid Woodhouse u64 x1d;
22cc4589ebSDavid Woodhouse } raid6_mmx_constants = {
23cc4589ebSDavid Woodhouse 0x1d1d1d1d1d1d1d1dULL,
24cc4589ebSDavid Woodhouse };
25cc4589ebSDavid Woodhouse
raid6_have_mmx(void)26cc4589ebSDavid Woodhouse static int raid6_have_mmx(void)
27cc4589ebSDavid Woodhouse {
28cc4589ebSDavid Woodhouse /* Not really "boot_cpu" but "all_cpus" */
29cc4589ebSDavid Woodhouse return boot_cpu_has(X86_FEATURE_MMX);
30cc4589ebSDavid Woodhouse }
31cc4589ebSDavid Woodhouse
32cc4589ebSDavid Woodhouse /*
33cc4589ebSDavid Woodhouse * Plain MMX implementation
34cc4589ebSDavid Woodhouse */
raid6_mmx1_gen_syndrome(int disks,size_t bytes,void ** ptrs)35cc4589ebSDavid Woodhouse static void raid6_mmx1_gen_syndrome(int disks, size_t bytes, void **ptrs)
36cc4589ebSDavid Woodhouse {
37cc4589ebSDavid Woodhouse u8 **dptr = (u8 **)ptrs;
38cc4589ebSDavid Woodhouse u8 *p, *q;
39cc4589ebSDavid Woodhouse int d, z, z0;
40cc4589ebSDavid Woodhouse
41cc4589ebSDavid Woodhouse z0 = disks - 3; /* Highest data disk */
42cc4589ebSDavid Woodhouse p = dptr[z0+1]; /* XOR parity */
43cc4589ebSDavid Woodhouse q = dptr[z0+2]; /* RS syndrome */
44cc4589ebSDavid Woodhouse
45cc4589ebSDavid Woodhouse kernel_fpu_begin();
46cc4589ebSDavid Woodhouse
47cc4589ebSDavid Woodhouse asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d));
48cc4589ebSDavid Woodhouse asm volatile("pxor %mm5,%mm5"); /* Zero temp */
49cc4589ebSDavid Woodhouse
50cc4589ebSDavid Woodhouse for ( d = 0 ; d < bytes ; d += 8 ) {
51cc4589ebSDavid Woodhouse asm volatile("movq %0,%%mm2" : : "m" (dptr[z0][d])); /* P[0] */
52cc4589ebSDavid Woodhouse asm volatile("movq %mm2,%mm4"); /* Q[0] */
53cc4589ebSDavid Woodhouse for ( z = z0-1 ; z >= 0 ; z-- ) {
54cc4589ebSDavid Woodhouse asm volatile("movq %0,%%mm6" : : "m" (dptr[z][d]));
55cc4589ebSDavid Woodhouse asm volatile("pcmpgtb %mm4,%mm5");
56cc4589ebSDavid Woodhouse asm volatile("paddb %mm4,%mm4");
57cc4589ebSDavid Woodhouse asm volatile("pand %mm0,%mm5");
58cc4589ebSDavid Woodhouse asm volatile("pxor %mm5,%mm4");
59cc4589ebSDavid Woodhouse asm volatile("pxor %mm5,%mm5");
60cc4589ebSDavid Woodhouse asm volatile("pxor %mm6,%mm2");
61cc4589ebSDavid Woodhouse asm volatile("pxor %mm6,%mm4");
62cc4589ebSDavid Woodhouse }
63cc4589ebSDavid Woodhouse asm volatile("movq %%mm2,%0" : "=m" (p[d]));
64cc4589ebSDavid Woodhouse asm volatile("pxor %mm2,%mm2");
65cc4589ebSDavid Woodhouse asm volatile("movq %%mm4,%0" : "=m" (q[d]));
66cc4589ebSDavid Woodhouse asm volatile("pxor %mm4,%mm4");
67cc4589ebSDavid Woodhouse }
68cc4589ebSDavid Woodhouse
69cc4589ebSDavid Woodhouse kernel_fpu_end();
70cc4589ebSDavid Woodhouse }
71cc4589ebSDavid Woodhouse
72cc4589ebSDavid Woodhouse const struct raid6_calls raid6_mmxx1 = {
73cc4589ebSDavid Woodhouse raid6_mmx1_gen_syndrome,
74fe5cbc6eSMarkus Stockhausen NULL, /* XOR not yet implemented */
75cc4589ebSDavid Woodhouse raid6_have_mmx,
76cc4589ebSDavid Woodhouse "mmxx1",
77cc4589ebSDavid Woodhouse 0
78cc4589ebSDavid Woodhouse };
79cc4589ebSDavid Woodhouse
80cc4589ebSDavid Woodhouse /*
81cc4589ebSDavid Woodhouse * Unrolled-by-2 MMX implementation
82cc4589ebSDavid Woodhouse */
raid6_mmx2_gen_syndrome(int disks,size_t bytes,void ** ptrs)83cc4589ebSDavid Woodhouse static void raid6_mmx2_gen_syndrome(int disks, size_t bytes, void **ptrs)
84cc4589ebSDavid Woodhouse {
85cc4589ebSDavid Woodhouse u8 **dptr = (u8 **)ptrs;
86cc4589ebSDavid Woodhouse u8 *p, *q;
87cc4589ebSDavid Woodhouse int d, z, z0;
88cc4589ebSDavid Woodhouse
89cc4589ebSDavid Woodhouse z0 = disks - 3; /* Highest data disk */
90cc4589ebSDavid Woodhouse p = dptr[z0+1]; /* XOR parity */
91cc4589ebSDavid Woodhouse q = dptr[z0+2]; /* RS syndrome */
92cc4589ebSDavid Woodhouse
93cc4589ebSDavid Woodhouse kernel_fpu_begin();
94cc4589ebSDavid Woodhouse
95cc4589ebSDavid Woodhouse asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d));
96cc4589ebSDavid Woodhouse asm volatile("pxor %mm5,%mm5"); /* Zero temp */
97cc4589ebSDavid Woodhouse asm volatile("pxor %mm7,%mm7"); /* Zero temp */
98cc4589ebSDavid Woodhouse
99cc4589ebSDavid Woodhouse for ( d = 0 ; d < bytes ; d += 16 ) {
100cc4589ebSDavid Woodhouse asm volatile("movq %0,%%mm2" : : "m" (dptr[z0][d])); /* P[0] */
101cc4589ebSDavid Woodhouse asm volatile("movq %0,%%mm3" : : "m" (dptr[z0][d+8]));
102cc4589ebSDavid Woodhouse asm volatile("movq %mm2,%mm4"); /* Q[0] */
103cc4589ebSDavid Woodhouse asm volatile("movq %mm3,%mm6"); /* Q[1] */
104cc4589ebSDavid Woodhouse for ( z = z0-1 ; z >= 0 ; z-- ) {
105cc4589ebSDavid Woodhouse asm volatile("pcmpgtb %mm4,%mm5");
106cc4589ebSDavid Woodhouse asm volatile("pcmpgtb %mm6,%mm7");
107cc4589ebSDavid Woodhouse asm volatile("paddb %mm4,%mm4");
108cc4589ebSDavid Woodhouse asm volatile("paddb %mm6,%mm6");
109cc4589ebSDavid Woodhouse asm volatile("pand %mm0,%mm5");
110cc4589ebSDavid Woodhouse asm volatile("pand %mm0,%mm7");
111cc4589ebSDavid Woodhouse asm volatile("pxor %mm5,%mm4");
112cc4589ebSDavid Woodhouse asm volatile("pxor %mm7,%mm6");
113cc4589ebSDavid Woodhouse asm volatile("movq %0,%%mm5" : : "m" (dptr[z][d]));
114cc4589ebSDavid Woodhouse asm volatile("movq %0,%%mm7" : : "m" (dptr[z][d+8]));
115cc4589ebSDavid Woodhouse asm volatile("pxor %mm5,%mm2");
116cc4589ebSDavid Woodhouse asm volatile("pxor %mm7,%mm3");
117cc4589ebSDavid Woodhouse asm volatile("pxor %mm5,%mm4");
118cc4589ebSDavid Woodhouse asm volatile("pxor %mm7,%mm6");
119cc4589ebSDavid Woodhouse asm volatile("pxor %mm5,%mm5");
120cc4589ebSDavid Woodhouse asm volatile("pxor %mm7,%mm7");
121cc4589ebSDavid Woodhouse }
122cc4589ebSDavid Woodhouse asm volatile("movq %%mm2,%0" : "=m" (p[d]));
123cc4589ebSDavid Woodhouse asm volatile("movq %%mm3,%0" : "=m" (p[d+8]));
124cc4589ebSDavid Woodhouse asm volatile("movq %%mm4,%0" : "=m" (q[d]));
125cc4589ebSDavid Woodhouse asm volatile("movq %%mm6,%0" : "=m" (q[d+8]));
126cc4589ebSDavid Woodhouse }
127cc4589ebSDavid Woodhouse
128cc4589ebSDavid Woodhouse kernel_fpu_end();
129cc4589ebSDavid Woodhouse }
130cc4589ebSDavid Woodhouse
131cc4589ebSDavid Woodhouse const struct raid6_calls raid6_mmxx2 = {
132cc4589ebSDavid Woodhouse raid6_mmx2_gen_syndrome,
133fe5cbc6eSMarkus Stockhausen NULL, /* XOR not yet implemented */
134cc4589ebSDavid Woodhouse raid6_have_mmx,
135cc4589ebSDavid Woodhouse "mmxx2",
136cc4589ebSDavid Woodhouse 0
137cc4589ebSDavid Woodhouse };
138cc4589ebSDavid Woodhouse
139cc4589ebSDavid Woodhouse #endif
140