xref: /openbmc/linux/lib/raid6/recov_ssse3.c (revision ead5d1f4d877e92c051e1a1ade623d0d30e71619)
1*b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2048a8b8cSJim Kukunas /*
3048a8b8cSJim Kukunas  * Copyright (C) 2012 Intel Corporation
4048a8b8cSJim Kukunas  */
5048a8b8cSJim Kukunas 
6048a8b8cSJim Kukunas #include <linux/raid/pq.h>
7048a8b8cSJim Kukunas #include "x86.h"
8048a8b8cSJim Kukunas 
raid6_has_ssse3(void)9048a8b8cSJim Kukunas static int raid6_has_ssse3(void)
10048a8b8cSJim Kukunas {
11048a8b8cSJim Kukunas 	return boot_cpu_has(X86_FEATURE_XMM) &&
12048a8b8cSJim Kukunas 		boot_cpu_has(X86_FEATURE_XMM2) &&
13048a8b8cSJim Kukunas 		boot_cpu_has(X86_FEATURE_SSSE3);
14048a8b8cSJim Kukunas }
15048a8b8cSJim Kukunas 
raid6_2data_recov_ssse3(int disks,size_t bytes,int faila,int failb,void ** ptrs)162aa4ee2aSJim Kukunas static void raid6_2data_recov_ssse3(int disks, size_t bytes, int faila,
172aa4ee2aSJim Kukunas 		int failb, void **ptrs)
18048a8b8cSJim Kukunas {
19048a8b8cSJim Kukunas 	u8 *p, *q, *dp, *dq;
20048a8b8cSJim Kukunas 	const u8 *pbmul;	/* P multiplier table for B data */
21048a8b8cSJim Kukunas 	const u8 *qmul;		/* Q multiplier table (for both) */
22048a8b8cSJim Kukunas 	static const u8 __aligned(16) x0f[16] = {
23048a8b8cSJim Kukunas 		 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
24048a8b8cSJim Kukunas 		 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f};
25048a8b8cSJim Kukunas 
26048a8b8cSJim Kukunas 	p = (u8 *)ptrs[disks-2];
27048a8b8cSJim Kukunas 	q = (u8 *)ptrs[disks-1];
28048a8b8cSJim Kukunas 
29048a8b8cSJim Kukunas 	/* Compute syndrome with zero for the missing data pages
30048a8b8cSJim Kukunas 	   Use the dead data pages as temporary storage for
31048a8b8cSJim Kukunas 	   delta p and delta q */
32048a8b8cSJim Kukunas 	dp = (u8 *)ptrs[faila];
33048a8b8cSJim Kukunas 	ptrs[faila] = (void *)raid6_empty_zero_page;
34048a8b8cSJim Kukunas 	ptrs[disks-2] = dp;
35048a8b8cSJim Kukunas 	dq = (u8 *)ptrs[failb];
36048a8b8cSJim Kukunas 	ptrs[failb] = (void *)raid6_empty_zero_page;
37048a8b8cSJim Kukunas 	ptrs[disks-1] = dq;
38048a8b8cSJim Kukunas 
39048a8b8cSJim Kukunas 	raid6_call.gen_syndrome(disks, bytes, ptrs);
40048a8b8cSJim Kukunas 
41048a8b8cSJim Kukunas 	/* Restore pointer table */
42048a8b8cSJim Kukunas 	ptrs[faila]   = dp;
43048a8b8cSJim Kukunas 	ptrs[failb]   = dq;
44048a8b8cSJim Kukunas 	ptrs[disks-2] = p;
45048a8b8cSJim Kukunas 	ptrs[disks-1] = q;
46048a8b8cSJim Kukunas 
47048a8b8cSJim Kukunas 	/* Now, pick the proper data tables */
48048a8b8cSJim Kukunas 	pbmul = raid6_vgfmul[raid6_gfexi[failb-faila]];
49048a8b8cSJim Kukunas 	qmul  = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila] ^
50048a8b8cSJim Kukunas 		raid6_gfexp[failb]]];
51048a8b8cSJim Kukunas 
52048a8b8cSJim Kukunas 	kernel_fpu_begin();
53048a8b8cSJim Kukunas 
54048a8b8cSJim Kukunas 	asm volatile("movdqa %0,%%xmm7" : : "m" (x0f[0]));
55048a8b8cSJim Kukunas 
56048a8b8cSJim Kukunas #ifdef CONFIG_X86_64
57048a8b8cSJim Kukunas 	asm volatile("movdqa %0,%%xmm6" : : "m" (qmul[0]));
58048a8b8cSJim Kukunas 	asm volatile("movdqa %0,%%xmm14" : : "m" (pbmul[0]));
59048a8b8cSJim Kukunas 	asm volatile("movdqa %0,%%xmm15" : : "m" (pbmul[16]));
60048a8b8cSJim Kukunas #endif
61048a8b8cSJim Kukunas 
62048a8b8cSJim Kukunas 	/* Now do it... */
63048a8b8cSJim Kukunas 	while (bytes) {
64048a8b8cSJim Kukunas #ifdef CONFIG_X86_64
65048a8b8cSJim Kukunas 		/* xmm6, xmm14, xmm15 */
66048a8b8cSJim Kukunas 
67048a8b8cSJim Kukunas 		asm volatile("movdqa %0,%%xmm1" : : "m" (q[0]));
68048a8b8cSJim Kukunas 		asm volatile("movdqa %0,%%xmm9" : : "m" (q[16]));
69048a8b8cSJim Kukunas 		asm volatile("movdqa %0,%%xmm0" : : "m" (p[0]));
70048a8b8cSJim Kukunas 		asm volatile("movdqa %0,%%xmm8" : : "m" (p[16]));
71048a8b8cSJim Kukunas 		asm volatile("pxor   %0,%%xmm1" : : "m" (dq[0]));
72048a8b8cSJim Kukunas 		asm volatile("pxor   %0,%%xmm9" : : "m" (dq[16]));
73048a8b8cSJim Kukunas 		asm volatile("pxor   %0,%%xmm0" : : "m" (dp[0]));
74048a8b8cSJim Kukunas 		asm volatile("pxor   %0,%%xmm8" : : "m" (dp[16]));
75048a8b8cSJim Kukunas 
76048a8b8cSJim Kukunas 		/* xmm0/8 = px */
77048a8b8cSJim Kukunas 
78048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm6,%xmm4");
79048a8b8cSJim Kukunas 		asm volatile("movdqa %0,%%xmm5" : : "m" (qmul[16]));
80048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm6,%xmm12");
81048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm5,%xmm13");
82048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm1,%xmm3");
83048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm9,%xmm11");
84048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm0,%xmm2"); /* xmm2/10 = px */
85048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm8,%xmm10");
86048a8b8cSJim Kukunas 		asm volatile("psraw  $4,%xmm1");
87048a8b8cSJim Kukunas 		asm volatile("psraw  $4,%xmm9");
88048a8b8cSJim Kukunas 		asm volatile("pand   %xmm7,%xmm3");
89048a8b8cSJim Kukunas 		asm volatile("pand   %xmm7,%xmm11");
90048a8b8cSJim Kukunas 		asm volatile("pand   %xmm7,%xmm1");
91048a8b8cSJim Kukunas 		asm volatile("pand   %xmm7,%xmm9");
92048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm3,%xmm4");
93048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm11,%xmm12");
94048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm1,%xmm5");
95048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm9,%xmm13");
96048a8b8cSJim Kukunas 		asm volatile("pxor   %xmm4,%xmm5");
97048a8b8cSJim Kukunas 		asm volatile("pxor   %xmm12,%xmm13");
98048a8b8cSJim Kukunas 
99048a8b8cSJim Kukunas 		/* xmm5/13 = qx */
100048a8b8cSJim Kukunas 
101048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm14,%xmm4");
102048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm15,%xmm1");
103048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm14,%xmm12");
104048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm15,%xmm9");
105048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm2,%xmm3");
106048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm10,%xmm11");
107048a8b8cSJim Kukunas 		asm volatile("psraw  $4,%xmm2");
108048a8b8cSJim Kukunas 		asm volatile("psraw  $4,%xmm10");
109048a8b8cSJim Kukunas 		asm volatile("pand   %xmm7,%xmm3");
110048a8b8cSJim Kukunas 		asm volatile("pand   %xmm7,%xmm11");
111048a8b8cSJim Kukunas 		asm volatile("pand   %xmm7,%xmm2");
112048a8b8cSJim Kukunas 		asm volatile("pand   %xmm7,%xmm10");
113048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm3,%xmm4");
114048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm11,%xmm12");
115048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm2,%xmm1");
116048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm10,%xmm9");
117048a8b8cSJim Kukunas 		asm volatile("pxor   %xmm4,%xmm1");
118048a8b8cSJim Kukunas 		asm volatile("pxor   %xmm12,%xmm9");
119048a8b8cSJim Kukunas 
120048a8b8cSJim Kukunas 		/* xmm1/9 = pbmul[px] */
121048a8b8cSJim Kukunas 		asm volatile("pxor   %xmm5,%xmm1");
122048a8b8cSJim Kukunas 		asm volatile("pxor   %xmm13,%xmm9");
123048a8b8cSJim Kukunas 		/* xmm1/9 = db = DQ */
124048a8b8cSJim Kukunas 		asm volatile("movdqa %%xmm1,%0" : "=m" (dq[0]));
125048a8b8cSJim Kukunas 		asm volatile("movdqa %%xmm9,%0" : "=m" (dq[16]));
126048a8b8cSJim Kukunas 
127048a8b8cSJim Kukunas 		asm volatile("pxor   %xmm1,%xmm0");
128048a8b8cSJim Kukunas 		asm volatile("pxor   %xmm9,%xmm8");
129048a8b8cSJim Kukunas 		asm volatile("movdqa %%xmm0,%0" : "=m" (dp[0]));
130048a8b8cSJim Kukunas 		asm volatile("movdqa %%xmm8,%0" : "=m" (dp[16]));
131048a8b8cSJim Kukunas 
132048a8b8cSJim Kukunas 		bytes -= 32;
133048a8b8cSJim Kukunas 		p += 32;
134048a8b8cSJim Kukunas 		q += 32;
135048a8b8cSJim Kukunas 		dp += 32;
136048a8b8cSJim Kukunas 		dq += 32;
137048a8b8cSJim Kukunas #else
138048a8b8cSJim Kukunas 		asm volatile("movdqa %0,%%xmm1" : : "m" (*q));
139048a8b8cSJim Kukunas 		asm volatile("movdqa %0,%%xmm0" : : "m" (*p));
140048a8b8cSJim Kukunas 		asm volatile("pxor   %0,%%xmm1" : : "m" (*dq));
141048a8b8cSJim Kukunas 		asm volatile("pxor   %0,%%xmm0" : : "m" (*dp));
142048a8b8cSJim Kukunas 
143048a8b8cSJim Kukunas 		/* 1 = dq ^ q
144048a8b8cSJim Kukunas 		 * 0 = dp ^ p
145048a8b8cSJim Kukunas 		 */
146048a8b8cSJim Kukunas 		asm volatile("movdqa %0,%%xmm4" : : "m" (qmul[0]));
147048a8b8cSJim Kukunas 		asm volatile("movdqa %0,%%xmm5" : : "m" (qmul[16]));
148048a8b8cSJim Kukunas 
149048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm1,%xmm3");
150048a8b8cSJim Kukunas 		asm volatile("psraw  $4,%xmm1");
151048a8b8cSJim Kukunas 		asm volatile("pand   %xmm7,%xmm3");
152048a8b8cSJim Kukunas 		asm volatile("pand   %xmm7,%xmm1");
153048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm3,%xmm4");
154048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm1,%xmm5");
155048a8b8cSJim Kukunas 		asm volatile("pxor   %xmm4,%xmm5");
156048a8b8cSJim Kukunas 
157048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm0,%xmm2"); /* xmm2 = px */
158048a8b8cSJim Kukunas 
159048a8b8cSJim Kukunas 		/* xmm5 = qx */
160048a8b8cSJim Kukunas 
161048a8b8cSJim Kukunas 		asm volatile("movdqa %0,%%xmm4" : : "m" (pbmul[0]));
162048a8b8cSJim Kukunas 		asm volatile("movdqa %0,%%xmm1" : : "m" (pbmul[16]));
163048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm2,%xmm3");
164048a8b8cSJim Kukunas 		asm volatile("psraw  $4,%xmm2");
165048a8b8cSJim Kukunas 		asm volatile("pand   %xmm7,%xmm3");
166048a8b8cSJim Kukunas 		asm volatile("pand   %xmm7,%xmm2");
167048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm3,%xmm4");
168048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm2,%xmm1");
169048a8b8cSJim Kukunas 		asm volatile("pxor   %xmm4,%xmm1");
170048a8b8cSJim Kukunas 
171048a8b8cSJim Kukunas 		/* xmm1 = pbmul[px] */
172048a8b8cSJim Kukunas 		asm volatile("pxor   %xmm5,%xmm1");
173048a8b8cSJim Kukunas 		/* xmm1 = db = DQ */
174048a8b8cSJim Kukunas 		asm volatile("movdqa %%xmm1,%0" : "=m" (*dq));
175048a8b8cSJim Kukunas 
176048a8b8cSJim Kukunas 		asm volatile("pxor   %xmm1,%xmm0");
177048a8b8cSJim Kukunas 		asm volatile("movdqa %%xmm0,%0" : "=m" (*dp));
178048a8b8cSJim Kukunas 
179048a8b8cSJim Kukunas 		bytes -= 16;
180048a8b8cSJim Kukunas 		p += 16;
181048a8b8cSJim Kukunas 		q += 16;
182048a8b8cSJim Kukunas 		dp += 16;
183048a8b8cSJim Kukunas 		dq += 16;
184048a8b8cSJim Kukunas #endif
185048a8b8cSJim Kukunas 	}
186048a8b8cSJim Kukunas 
187048a8b8cSJim Kukunas 	kernel_fpu_end();
188048a8b8cSJim Kukunas }
189048a8b8cSJim Kukunas 
190048a8b8cSJim Kukunas 
raid6_datap_recov_ssse3(int disks,size_t bytes,int faila,void ** ptrs)1912aa4ee2aSJim Kukunas static void raid6_datap_recov_ssse3(int disks, size_t bytes, int faila,
1922aa4ee2aSJim Kukunas 		void **ptrs)
193048a8b8cSJim Kukunas {
194048a8b8cSJim Kukunas 	u8 *p, *q, *dq;
195048a8b8cSJim Kukunas 	const u8 *qmul;		/* Q multiplier table */
196048a8b8cSJim Kukunas 	static const u8 __aligned(16) x0f[16] = {
197048a8b8cSJim Kukunas 		 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
198048a8b8cSJim Kukunas 		 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f};
199048a8b8cSJim Kukunas 
200048a8b8cSJim Kukunas 	p = (u8 *)ptrs[disks-2];
201048a8b8cSJim Kukunas 	q = (u8 *)ptrs[disks-1];
202048a8b8cSJim Kukunas 
203048a8b8cSJim Kukunas 	/* Compute syndrome with zero for the missing data page
204048a8b8cSJim Kukunas 	   Use the dead data page as temporary storage for delta q */
205048a8b8cSJim Kukunas 	dq = (u8 *)ptrs[faila];
206048a8b8cSJim Kukunas 	ptrs[faila] = (void *)raid6_empty_zero_page;
207048a8b8cSJim Kukunas 	ptrs[disks-1] = dq;
208048a8b8cSJim Kukunas 
209048a8b8cSJim Kukunas 	raid6_call.gen_syndrome(disks, bytes, ptrs);
210048a8b8cSJim Kukunas 
211048a8b8cSJim Kukunas 	/* Restore pointer table */
212048a8b8cSJim Kukunas 	ptrs[faila]   = dq;
213048a8b8cSJim Kukunas 	ptrs[disks-1] = q;
214048a8b8cSJim Kukunas 
215048a8b8cSJim Kukunas 	/* Now, pick the proper data tables */
216048a8b8cSJim Kukunas 	qmul  = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila]]];
217048a8b8cSJim Kukunas 
218048a8b8cSJim Kukunas 	kernel_fpu_begin();
219048a8b8cSJim Kukunas 
220048a8b8cSJim Kukunas 	asm volatile("movdqa %0, %%xmm7" : : "m" (x0f[0]));
221048a8b8cSJim Kukunas 
222048a8b8cSJim Kukunas 	while (bytes) {
223048a8b8cSJim Kukunas #ifdef CONFIG_X86_64
224048a8b8cSJim Kukunas 		asm volatile("movdqa %0, %%xmm3" : : "m" (dq[0]));
225048a8b8cSJim Kukunas 		asm volatile("movdqa %0, %%xmm4" : : "m" (dq[16]));
226048a8b8cSJim Kukunas 		asm volatile("pxor %0, %%xmm3" : : "m" (q[0]));
227048a8b8cSJim Kukunas 		asm volatile("movdqa %0, %%xmm0" : : "m" (qmul[0]));
228048a8b8cSJim Kukunas 
229048a8b8cSJim Kukunas 		/* xmm3 = q[0] ^ dq[0] */
230048a8b8cSJim Kukunas 
231048a8b8cSJim Kukunas 		asm volatile("pxor %0, %%xmm4" : : "m" (q[16]));
232048a8b8cSJim Kukunas 		asm volatile("movdqa %0, %%xmm1" : : "m" (qmul[16]));
233048a8b8cSJim Kukunas 
234048a8b8cSJim Kukunas 		/* xmm4 = q[16] ^ dq[16] */
235048a8b8cSJim Kukunas 
236048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm3, %xmm6");
237048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm4, %xmm8");
238048a8b8cSJim Kukunas 
239048a8b8cSJim Kukunas 		/* xmm4 = xmm8 = q[16] ^ dq[16] */
240048a8b8cSJim Kukunas 
241048a8b8cSJim Kukunas 		asm volatile("psraw $4, %xmm3");
242048a8b8cSJim Kukunas 		asm volatile("pand %xmm7, %xmm6");
243048a8b8cSJim Kukunas 		asm volatile("pand %xmm7, %xmm3");
244048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm6, %xmm0");
245048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm3, %xmm1");
246048a8b8cSJim Kukunas 		asm volatile("movdqa %0, %%xmm10" : : "m" (qmul[0]));
247048a8b8cSJim Kukunas 		asm volatile("pxor %xmm0, %xmm1");
248048a8b8cSJim Kukunas 		asm volatile("movdqa %0, %%xmm11" : : "m" (qmul[16]));
249048a8b8cSJim Kukunas 
250048a8b8cSJim Kukunas 		/* xmm1 = qmul[q[0] ^ dq[0]] */
251048a8b8cSJim Kukunas 
252048a8b8cSJim Kukunas 		asm volatile("psraw $4, %xmm4");
253048a8b8cSJim Kukunas 		asm volatile("pand %xmm7, %xmm8");
254048a8b8cSJim Kukunas 		asm volatile("pand %xmm7, %xmm4");
255048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm8, %xmm10");
256048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm4, %xmm11");
257048a8b8cSJim Kukunas 		asm volatile("movdqa %0, %%xmm2" : : "m" (p[0]));
258048a8b8cSJim Kukunas 		asm volatile("pxor %xmm10, %xmm11");
259048a8b8cSJim Kukunas 		asm volatile("movdqa %0, %%xmm12" : : "m" (p[16]));
260048a8b8cSJim Kukunas 
261048a8b8cSJim Kukunas 		/* xmm11 = qmul[q[16] ^ dq[16]] */
262048a8b8cSJim Kukunas 
263048a8b8cSJim Kukunas 		asm volatile("pxor %xmm1, %xmm2");
264048a8b8cSJim Kukunas 
265048a8b8cSJim Kukunas 		/* xmm2 = p[0] ^ qmul[q[0] ^ dq[0]] */
266048a8b8cSJim Kukunas 
267048a8b8cSJim Kukunas 		asm volatile("pxor %xmm11, %xmm12");
268048a8b8cSJim Kukunas 
269048a8b8cSJim Kukunas 		/* xmm12 = p[16] ^ qmul[q[16] ^ dq[16]] */
270048a8b8cSJim Kukunas 
271048a8b8cSJim Kukunas 		asm volatile("movdqa %%xmm1, %0" : "=m" (dq[0]));
272048a8b8cSJim Kukunas 		asm volatile("movdqa %%xmm11, %0" : "=m" (dq[16]));
273048a8b8cSJim Kukunas 
274048a8b8cSJim Kukunas 		asm volatile("movdqa %%xmm2, %0" : "=m" (p[0]));
275048a8b8cSJim Kukunas 		asm volatile("movdqa %%xmm12, %0" : "=m" (p[16]));
276048a8b8cSJim Kukunas 
277048a8b8cSJim Kukunas 		bytes -= 32;
278048a8b8cSJim Kukunas 		p += 32;
279048a8b8cSJim Kukunas 		q += 32;
280048a8b8cSJim Kukunas 		dq += 32;
281048a8b8cSJim Kukunas 
282048a8b8cSJim Kukunas #else
283048a8b8cSJim Kukunas 		asm volatile("movdqa %0, %%xmm3" : : "m" (dq[0]));
284048a8b8cSJim Kukunas 		asm volatile("movdqa %0, %%xmm0" : : "m" (qmul[0]));
285048a8b8cSJim Kukunas 		asm volatile("pxor %0, %%xmm3" : : "m" (q[0]));
286048a8b8cSJim Kukunas 		asm volatile("movdqa %0, %%xmm1" : : "m" (qmul[16]));
287048a8b8cSJim Kukunas 
288048a8b8cSJim Kukunas 		/* xmm3 = *q ^ *dq */
289048a8b8cSJim Kukunas 
290048a8b8cSJim Kukunas 		asm volatile("movdqa %xmm3, %xmm6");
291048a8b8cSJim Kukunas 		asm volatile("movdqa %0, %%xmm2" : : "m" (p[0]));
292048a8b8cSJim Kukunas 		asm volatile("psraw $4, %xmm3");
293048a8b8cSJim Kukunas 		asm volatile("pand %xmm7, %xmm6");
294048a8b8cSJim Kukunas 		asm volatile("pand %xmm7, %xmm3");
295048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm6, %xmm0");
296048a8b8cSJim Kukunas 		asm volatile("pshufb %xmm3, %xmm1");
297048a8b8cSJim Kukunas 		asm volatile("pxor %xmm0, %xmm1");
298048a8b8cSJim Kukunas 
299048a8b8cSJim Kukunas 		/* xmm1 = qmul[*q ^ *dq */
300048a8b8cSJim Kukunas 
301048a8b8cSJim Kukunas 		asm volatile("pxor %xmm1, %xmm2");
302048a8b8cSJim Kukunas 
303048a8b8cSJim Kukunas 		/* xmm2 = *p ^ qmul[*q ^ *dq] */
304048a8b8cSJim Kukunas 
305048a8b8cSJim Kukunas 		asm volatile("movdqa %%xmm1, %0" : "=m" (dq[0]));
306048a8b8cSJim Kukunas 		asm volatile("movdqa %%xmm2, %0" : "=m" (p[0]));
307048a8b8cSJim Kukunas 
308048a8b8cSJim Kukunas 		bytes -= 16;
309048a8b8cSJim Kukunas 		p += 16;
310048a8b8cSJim Kukunas 		q += 16;
311048a8b8cSJim Kukunas 		dq += 16;
312048a8b8cSJim Kukunas #endif
313048a8b8cSJim Kukunas 	}
314048a8b8cSJim Kukunas 
315048a8b8cSJim Kukunas 	kernel_fpu_end();
316048a8b8cSJim Kukunas }
317048a8b8cSJim Kukunas 
318048a8b8cSJim Kukunas const struct raid6_recov_calls raid6_recov_ssse3 = {
319048a8b8cSJim Kukunas 	.data2 = raid6_2data_recov_ssse3,
320048a8b8cSJim Kukunas 	.datap = raid6_datap_recov_ssse3,
321048a8b8cSJim Kukunas 	.valid = raid6_has_ssse3,
322048a8b8cSJim Kukunas #ifdef CONFIG_X86_64
323048a8b8cSJim Kukunas 	.name = "ssse3x2",
324048a8b8cSJim Kukunas #else
325048a8b8cSJim Kukunas 	.name = "ssse3x1",
326048a8b8cSJim Kukunas #endif
327048a8b8cSJim Kukunas 	.priority = 1,
328048a8b8cSJim Kukunas };
329