~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/s390/include/asm/fpu-insn.h

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 */
  2 /*
  3  * Support for Floating Point and Vector Instructions
  4  *
  5  */
  6 
  7 #ifndef __ASM_S390_FPU_INSN_H
  8 #define __ASM_S390_FPU_INSN_H
  9 
 10 #include <asm/fpu-insn-asm.h>
 11 
 12 #ifndef __ASSEMBLY__
 13 
 14 #include <linux/instrumented.h>
 15 #include <asm/asm-extable.h>
 16 
 17 asm(".include \"asm/fpu-insn-asm.h\"\n");
 18 
 19 /*
 20  * Various small helper functions, which can and should be used within
 21  * kernel fpu code sections. Each function represents only one floating
 22  * point or vector instruction (except for helper functions which require
 23  * exception handling).
 24  *
 25  * This allows to use floating point and vector instructions like C
 26  * functions, which has the advantage that all supporting code, like
 27  * e.g. loops, can be written in easy to read C code.
 28  *
 29  * Each of the helper functions provides support for code instrumentation,
 30  * like e.g. KASAN. Therefore instrumentation is also covered automatically
 31  * when using these functions.
 32  *
 33  * In order to ensure that code generated with the helper functions stays
 34  * within kernel fpu sections, which are guarded with kernel_fpu_begin()
 35  * and kernel_fpu_end() calls, each function has a mandatory "memory"
 36  * barrier.
 37  */
 38 
 39 static __always_inline void fpu_cefbr(u8 f1, s32 val)
 40 {
 41         asm volatile("cefbr     %[f1],%[val]\n"
 42                      :
 43                      : [f1] "I" (f1), [val] "d" (val)
 44                      : "memory");
 45 }
 46 
 47 static __always_inline unsigned long fpu_cgebr(u8 f2, u8 mode)
 48 {
 49         unsigned long val;
 50 
 51         asm volatile("cgebr     %[val],%[mode],%[f2]\n"
 52                      : [val] "=d" (val)
 53                      : [f2] "I" (f2), [mode] "I" (mode)
 54                      : "memory");
 55         return val;
 56 }
 57 
 58 static __always_inline void fpu_debr(u8 f1, u8 f2)
 59 {
 60         asm volatile("debr      %[f1],%[f2]\n"
 61                      :
 62                      : [f1] "I" (f1), [f2] "I" (f2)
 63                      : "memory");
 64 }
 65 
 66 static __always_inline void fpu_ld(unsigned short fpr, freg_t *reg)
 67 {
 68         instrument_read(reg, sizeof(*reg));
 69         asm volatile("ld         %[fpr],%[reg]\n"
 70                      :
 71                      : [fpr] "I" (fpr), [reg] "Q" (reg->ui)
 72                      : "memory");
 73 }
 74 
 75 static __always_inline void fpu_ldgr(u8 f1, u32 val)
 76 {
 77         asm volatile("ldgr      %[f1],%[val]\n"
 78                      :
 79                      : [f1] "I" (f1), [val] "d" (val)
 80                      : "memory");
 81 }
 82 
 83 static __always_inline void fpu_lfpc(unsigned int *fpc)
 84 {
 85         instrument_read(fpc, sizeof(*fpc));
 86         asm volatile("lfpc      %[fpc]"
 87                      :
 88                      : [fpc] "Q" (*fpc)
 89                      : "memory");
 90 }
 91 
 92 /**
 93  * fpu_lfpc_safe - Load floating point control register safely.
 94  * @fpc: new value for floating point control register
 95  *
 96  * Load floating point control register. This may lead to an exception,
 97  * since a saved value may have been modified by user space (ptrace,
 98  * signal return, kvm registers) to an invalid value. In such a case
 99  * set the floating point control register to zero.
100  */
101 static inline void fpu_lfpc_safe(unsigned int *fpc)
102 {
103         u32 tmp;
104 
105         instrument_read(fpc, sizeof(*fpc));
106         asm volatile("\n"
107                 "0:     lfpc    %[fpc]\n"
108                 "1:     nopr    %%r7\n"
109                 ".pushsection .fixup, \"ax\"\n"
110                 "2:     lghi    %[tmp],0\n"
111                 "       sfpc    %[tmp]\n"
112                 "       jg      1b\n"
113                 ".popsection\n"
114                 EX_TABLE(1b, 2b)
115                 : [tmp] "=d" (tmp)
116                 : [fpc] "Q" (*fpc)
117                 : "memory");
118 }
119 
120 static __always_inline void fpu_std(unsigned short fpr, freg_t *reg)
121 {
122         instrument_write(reg, sizeof(*reg));
123         asm volatile("std        %[fpr],%[reg]\n"
124                      : [reg] "=Q" (reg->ui)
125                      : [fpr] "I" (fpr)
126                      : "memory");
127 }
128 
129 static __always_inline void fpu_sfpc(unsigned int fpc)
130 {
131         asm volatile("sfpc      %[fpc]"
132                      :
133                      : [fpc] "d" (fpc)
134                      : "memory");
135 }
136 
137 static __always_inline void fpu_stfpc(unsigned int *fpc)
138 {
139         instrument_write(fpc, sizeof(*fpc));
140         asm volatile("stfpc     %[fpc]"
141                      : [fpc] "=Q" (*fpc)
142                      :
143                      : "memory");
144 }
145 
146 static __always_inline void fpu_vab(u8 v1, u8 v2, u8 v3)
147 {
148         asm volatile("VAB       %[v1],%[v2],%[v3]"
149                      :
150                      : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3)
151                      : "memory");
152 }
153 
154 static __always_inline void fpu_vcksm(u8 v1, u8 v2, u8 v3)
155 {
156         asm volatile("VCKSM     %[v1],%[v2],%[v3]"
157                      :
158                      : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3)
159                      : "memory");
160 }
161 
162 static __always_inline void fpu_vesravb(u8 v1, u8 v2, u8 v3)
163 {
164         asm volatile("VESRAVB   %[v1],%[v2],%[v3]"
165                      :
166                      : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3)
167                      : "memory");
168 }
169 
170 static __always_inline void fpu_vgfmag(u8 v1, u8 v2, u8 v3, u8 v4)
171 {
172         asm volatile("VGFMAG    %[v1],%[v2],%[v3],%[v4]"
173                      :
174                      : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3), [v4] "I" (v4)
175                      : "memory");
176 }
177 
178 static __always_inline void fpu_vgfmg(u8 v1, u8 v2, u8 v3)
179 {
180         asm volatile("VGFMG     %[v1],%[v2],%[v3]"
181                      :
182                      : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3)
183                      : "memory");
184 }
185 
186 #ifdef CONFIG_CC_IS_CLANG
187 
188 static __always_inline void fpu_vl(u8 v1, const void *vxr)
189 {
190         instrument_read(vxr, sizeof(__vector128));
191         asm volatile("\n"
192                 "       la      1,%[vxr]\n"
193                 "       VL      %[v1],0,,1\n"
194                 :
195                 : [vxr] "R" (*(__vector128 *)vxr),
196                   [v1] "I" (v1)
197                 : "memory", "1");
198 }
199 
200 #else /* CONFIG_CC_IS_CLANG */
201 
202 static __always_inline void fpu_vl(u8 v1, const void *vxr)
203 {
204         instrument_read(vxr, sizeof(__vector128));
205         asm volatile("VL        %[v1],%O[vxr],,%R[vxr]\n"
206                      :
207                      : [vxr] "Q" (*(__vector128 *)vxr),
208                        [v1] "I" (v1)
209                      : "memory");
210 }
211 
212 #endif /* CONFIG_CC_IS_CLANG */
213 
214 static __always_inline void fpu_vleib(u8 v, s16 val, u8 index)
215 {
216         asm volatile("VLEIB     %[v],%[val],%[index]"
217                      :
218                      : [v] "I" (v), [val] "K" (val), [index] "I" (index)
219                      : "memory");
220 }
221 
222 static __always_inline void fpu_vleig(u8 v, s16 val, u8 index)
223 {
224         asm volatile("VLEIG     %[v],%[val],%[index]"
225                      :
226                      : [v] "I" (v), [val] "K" (val), [index] "I" (index)
227                      : "memory");
228 }
229 
230 static __always_inline u64 fpu_vlgvf(u8 v, u16 index)
231 {
232         u64 val;
233 
234         asm volatile("VLGVF     %[val],%[v],%[index]"
235                      : [val] "=d" (val)
236                      : [v] "I" (v), [index] "L" (index)
237                      : "memory");
238         return val;
239 }
240 
241 #ifdef CONFIG_CC_IS_CLANG
242 
243 static __always_inline void fpu_vll(u8 v1, u32 index, const void *vxr)
244 {
245         unsigned int size;
246 
247         size = min(index + 1, sizeof(__vector128));
248         instrument_read(vxr, size);
249         asm volatile("\n"
250                 "       la      1,%[vxr]\n"
251                 "       VLL     %[v1],%[index],0,1\n"
252                 :
253                 : [vxr] "R" (*(u8 *)vxr),
254                   [index] "d" (index),
255                   [v1] "I" (v1)
256                 : "memory", "1");
257 }
258 
259 #else /* CONFIG_CC_IS_CLANG */
260 
261 static __always_inline void fpu_vll(u8 v1, u32 index, const void *vxr)
262 {
263         unsigned int size;
264 
265         size = min(index + 1, sizeof(__vector128));
266         instrument_read(vxr, size);
267         asm volatile("VLL       %[v1],%[index],%O[vxr],%R[vxr]\n"
268                      :
269                      : [vxr] "Q" (*(u8 *)vxr),
270                        [index] "d" (index),
271                        [v1] "I" (v1)
272                      : "memory");
273 }
274 
275 #endif /* CONFIG_CC_IS_CLANG */
276 
277 #ifdef CONFIG_CC_IS_CLANG
278 
279 #define fpu_vlm(_v1, _v3, _vxrs)                                        \
280 ({                                                                      \
281         unsigned int size = ((_v3) - (_v1) + 1) * sizeof(__vector128);  \
282         struct {                                                        \
283                 __vector128 _v[(_v3) - (_v1) + 1];                      \
284         } *_v = (void *)(_vxrs);                                        \
285                                                                         \
286         instrument_read(_v, size);                                      \
287         asm volatile("\n"                                               \
288                 "       la      1,%[vxrs]\n"                            \
289                 "       VLM     %[v1],%[v3],0,1\n"                      \
290                 :                                                       \
291                 : [vxrs] "R" (*_v),                                     \
292                   [v1] "I" (_v1), [v3] "I" (_v3)                        \
293                 : "memory", "1");                                       \
294         (_v3) - (_v1) + 1;                                              \
295 })
296 
297 #else /* CONFIG_CC_IS_CLANG */
298 
299 #define fpu_vlm(_v1, _v3, _vxrs)                                        \
300 ({                                                                      \
301         unsigned int size = ((_v3) - (_v1) + 1) * sizeof(__vector128);  \
302         struct {                                                        \
303                 __vector128 _v[(_v3) - (_v1) + 1];                      \
304         } *_v = (void *)(_vxrs);                                        \
305                                                                         \
306         instrument_read(_v, size);                                      \
307         asm volatile("VLM       %[v1],%[v3],%O[vxrs],%R[vxrs]\n"        \
308                      :                                                  \
309                      : [vxrs] "Q" (*_v),                                \
310                        [v1] "I" (_v1), [v3] "I" (_v3)                   \
311                      : "memory");                                       \
312         (_v3) - (_v1) + 1;                                              \
313 })
314 
315 #endif /* CONFIG_CC_IS_CLANG */
316 
317 static __always_inline void fpu_vlr(u8 v1, u8 v2)
318 {
319         asm volatile("VLR       %[v1],%[v2]"
320                      :
321                      : [v1] "I" (v1), [v2] "I" (v2)
322                      : "memory");
323 }
324 
325 static __always_inline void fpu_vlvgf(u8 v, u32 val, u16 index)
326 {
327         asm volatile("VLVGF     %[v],%[val],%[index]"
328                      :
329                      : [v] "I" (v), [val] "d" (val), [index] "L" (index)
330                      : "memory");
331 }
332 
333 static __always_inline void fpu_vn(u8 v1, u8 v2, u8 v3)
334 {
335         asm volatile("VN        %[v1],%[v2],%[v3]"
336                      :
337                      : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3)
338                      : "memory");
339 }
340 
341 static __always_inline void fpu_vperm(u8 v1, u8 v2, u8 v3, u8 v4)
342 {
343         asm volatile("VPERM     %[v1],%[v2],%[v3],%[v4]"
344                      :
345                      : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3), [v4] "I" (v4)
346                      : "memory");
347 }
348 
349 static __always_inline void fpu_vrepib(u8 v1, s16 i2)
350 {
351         asm volatile("VREPIB    %[v1],%[i2]"
352                      :
353                      : [v1] "I" (v1), [i2] "K" (i2)
354                      : "memory");
355 }
356 
357 static __always_inline void fpu_vsrlb(u8 v1, u8 v2, u8 v3)
358 {
359         asm volatile("VSRLB     %[v1],%[v2],%[v3]"
360                      :
361                      : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3)
362                      : "memory");
363 }
364 
365 #ifdef CONFIG_CC_IS_CLANG
366 
367 static __always_inline void fpu_vst(u8 v1, const void *vxr)
368 {
369         instrument_write(vxr, sizeof(__vector128));
370         asm volatile("\n"
371                 "       la      1,%[vxr]\n"
372                 "       VST     %[v1],0,,1\n"
373                 : [vxr] "=R" (*(__vector128 *)vxr)
374                 : [v1] "I" (v1)
375                 : "memory", "1");
376 }
377 
378 #else /* CONFIG_CC_IS_CLANG */
379 
380 static __always_inline void fpu_vst(u8 v1, const void *vxr)
381 {
382         instrument_write(vxr, sizeof(__vector128));
383         asm volatile("VST       %[v1],%O[vxr],,%R[vxr]\n"
384                      : [vxr] "=Q" (*(__vector128 *)vxr)
385                      : [v1] "I" (v1)
386                      : "memory");
387 }
388 
389 #endif /* CONFIG_CC_IS_CLANG */
390 
391 #ifdef CONFIG_CC_IS_CLANG
392 
393 static __always_inline void fpu_vstl(u8 v1, u32 index, const void *vxr)
394 {
395         unsigned int size;
396 
397         size = min(index + 1, sizeof(__vector128));
398         instrument_write(vxr, size);
399         asm volatile("\n"
400                 "       la      1,%[vxr]\n"
401                 "       VSTL    %[v1],%[index],0,1\n"
402                 : [vxr] "=R" (*(u8 *)vxr)
403                 : [index] "d" (index), [v1] "I" (v1)
404                 : "memory", "1");
405 }
406 
407 #else /* CONFIG_CC_IS_CLANG */
408 
409 static __always_inline void fpu_vstl(u8 v1, u32 index, const void *vxr)
410 {
411         unsigned int size;
412 
413         size = min(index + 1, sizeof(__vector128));
414         instrument_write(vxr, size);
415         asm volatile("VSTL      %[v1],%[index],%O[vxr],%R[vxr]\n"
416                      : [vxr] "=Q" (*(u8 *)vxr)
417                      : [index] "d" (index), [v1] "I" (v1)
418                      : "memory");
419 }
420 
421 #endif /* CONFIG_CC_IS_CLANG */
422 
423 #ifdef CONFIG_CC_IS_CLANG
424 
425 #define fpu_vstm(_v1, _v3, _vxrs)                                       \
426 ({                                                                      \
427         unsigned int size = ((_v3) - (_v1) + 1) * sizeof(__vector128);  \
428         struct {                                                        \
429                 __vector128 _v[(_v3) - (_v1) + 1];                      \
430         } *_v = (void *)(_vxrs);                                        \
431                                                                         \
432         instrument_write(_v, size);                                     \
433         asm volatile("\n"                                               \
434                 "       la      1,%[vxrs]\n"                            \
435                 "       VSTM    %[v1],%[v3],0,1\n"                      \
436                 : [vxrs] "=R" (*_v)                                     \
437                 : [v1] "I" (_v1), [v3] "I" (_v3)                        \
438                 : "memory", "1");                                       \
439         (_v3) - (_v1) + 1;                                              \
440 })
441 
442 #else /* CONFIG_CC_IS_CLANG */
443 
444 #define fpu_vstm(_v1, _v3, _vxrs)                                       \
445 ({                                                                      \
446         unsigned int size = ((_v3) - (_v1) + 1) * sizeof(__vector128);  \
447         struct {                                                        \
448                 __vector128 _v[(_v3) - (_v1) + 1];                      \
449         } *_v = (void *)(_vxrs);                                        \
450                                                                         \
451         instrument_write(_v, size);                                     \
452         asm volatile("VSTM      %[v1],%[v3],%O[vxrs],%R[vxrs]\n"        \
453                      : [vxrs] "=Q" (*_v)                                \
454                      : [v1] "I" (_v1), [v3] "I" (_v3)                   \
455                      : "memory");                                       \
456         (_v3) - (_v1) + 1;                                              \
457 })
458 
459 #endif /* CONFIG_CC_IS_CLANG */
460 
461 static __always_inline void fpu_vupllf(u8 v1, u8 v2)
462 {
463         asm volatile("VUPLLF    %[v1],%[v2]"
464                      :
465                      : [v1] "I" (v1), [v2] "I" (v2)
466                      : "memory");
467 }
468 
469 static __always_inline void fpu_vx(u8 v1, u8 v2, u8 v3)
470 {
471         asm volatile("VX        %[v1],%[v2],%[v3]"
472                      :
473                      : [v1] "I" (v1), [v2] "I" (v2), [v3] "I" (v3)
474                      : "memory");
475 }
476 
477 static __always_inline void fpu_vzero(u8 v)
478 {
479         asm volatile("VZERO     %[v]"
480                      :
481                      : [v] "I" (v)
482                      : "memory");
483 }
484 
485 #endif /* __ASSEMBLY__ */
486 #endif  /* __ASM_S390_FPU_INSN_H */
487 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php