s390vx.uc 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * raid6_vx$#.c
  4. *
  5. * $#-way unrolled RAID6 gen/xor functions for s390
  6. * based on the vector facility
  7. *
  8. * Copyright IBM Corp. 2016
  9. * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
  10. *
  11. * This file is postprocessed using unroll.awk.
  12. */
  13. #include <linux/cpufeature.h>
  14. #include <linux/raid/pq.h>
  15. #include <asm/fpu.h>
  16. #define NSIZE 16
  17. static __always_inline void LOAD_CONST(void)
  18. {
  19. fpu_vrepib(24, 0x07);
  20. fpu_vrepib(25, 0x1d);
  21. }
  22. /*
  23. * The SHLBYTE() operation shifts each of the 16 bytes in
  24. * vector register y left by 1 bit and stores the result in
  25. * vector register x.
  26. */
  27. #define SHLBYTE(x, y) fpu_vab(x, y, y)
  28. /*
  29. * For each of the 16 bytes in the vector register y the MASK()
  30. * operation returns 0xFF if the high bit of the byte is 1,
  31. * or 0x00 if the high bit is 0. The result is stored in vector
  32. * register x.
  33. */
  34. #define MASK(x, y) fpu_vesravb(x, y, 24)
  35. #define AND(x, y, z) fpu_vn(x, y, z)
  36. #define XOR(x, y, z) fpu_vx(x, y, z)
  37. #define LOAD_DATA(x, ptr) fpu_vlm(x, x + $# - 1, ptr)
  38. #define STORE_DATA(x, ptr) fpu_vstm(x, x + $# - 1, ptr)
  39. #define COPY_VEC(x, y) fpu_vlr(x, y)
  40. static void raid6_s390vx$#_gen_syndrome(int disks, size_t bytes, void **ptrs)
  41. {
  42. DECLARE_KERNEL_FPU_ONSTACK32(vxstate);
  43. u8 **dptr, *p, *q;
  44. int d, z, z0;
  45. kernel_fpu_begin(&vxstate, KERNEL_VXR);
  46. LOAD_CONST();
  47. dptr = (u8 **) ptrs;
  48. z0 = disks - 3; /* Highest data disk */
  49. p = dptr[z0 + 1]; /* XOR parity */
  50. q = dptr[z0 + 2]; /* RS syndrome */
  51. for (d = 0; d < bytes; d += $#*NSIZE) {
  52. LOAD_DATA(0,&dptr[z0][d]);
  53. COPY_VEC(8+$$,0+$$);
  54. for (z = z0 - 1; z >= 0; z--) {
  55. MASK(16+$$,8+$$);
  56. AND(16+$$,16+$$,25);
  57. SHLBYTE(8+$$,8+$$);
  58. XOR(8+$$,8+$$,16+$$);
  59. LOAD_DATA(16,&dptr[z][d]);
  60. XOR(0+$$,0+$$,16+$$);
  61. XOR(8+$$,8+$$,16+$$);
  62. }
  63. STORE_DATA(0,&p[d]);
  64. STORE_DATA(8,&q[d]);
  65. }
  66. kernel_fpu_end(&vxstate, KERNEL_VXR);
  67. }
  68. static void raid6_s390vx$#_xor_syndrome(int disks, int start, int stop,
  69. size_t bytes, void **ptrs)
  70. {
  71. DECLARE_KERNEL_FPU_ONSTACK32(vxstate);
  72. u8 **dptr, *p, *q;
  73. int d, z, z0;
  74. dptr = (u8 **) ptrs;
  75. z0 = stop; /* P/Q right side optimization */
  76. p = dptr[disks - 2]; /* XOR parity */
  77. q = dptr[disks - 1]; /* RS syndrome */
  78. kernel_fpu_begin(&vxstate, KERNEL_VXR);
  79. LOAD_CONST();
  80. for (d = 0; d < bytes; d += $#*NSIZE) {
  81. /* P/Q data pages */
  82. LOAD_DATA(0,&dptr[z0][d]);
  83. COPY_VEC(8+$$,0+$$);
  84. for (z = z0 - 1; z >= start; z--) {
  85. MASK(16+$$,8+$$);
  86. AND(16+$$,16+$$,25);
  87. SHLBYTE(8+$$,8+$$);
  88. XOR(8+$$,8+$$,16+$$);
  89. LOAD_DATA(16,&dptr[z][d]);
  90. XOR(0+$$,0+$$,16+$$);
  91. XOR(8+$$,8+$$,16+$$);
  92. }
  93. /* P/Q left side optimization */
  94. for (z = start - 1; z >= 0; z--) {
  95. MASK(16+$$,8+$$);
  96. AND(16+$$,16+$$,25);
  97. SHLBYTE(8+$$,8+$$);
  98. XOR(8+$$,8+$$,16+$$);
  99. }
  100. LOAD_DATA(16,&p[d]);
  101. XOR(16+$$,16+$$,0+$$);
  102. STORE_DATA(16,&p[d]);
  103. LOAD_DATA(16,&q[d]);
  104. XOR(16+$$,16+$$,8+$$);
  105. STORE_DATA(16,&q[d]);
  106. }
  107. kernel_fpu_end(&vxstate, KERNEL_VXR);
  108. }
  109. static int raid6_s390vx$#_valid(void)
  110. {
  111. return cpu_has_vx();
  112. }
  113. const struct raid6_calls raid6_s390vx$# = {
  114. raid6_s390vx$#_gen_syndrome,
  115. raid6_s390vx$#_xor_syndrome,
  116. raid6_s390vx$#_valid,
  117. "vx128x$#",
  118. 1
  119. };