13626738bSChristoph Hellwig // SPDX-License-Identifier: GPL-2.0-only 23626738bSChristoph Hellwig /* 33626738bSChristoph Hellwig * Copyright 2024 Institute of Software, CAS. 43626738bSChristoph Hellwig * Author: Chunyan Zhang <zhangchunyan@iscas.ac.cn> 53626738bSChristoph Hellwig */ 63626738bSChristoph Hellwig 7*769d603fSChristoph Hellwig #include <linux/mm.h> 83626738bSChristoph Hellwig #include <linux/raid/pq.h> 9*769d603fSChristoph Hellwig #include "algos.h" 103626738bSChristoph Hellwig #include "rvv.h" 113626738bSChristoph Hellwig 123626738bSChristoph Hellwig static void __raid6_2data_recov_rvv(int bytes, u8 *p, u8 *q, u8 *dp, 133626738bSChristoph Hellwig u8 *dq, const u8 *pbmul, 143626738bSChristoph Hellwig const u8 *qmul) 153626738bSChristoph Hellwig { 163626738bSChristoph Hellwig asm volatile (".option push\n" 173626738bSChristoph Hellwig ".option arch,+v\n" 183626738bSChristoph Hellwig "vsetvli x0, %[avl], e8, m1, ta, ma\n" 193626738bSChristoph Hellwig ".option pop\n" 203626738bSChristoph Hellwig : : 213626738bSChristoph Hellwig [avl]"r"(16) 223626738bSChristoph Hellwig ); 233626738bSChristoph Hellwig 243626738bSChristoph Hellwig /* 253626738bSChristoph Hellwig * while ( bytes-- ) { 263626738bSChristoph Hellwig * uint8_t px, qx, db; 273626738bSChristoph Hellwig * 283626738bSChristoph Hellwig * px = *p ^ *dp; 293626738bSChristoph Hellwig * qx = qmul[*q ^ *dq]; 303626738bSChristoph Hellwig * *dq++ = db = pbmul[px] ^ qx; 313626738bSChristoph Hellwig * *dp++ = db ^ px; 323626738bSChristoph Hellwig * p++; q++; 333626738bSChristoph Hellwig * } 343626738bSChristoph Hellwig */ 353626738bSChristoph Hellwig while (bytes) { 363626738bSChristoph Hellwig /* 373626738bSChristoph Hellwig * v0:px, v1:dp, 383626738bSChristoph Hellwig * v2:qx, v3:dq, 393626738bSChristoph Hellwig * v4:vx, v5:vy, 403626738bSChristoph Hellwig * v6:qm0, v7:qm1, 413626738bSChristoph Hellwig * v8:pm0, v9:pm1, 423626738bSChristoph Hellwig * v14:p/qm[vx], v15:p/qm[vy] 433626738bSChristoph Hellwig */ 443626738bSChristoph Hellwig asm volatile (".option push\n" 453626738bSChristoph Hellwig ".option arch,+v\n" 463626738bSChristoph Hellwig "vle8.v v0, (%[px])\n" 473626738bSChristoph Hellwig "vle8.v v1, (%[dp])\n" 483626738bSChristoph Hellwig "vxor.vv v0, v0, v1\n" 493626738bSChristoph Hellwig "vle8.v v2, (%[qx])\n" 503626738bSChristoph Hellwig "vle8.v v3, (%[dq])\n" 513626738bSChristoph Hellwig "vxor.vv v4, v2, v3\n" 523626738bSChristoph Hellwig "vsrl.vi v5, v4, 4\n" 533626738bSChristoph Hellwig "vand.vi v4, v4, 0xf\n" 543626738bSChristoph Hellwig "vle8.v v6, (%[qm0])\n" 553626738bSChristoph Hellwig "vle8.v v7, (%[qm1])\n" 563626738bSChristoph Hellwig "vrgather.vv v14, v6, v4\n" /* v14 = qm[vx] */ 573626738bSChristoph Hellwig "vrgather.vv v15, v7, v5\n" /* v15 = qm[vy] */ 583626738bSChristoph Hellwig "vxor.vv v2, v14, v15\n" /* v2 = qmul[*q ^ *dq] */ 593626738bSChristoph Hellwig 603626738bSChristoph Hellwig "vsrl.vi v5, v0, 4\n" 613626738bSChristoph Hellwig "vand.vi v4, v0, 0xf\n" 623626738bSChristoph Hellwig "vle8.v v8, (%[pm0])\n" 633626738bSChristoph Hellwig "vle8.v v9, (%[pm1])\n" 643626738bSChristoph Hellwig "vrgather.vv v14, v8, v4\n" /* v14 = pm[vx] */ 653626738bSChristoph Hellwig "vrgather.vv v15, v9, v5\n" /* v15 = pm[vy] */ 663626738bSChristoph Hellwig "vxor.vv v4, v14, v15\n" /* v4 = pbmul[px] */ 673626738bSChristoph Hellwig "vxor.vv v3, v4, v2\n" /* v3 = db = pbmul[px] ^ qx */ 683626738bSChristoph Hellwig "vxor.vv v1, v3, v0\n" /* v1 = db ^ px; */ 693626738bSChristoph Hellwig "vse8.v v3, (%[dq])\n" 703626738bSChristoph Hellwig "vse8.v v1, (%[dp])\n" 713626738bSChristoph Hellwig ".option pop\n" 723626738bSChristoph Hellwig : : 733626738bSChristoph Hellwig [px]"r"(p), 743626738bSChristoph Hellwig [dp]"r"(dp), 753626738bSChristoph Hellwig [qx]"r"(q), 763626738bSChristoph Hellwig [dq]"r"(dq), 773626738bSChristoph Hellwig [qm0]"r"(qmul), 783626738bSChristoph Hellwig [qm1]"r"(qmul + 16), 793626738bSChristoph Hellwig [pm0]"r"(pbmul), 803626738bSChristoph Hellwig [pm1]"r"(pbmul + 16) 813626738bSChristoph Hellwig :); 823626738bSChristoph Hellwig 833626738bSChristoph Hellwig bytes -= 16; 843626738bSChristoph Hellwig p += 16; 853626738bSChristoph Hellwig q += 16; 863626738bSChristoph Hellwig dp += 16; 873626738bSChristoph Hellwig dq += 16; 883626738bSChristoph Hellwig } 893626738bSChristoph Hellwig } 903626738bSChristoph Hellwig 913626738bSChristoph Hellwig static void __raid6_datap_recov_rvv(int bytes, u8 *p, u8 *q, 923626738bSChristoph Hellwig u8 *dq, const u8 *qmul) 933626738bSChristoph Hellwig { 943626738bSChristoph Hellwig asm volatile (".option push\n" 953626738bSChristoph Hellwig ".option arch,+v\n" 963626738bSChristoph Hellwig "vsetvli x0, %[avl], e8, m1, ta, ma\n" 973626738bSChristoph Hellwig ".option pop\n" 983626738bSChristoph Hellwig : : 993626738bSChristoph Hellwig [avl]"r"(16) 1003626738bSChristoph Hellwig ); 1013626738bSChristoph Hellwig 1023626738bSChristoph Hellwig /* 1033626738bSChristoph Hellwig * while (bytes--) { 1043626738bSChristoph Hellwig * *p++ ^= *dq = qmul[*q ^ *dq]; 1053626738bSChristoph Hellwig * q++; dq++; 1063626738bSChristoph Hellwig * } 1073626738bSChristoph Hellwig */ 1083626738bSChristoph Hellwig while (bytes) { 1093626738bSChristoph Hellwig /* 1103626738bSChristoph Hellwig * v0:vx, v1:vy, 1113626738bSChristoph Hellwig * v2:dq, v3:p, 1123626738bSChristoph Hellwig * v4:qm0, v5:qm1, 1133626738bSChristoph Hellwig * v10:m[vx], v11:m[vy] 1143626738bSChristoph Hellwig */ 1153626738bSChristoph Hellwig asm volatile (".option push\n" 1163626738bSChristoph Hellwig ".option arch,+v\n" 1173626738bSChristoph Hellwig "vle8.v v0, (%[vx])\n" 1183626738bSChristoph Hellwig "vle8.v v2, (%[dq])\n" 1193626738bSChristoph Hellwig "vxor.vv v0, v0, v2\n" 1203626738bSChristoph Hellwig "vsrl.vi v1, v0, 4\n" 1213626738bSChristoph Hellwig "vand.vi v0, v0, 0xf\n" 1223626738bSChristoph Hellwig "vle8.v v4, (%[qm0])\n" 1233626738bSChristoph Hellwig "vle8.v v5, (%[qm1])\n" 1243626738bSChristoph Hellwig "vrgather.vv v10, v4, v0\n" 1253626738bSChristoph Hellwig "vrgather.vv v11, v5, v1\n" 1263626738bSChristoph Hellwig "vxor.vv v0, v10, v11\n" 1273626738bSChristoph Hellwig "vle8.v v1, (%[vy])\n" 1283626738bSChristoph Hellwig "vxor.vv v1, v0, v1\n" 1293626738bSChristoph Hellwig "vse8.v v0, (%[dq])\n" 1303626738bSChristoph Hellwig "vse8.v v1, (%[vy])\n" 1313626738bSChristoph Hellwig ".option pop\n" 1323626738bSChristoph Hellwig : : 1333626738bSChristoph Hellwig [vx]"r"(q), 1343626738bSChristoph Hellwig [vy]"r"(p), 1353626738bSChristoph Hellwig [dq]"r"(dq), 1363626738bSChristoph Hellwig [qm0]"r"(qmul), 1373626738bSChristoph Hellwig [qm1]"r"(qmul + 16) 1383626738bSChristoph Hellwig :); 1393626738bSChristoph Hellwig 1403626738bSChristoph Hellwig bytes -= 16; 1413626738bSChristoph Hellwig p += 16; 1423626738bSChristoph Hellwig q += 16; 1433626738bSChristoph Hellwig dq += 16; 1443626738bSChristoph Hellwig } 1453626738bSChristoph Hellwig } 1463626738bSChristoph Hellwig 1473626738bSChristoph Hellwig static void raid6_2data_recov_rvv(int disks, size_t bytes, int faila, 1483626738bSChristoph Hellwig int failb, void **ptrs) 1493626738bSChristoph Hellwig { 1503626738bSChristoph Hellwig u8 *p, *q, *dp, *dq; 1513626738bSChristoph Hellwig const u8 *pbmul; /* P multiplier table for B data */ 1523626738bSChristoph Hellwig const u8 *qmul; /* Q multiplier table (for both) */ 1533626738bSChristoph Hellwig 1543626738bSChristoph Hellwig p = (u8 *)ptrs[disks - 2]; 1553626738bSChristoph Hellwig q = (u8 *)ptrs[disks - 1]; 1563626738bSChristoph Hellwig 1573626738bSChristoph Hellwig /* 1583626738bSChristoph Hellwig * Compute syndrome with zero for the missing data pages 1593626738bSChristoph Hellwig * Use the dead data pages as temporary storage for 1603626738bSChristoph Hellwig * delta p and delta q 1613626738bSChristoph Hellwig */ 1623626738bSChristoph Hellwig dp = (u8 *)ptrs[faila]; 163885d3142SChristoph Hellwig ptrs[faila] = page_address(ZERO_PAGE(0)); 1643626738bSChristoph Hellwig ptrs[disks - 2] = dp; 1653626738bSChristoph Hellwig dq = (u8 *)ptrs[failb]; 166885d3142SChristoph Hellwig ptrs[failb] = page_address(ZERO_PAGE(0)); 1673626738bSChristoph Hellwig ptrs[disks - 1] = dq; 1683626738bSChristoph Hellwig 16935472bc6SChristoph Hellwig raid6_gen_syndrome(disks, bytes, ptrs); 1703626738bSChristoph Hellwig 1713626738bSChristoph Hellwig /* Restore pointer table */ 1723626738bSChristoph Hellwig ptrs[faila] = dp; 1733626738bSChristoph Hellwig ptrs[failb] = dq; 1743626738bSChristoph Hellwig ptrs[disks - 2] = p; 1753626738bSChristoph Hellwig ptrs[disks - 1] = q; 1763626738bSChristoph Hellwig 1773626738bSChristoph Hellwig /* Now, pick the proper data tables */ 1783626738bSChristoph Hellwig pbmul = raid6_vgfmul[raid6_gfexi[failb - faila]]; 1793626738bSChristoph Hellwig qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila] ^ 1803626738bSChristoph Hellwig raid6_gfexp[failb]]]; 1813626738bSChristoph Hellwig 1823626738bSChristoph Hellwig kernel_vector_begin(); 1833626738bSChristoph Hellwig __raid6_2data_recov_rvv(bytes, p, q, dp, dq, pbmul, qmul); 1843626738bSChristoph Hellwig kernel_vector_end(); 1853626738bSChristoph Hellwig } 1863626738bSChristoph Hellwig 1873626738bSChristoph Hellwig static void raid6_datap_recov_rvv(int disks, size_t bytes, int faila, 1883626738bSChristoph Hellwig void **ptrs) 1893626738bSChristoph Hellwig { 1903626738bSChristoph Hellwig u8 *p, *q, *dq; 1913626738bSChristoph Hellwig const u8 *qmul; /* Q multiplier table */ 1923626738bSChristoph Hellwig 1933626738bSChristoph Hellwig p = (u8 *)ptrs[disks - 2]; 1943626738bSChristoph Hellwig q = (u8 *)ptrs[disks - 1]; 1953626738bSChristoph Hellwig 1963626738bSChristoph Hellwig /* 1973626738bSChristoph Hellwig * Compute syndrome with zero for the missing data page 1983626738bSChristoph Hellwig * Use the dead data page as temporary storage for delta q 1993626738bSChristoph Hellwig */ 2003626738bSChristoph Hellwig dq = (u8 *)ptrs[faila]; 201885d3142SChristoph Hellwig ptrs[faila] = page_address(ZERO_PAGE(0)); 2023626738bSChristoph Hellwig ptrs[disks - 1] = dq; 2033626738bSChristoph Hellwig 20435472bc6SChristoph Hellwig raid6_gen_syndrome(disks, bytes, ptrs); 2053626738bSChristoph Hellwig 2063626738bSChristoph Hellwig /* Restore pointer table */ 2073626738bSChristoph Hellwig ptrs[faila] = dq; 2083626738bSChristoph Hellwig ptrs[disks - 1] = q; 2093626738bSChristoph Hellwig 2103626738bSChristoph Hellwig /* Now, pick the proper data tables */ 2113626738bSChristoph Hellwig qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila]]]; 2123626738bSChristoph Hellwig 2133626738bSChristoph Hellwig kernel_vector_begin(); 2143626738bSChristoph Hellwig __raid6_datap_recov_rvv(bytes, p, q, dq, qmul); 2153626738bSChristoph Hellwig kernel_vector_end(); 2163626738bSChristoph Hellwig } 2173626738bSChristoph Hellwig 2183626738bSChristoph Hellwig const struct raid6_recov_calls raid6_recov_rvv = { 2193626738bSChristoph Hellwig .data2 = raid6_2data_recov_rvv, 2203626738bSChristoph Hellwig .datap = raid6_datap_recov_rvv, 2213626738bSChristoph Hellwig .name = "rvv", 2223626738bSChristoph Hellwig }; 223