summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig1
-rw-r--r--lib/alloc_tag.c21
-rw-r--r--lib/codetag.c34
-rw-r--r--lib/crypto/Makefile6
-rw-r--r--lib/crypto/aescfb.c8
-rw-r--r--lib/crypto/aesgcm.c46
-rw-r--r--lib/group_cpus.c9
-rw-r--r--lib/iov_iter.c2
-rw-r--r--lib/maple_tree.c5
-rw-r--r--lib/raid6/Makefile1
-rw-r--r--lib/raid6/algos.c9
-rw-r--r--lib/raid6/recov_rvv.c229
-rw-r--r--lib/raid6/rvv.c1220
-rw-r--r--lib/raid6/rvv.h39
-rw-r--r--lib/scatterlist.c8
-rw-r--r--lib/test_objagg.c4
16 files changed, 1592 insertions, 50 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
index 6c1b8f184267..37db228f70a9 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -716,6 +716,7 @@ config GENERIC_LIB_DEVMEM_IS_ALLOWED
config PLDMFW
bool
+ select CRC32
default n
config ASN1_ENCODER
diff --git a/lib/alloc_tag.c b/lib/alloc_tag.c
index 45dae7da70e1..0142bc916f73 100644
--- a/lib/alloc_tag.c
+++ b/lib/alloc_tag.c
@@ -10,6 +10,7 @@
#include <linux/seq_buf.h>
#include <linux/seq_file.h>
#include <linux/vmalloc.h>
+#include <linux/kmemleak.h>
#define ALLOCINFO_FILE_NAME "allocinfo"
#define MODULE_ALLOC_TAG_VMAP_SIZE (100000UL * sizeof(struct alloc_tag))
@@ -134,6 +135,9 @@ size_t alloc_tag_top_users(struct codetag_bytes *tags, size_t count, bool can_sl
struct codetag_bytes n;
unsigned int i, nr = 0;
+ if (IS_ERR_OR_NULL(alloc_tag_cttype))
+ return 0;
+
if (can_sleep)
codetag_lock_module_list(alloc_tag_cttype, true);
else if (!codetag_trylock_module_list(alloc_tag_cttype))
@@ -607,15 +611,16 @@ out:
mas_unlock(&mas);
}
-static void load_module(struct module *mod, struct codetag *start, struct codetag *stop)
+static int load_module(struct module *mod, struct codetag *start, struct codetag *stop)
{
/* Allocate module alloc_tag percpu counters */
struct alloc_tag *start_tag;
struct alloc_tag *stop_tag;
struct alloc_tag *tag;
+ /* percpu counters for core allocations are already statically allocated */
if (!mod)
- return;
+ return 0;
start_tag = ct_to_alloc_tag(start);
stop_tag = ct_to_alloc_tag(stop);
@@ -627,12 +632,18 @@ static void load_module(struct module *mod, struct codetag *start, struct codeta
free_percpu(tag->counters);
tag->counters = NULL;
}
- shutdown_mem_profiling(true);
- pr_err("Failed to allocate memory for allocation tag percpu counters in the module %s. Memory allocation profiling is disabled!\n",
+ pr_err("Failed to allocate memory for allocation tag percpu counters in the module %s\n",
mod->name);
- break;
+ return -ENOMEM;
}
+
+ /*
+ * Avoid a kmemleak false positive. The pointer to the counters is stored
+ * in the alloc_tag section of the module and cannot be directly accessed.
+ */
+ kmemleak_ignore_percpu(tag->counters);
}
+ return 0;
}
static void replace_module(struct module *mod, struct module *new_mod)
diff --git a/lib/codetag.c b/lib/codetag.c
index de332e98d6f5..650d54d7e14d 100644
--- a/lib/codetag.c
+++ b/lib/codetag.c
@@ -167,6 +167,7 @@ static int codetag_module_init(struct codetag_type *cttype, struct module *mod)
{
struct codetag_range range;
struct codetag_module *cmod;
+ int mod_id;
int err;
range = get_section_range(mod, cttype->desc.section);
@@ -190,11 +191,20 @@ static int codetag_module_init(struct codetag_type *cttype, struct module *mod)
cmod->range = range;
down_write(&cttype->mod_lock);
- err = idr_alloc(&cttype->mod_idr, cmod, 0, 0, GFP_KERNEL);
- if (err >= 0) {
- cttype->count += range_size(cttype, &range);
- if (cttype->desc.module_load)
- cttype->desc.module_load(mod, range.start, range.stop);
+ mod_id = idr_alloc(&cttype->mod_idr, cmod, 0, 0, GFP_KERNEL);
+ if (mod_id >= 0) {
+ if (cttype->desc.module_load) {
+ err = cttype->desc.module_load(mod, range.start, range.stop);
+ if (!err)
+ cttype->count += range_size(cttype, &range);
+ else
+ idr_remove(&cttype->mod_idr, mod_id);
+ } else {
+ cttype->count += range_size(cttype, &range);
+ err = 0;
+ }
+ } else {
+ err = mod_id;
}
up_write(&cttype->mod_lock);
@@ -295,17 +305,23 @@ void codetag_module_replaced(struct module *mod, struct module *new_mod)
mutex_unlock(&codetag_lock);
}
-void codetag_load_module(struct module *mod)
+int codetag_load_module(struct module *mod)
{
struct codetag_type *cttype;
+ int ret = 0;
if (!mod)
- return;
+ return 0;
mutex_lock(&codetag_lock);
- list_for_each_entry(cttype, &codetag_types, link)
- codetag_module_init(cttype, mod);
+ list_for_each_entry(cttype, &codetag_types, link) {
+ ret = codetag_module_init(cttype, mod);
+ if (ret)
+ break;
+ }
mutex_unlock(&codetag_lock);
+
+ return ret;
}
void codetag_unload_module(struct module *mod)
diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile
index 3e79283b617d..b0c0f8aea269 100644
--- a/lib/crypto/Makefile
+++ b/lib/crypto/Makefile
@@ -35,6 +35,10 @@ obj-$(CONFIG_CRYPTO_LIB_CURVE25519_GENERIC) += libcurve25519-generic.o
libcurve25519-generic-y := curve25519-fiat32.o
libcurve25519-generic-$(CONFIG_ARCH_SUPPORTS_INT128) := curve25519-hacl64.o
libcurve25519-generic-y += curve25519-generic.o
+# clang versions prior to 18 may blow out the stack with KASAN
+ifeq ($(call clang-min-version, 180000),)
+KASAN_SANITIZE_curve25519-hacl64.o := n
+endif
obj-$(CONFIG_CRYPTO_LIB_CURVE25519) += libcurve25519.o
libcurve25519-y += curve25519.o
@@ -62,7 +66,7 @@ libsha256-generic-y := sha256-generic.o
obj-$(CONFIG_MPILIB) += mpi/
-obj-$(CONFIG_CRYPTO_SELFTESTS) += simd.o
+obj-$(CONFIG_CRYPTO_SELFTESTS_FULL) += simd.o
obj-$(CONFIG_CRYPTO_LIB_SM3) += libsm3.o
libsm3-y := sm3.o
diff --git a/lib/crypto/aescfb.c b/lib/crypto/aescfb.c
index 437613265e14..2f09ae92ffa0 100644
--- a/lib/crypto/aescfb.c
+++ b/lib/crypto/aescfb.c
@@ -106,11 +106,11 @@ MODULE_LICENSE("GPL");
*/
static struct {
- u8 ptext[64];
- u8 ctext[64];
+ u8 ptext[64] __nonstring;
+ u8 ctext[64] __nonstring;
- u8 key[AES_MAX_KEY_SIZE];
- u8 iv[AES_BLOCK_SIZE];
+ u8 key[AES_MAX_KEY_SIZE] __nonstring;
+ u8 iv[AES_BLOCK_SIZE] __nonstring;
int klen;
int len;
diff --git a/lib/crypto/aesgcm.c b/lib/crypto/aesgcm.c
index 277824d6b4af..faa4dee9bb1b 100644
--- a/lib/crypto/aesgcm.c
+++ b/lib/crypto/aesgcm.c
@@ -205,19 +205,19 @@ MODULE_LICENSE("GPL");
* Test code below. Vectors taken from crypto/testmgr.h
*/
-static const u8 __initconst ctext0[16] =
+static const u8 __initconst ctext0[16] __nonstring =
"\x58\xe2\xfc\xce\xfa\x7e\x30\x61"
"\x36\x7f\x1d\x57\xa4\xe7\x45\x5a";
static const u8 __initconst ptext1[16];
-static const u8 __initconst ctext1[32] =
+static const u8 __initconst ctext1[32] __nonstring =
"\x03\x88\xda\xce\x60\xb6\xa3\x92"
"\xf3\x28\xc2\xb9\x71\xb2\xfe\x78"
"\xab\x6e\x47\xd4\x2c\xec\x13\xbd"
"\xf5\x3a\x67\xb2\x12\x57\xbd\xdf";
-static const u8 __initconst ptext2[64] =
+static const u8 __initconst ptext2[64] __nonstring =
"\xd9\x31\x32\x25\xf8\x84\x06\xe5"
"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
@@ -227,7 +227,7 @@ static const u8 __initconst ptext2[64] =
"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
"\xba\x63\x7b\x39\x1a\xaf\xd2\x55";
-static const u8 __initconst ctext2[80] =
+static const u8 __initconst ctext2[80] __nonstring =
"\x42\x83\x1e\xc2\x21\x77\x74\x24"
"\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
"\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0"
@@ -239,7 +239,7 @@ static const u8 __initconst ctext2[80] =
"\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6"
"\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4";
-static const u8 __initconst ptext3[60] =
+static const u8 __initconst ptext3[60] __nonstring =
"\xd9\x31\x32\x25\xf8\x84\x06\xe5"
"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
@@ -249,7 +249,7 @@ static const u8 __initconst ptext3[60] =
"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
"\xba\x63\x7b\x39";
-static const u8 __initconst ctext3[76] =
+static const u8 __initconst ctext3[76] __nonstring =
"\x42\x83\x1e\xc2\x21\x77\x74\x24"
"\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
"\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0"
@@ -261,17 +261,17 @@ static const u8 __initconst ctext3[76] =
"\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb"
"\x94\xfa\xe9\x5a\xe7\x12\x1a\x47";
-static const u8 __initconst ctext4[16] =
+static const u8 __initconst ctext4[16] __nonstring =
"\xcd\x33\xb2\x8a\xc7\x73\xf7\x4b"
"\xa0\x0e\xd1\xf3\x12\x57\x24\x35";
-static const u8 __initconst ctext5[32] =
+static const u8 __initconst ctext5[32] __nonstring =
"\x98\xe7\x24\x7c\x07\xf0\xfe\x41"
"\x1c\x26\x7e\x43\x84\xb0\xf6\x00"
"\x2f\xf5\x8d\x80\x03\x39\x27\xab"
"\x8e\xf4\xd4\x58\x75\x14\xf0\xfb";
-static const u8 __initconst ptext6[64] =
+static const u8 __initconst ptext6[64] __nonstring =
"\xd9\x31\x32\x25\xf8\x84\x06\xe5"
"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
@@ -281,7 +281,7 @@ static const u8 __initconst ptext6[64] =
"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
"\xba\x63\x7b\x39\x1a\xaf\xd2\x55";
-static const u8 __initconst ctext6[80] =
+static const u8 __initconst ctext6[80] __nonstring =
"\x39\x80\xca\x0b\x3c\x00\xe8\x41"
"\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
"\x85\x9e\x1c\xea\xa6\xef\xd9\x84"
@@ -293,17 +293,17 @@ static const u8 __initconst ctext6[80] =
"\x99\x24\xa7\xc8\x58\x73\x36\xbf"
"\xb1\x18\x02\x4d\xb8\x67\x4a\x14";
-static const u8 __initconst ctext7[16] =
+static const u8 __initconst ctext7[16] __nonstring =
"\x53\x0f\x8a\xfb\xc7\x45\x36\xb9"
"\xa9\x63\xb4\xf1\xc4\xcb\x73\x8b";
-static const u8 __initconst ctext8[32] =
+static const u8 __initconst ctext8[32] __nonstring =
"\xce\xa7\x40\x3d\x4d\x60\x6b\x6e"
"\x07\x4e\xc5\xd3\xba\xf3\x9d\x18"
"\xd0\xd1\xc8\xa7\x99\x99\x6b\xf0"
"\x26\x5b\x98\xb5\xd4\x8a\xb9\x19";
-static const u8 __initconst ptext9[64] =
+static const u8 __initconst ptext9[64] __nonstring =
"\xd9\x31\x32\x25\xf8\x84\x06\xe5"
"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
@@ -313,7 +313,7 @@ static const u8 __initconst ptext9[64] =
"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
"\xba\x63\x7b\x39\x1a\xaf\xd2\x55";
-static const u8 __initconst ctext9[80] =
+static const u8 __initconst ctext9[80] __nonstring =
"\x52\x2d\xc1\xf0\x99\x56\x7d\x07"
"\xf4\x7f\x37\xa3\x2a\x84\x42\x7d"
"\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9"
@@ -325,7 +325,7 @@ static const u8 __initconst ctext9[80] =
"\xb0\x94\xda\xc5\xd9\x34\x71\xbd"
"\xec\x1a\x50\x22\x70\xe3\xcc\x6c";
-static const u8 __initconst ptext10[60] =
+static const u8 __initconst ptext10[60] __nonstring =
"\xd9\x31\x32\x25\xf8\x84\x06\xe5"
"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
@@ -335,7 +335,7 @@ static const u8 __initconst ptext10[60] =
"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
"\xba\x63\x7b\x39";
-static const u8 __initconst ctext10[76] =
+static const u8 __initconst ctext10[76] __nonstring =
"\x52\x2d\xc1\xf0\x99\x56\x7d\x07"
"\xf4\x7f\x37\xa3\x2a\x84\x42\x7d"
"\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9"
@@ -347,7 +347,7 @@ static const u8 __initconst ctext10[76] =
"\x76\xfc\x6e\xce\x0f\x4e\x17\x68"
"\xcd\xdf\x88\x53\xbb\x2d\x55\x1b";
-static const u8 __initconst ptext11[60] =
+static const u8 __initconst ptext11[60] __nonstring =
"\xd9\x31\x32\x25\xf8\x84\x06\xe5"
"\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
"\x86\xa7\xa9\x53\x15\x34\xf7\xda"
@@ -357,7 +357,7 @@ static const u8 __initconst ptext11[60] =
"\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
"\xba\x63\x7b\x39";
-static const u8 __initconst ctext11[76] =
+static const u8 __initconst ctext11[76] __nonstring =
"\x39\x80\xca\x0b\x3c\x00\xe8\x41"
"\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
"\x85\x9e\x1c\xea\xa6\xef\xd9\x84"
@@ -369,7 +369,7 @@ static const u8 __initconst ctext11[76] =
"\x25\x19\x49\x8e\x80\xf1\x47\x8f"
"\x37\xba\x55\xbd\x6d\x27\x61\x8c";
-static const u8 __initconst ptext12[719] =
+static const u8 __initconst ptext12[719] __nonstring =
"\x42\xc1\xcc\x08\x48\x6f\x41\x3f"
"\x2f\x11\x66\x8b\x2a\x16\xf0\xe0"
"\x58\x83\xf0\xc3\x70\x14\xc0\x5b"
@@ -461,7 +461,7 @@ static const u8 __initconst ptext12[719] =
"\x59\xfa\xfa\xaa\x44\x04\x01\xa7"
"\xa4\x78\xdb\x74\x3d\x8b\xb5";
-static const u8 __initconst ctext12[735] =
+static const u8 __initconst ctext12[735] __nonstring =
"\x84\x0b\xdb\xd5\xb7\xa8\xfe\x20"
"\xbb\xb1\x12\x7f\x41\xea\xb3\xc0"
"\xa2\xb4\x37\x19\x11\x58\xb6\x0b"
@@ -559,9 +559,9 @@ static struct {
const u8 *ptext;
const u8 *ctext;
- u8 key[AES_MAX_KEY_SIZE];
- u8 iv[GCM_AES_IV_SIZE];
- u8 assoc[20];
+ u8 key[AES_MAX_KEY_SIZE] __nonstring;
+ u8 iv[GCM_AES_IV_SIZE] __nonstring;
+ u8 assoc[20] __nonstring;
int klen;
int clen;
diff --git a/lib/group_cpus.c b/lib/group_cpus.c
index ee272c4cefcc..18d43a406114 100644
--- a/lib/group_cpus.c
+++ b/lib/group_cpus.c
@@ -352,6 +352,9 @@ struct cpumask *group_cpus_evenly(unsigned int numgrps)
int ret = -ENOMEM;
struct cpumask *masks = NULL;
+ if (numgrps == 0)
+ return NULL;
+
if (!zalloc_cpumask_var(&nmsk, GFP_KERNEL))
return NULL;
@@ -426,8 +429,12 @@ struct cpumask *group_cpus_evenly(unsigned int numgrps)
#else /* CONFIG_SMP */
struct cpumask *group_cpus_evenly(unsigned int numgrps)
{
- struct cpumask *masks = kcalloc(numgrps, sizeof(*masks), GFP_KERNEL);
+ struct cpumask *masks;
+ if (numgrps == 0)
+ return NULL;
+
+ masks = kcalloc(numgrps, sizeof(*masks), GFP_KERNEL);
if (!masks)
return NULL;
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index 969d4ad510df..f9193f952f49 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -817,7 +817,7 @@ static bool iov_iter_aligned_bvec(const struct iov_iter *i, unsigned addr_mask,
size_t size = i->count;
do {
- size_t len = bvec->bv_len;
+ size_t len = bvec->bv_len - skip;
if (len > size)
len = size;
diff --git a/lib/maple_tree.c b/lib/maple_tree.c
index affe979bd14d..ef66be963798 100644
--- a/lib/maple_tree.c
+++ b/lib/maple_tree.c
@@ -5319,6 +5319,7 @@ static void mt_destroy_walk(struct maple_enode *enode, struct maple_tree *mt,
struct maple_enode *start;
if (mte_is_leaf(enode)) {
+ mte_set_node_dead(enode);
node->type = mte_node_type(enode);
goto free_leaf;
}
@@ -5527,8 +5528,9 @@ int mas_preallocate(struct ma_state *mas, void *entry, gfp_t gfp)
mas->store_type = mas_wr_store_type(&wr_mas);
request = mas_prealloc_calc(&wr_mas, entry);
if (!request)
- return ret;
+ goto set_flag;
+ mas->mas_flags &= ~MA_STATE_PREALLOC;
mas_node_count_gfp(mas, request, gfp);
if (mas_is_err(mas)) {
mas_set_alloc_req(mas, 0);
@@ -5538,6 +5540,7 @@ int mas_preallocate(struct ma_state *mas, void *entry, gfp_t gfp)
return ret;
}
+set_flag:
mas->mas_flags |= MA_STATE_PREALLOC;
return ret;
}
diff --git a/lib/raid6/Makefile b/lib/raid6/Makefile
index 29127dd05d63..5be0a4e60ab1 100644
--- a/lib/raid6/Makefile
+++ b/lib/raid6/Makefile
@@ -10,6 +10,7 @@ raid6_pq-$(CONFIG_ALTIVEC) += altivec1.o altivec2.o altivec4.o altivec8.o \
raid6_pq-$(CONFIG_KERNEL_MODE_NEON) += neon.o neon1.o neon2.o neon4.o neon8.o recov_neon.o recov_neon_inner.o
raid6_pq-$(CONFIG_S390) += s390vx8.o recov_s390xc.o
raid6_pq-$(CONFIG_LOONGARCH) += loongarch_simd.o recov_loongarch_simd.o
+raid6_pq-$(CONFIG_RISCV_ISA_V) += rvv.o recov_rvv.o
hostprogs += mktables
diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
index dfd3f800ac9b..75ce3e134b7c 100644
--- a/lib/raid6/algos.c
+++ b/lib/raid6/algos.c
@@ -77,6 +77,12 @@ const struct raid6_calls * const raid6_algos[] = {
&raid6_lsx,
#endif
#endif
+#ifdef CONFIG_RISCV_ISA_V
+ &raid6_rvvx1,
+ &raid6_rvvx2,
+ &raid6_rvvx4,
+ &raid6_rvvx8,
+#endif
&raid6_intx8,
&raid6_intx4,
&raid6_intx2,
@@ -110,6 +116,9 @@ const struct raid6_recov_calls *const raid6_recov_algos[] = {
&raid6_recov_lsx,
#endif
#endif
+#ifdef CONFIG_RISCV_ISA_V
+ &raid6_recov_rvv,
+#endif
&raid6_recov_intx1,
NULL
};
diff --git a/lib/raid6/recov_rvv.c b/lib/raid6/recov_rvv.c
new file mode 100644
index 000000000000..f29303795ccf
--- /dev/null
+++ b/lib/raid6/recov_rvv.c
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2024 Institute of Software, CAS.
+ * Author: Chunyan Zhang <zhangchunyan@iscas.ac.cn>
+ */
+
+#include <asm/simd.h>
+#include <asm/vector.h>
+#include <crypto/internal/simd.h>
+#include <linux/raid/pq.h>
+
+static int rvv_has_vector(void)
+{
+ return has_vector();
+}
+
+static void __raid6_2data_recov_rvv(int bytes, u8 *p, u8 *q, u8 *dp,
+ u8 *dq, const u8 *pbmul,
+ const u8 *qmul)
+{
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsetvli x0, %[avl], e8, m1, ta, ma\n"
+ ".option pop\n"
+ : :
+ [avl]"r"(16)
+ );
+
+ /*
+ * while ( bytes-- ) {
+ * uint8_t px, qx, db;
+ *
+ * px = *p ^ *dp;
+ * qx = qmul[*q ^ *dq];
+ * *dq++ = db = pbmul[px] ^ qx;
+ * *dp++ = db ^ px;
+ * p++; q++;
+ * }
+ */
+ while (bytes) {
+ /*
+ * v0:px, v1:dp,
+ * v2:qx, v3:dq,
+ * v4:vx, v5:vy,
+ * v6:qm0, v7:qm1,
+ * v8:pm0, v9:pm1,
+ * v14:p/qm[vx], v15:p/qm[vy]
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vle8.v v0, (%[px])\n"
+ "vle8.v v1, (%[dp])\n"
+ "vxor.vv v0, v0, v1\n"
+ "vle8.v v2, (%[qx])\n"
+ "vle8.v v3, (%[dq])\n"
+ "vxor.vv v4, v2, v3\n"
+ "vsrl.vi v5, v4, 4\n"
+ "vand.vi v4, v4, 0xf\n"
+ "vle8.v v6, (%[qm0])\n"
+ "vle8.v v7, (%[qm1])\n"
+ "vrgather.vv v14, v6, v4\n" /* v14 = qm[vx] */
+ "vrgather.vv v15, v7, v5\n" /* v15 = qm[vy] */
+ "vxor.vv v2, v14, v15\n" /* v2 = qmul[*q ^ *dq] */
+
+ "vsrl.vi v5, v0, 4\n"
+ "vand.vi v4, v0, 0xf\n"
+ "vle8.v v8, (%[pm0])\n"
+ "vle8.v v9, (%[pm1])\n"
+ "vrgather.vv v14, v8, v4\n" /* v14 = pm[vx] */
+ "vrgather.vv v15, v9, v5\n" /* v15 = pm[vy] */
+ "vxor.vv v4, v14, v15\n" /* v4 = pbmul[px] */
+ "vxor.vv v3, v4, v2\n" /* v3 = db = pbmul[px] ^ qx */
+ "vxor.vv v1, v3, v0\n" /* v1 = db ^ px; */
+ "vse8.v v3, (%[dq])\n"
+ "vse8.v v1, (%[dp])\n"
+ ".option pop\n"
+ : :
+ [px]"r"(p),
+ [dp]"r"(dp),
+ [qx]"r"(q),
+ [dq]"r"(dq),
+ [qm0]"r"(qmul),
+ [qm1]"r"(qmul + 16),
+ [pm0]"r"(pbmul),
+ [pm1]"r"(pbmul + 16)
+ :);
+
+ bytes -= 16;
+ p += 16;
+ q += 16;
+ dp += 16;
+ dq += 16;
+ }
+}
+
+static void __raid6_datap_recov_rvv(int bytes, u8 *p, u8 *q,
+ u8 *dq, const u8 *qmul)
+{
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsetvli x0, %[avl], e8, m1, ta, ma\n"
+ ".option pop\n"
+ : :
+ [avl]"r"(16)
+ );
+
+ /*
+ * while (bytes--) {
+ * *p++ ^= *dq = qmul[*q ^ *dq];
+ * q++; dq++;
+ * }
+ */
+ while (bytes) {
+ /*
+ * v0:vx, v1:vy,
+ * v2:dq, v3:p,
+ * v4:qm0, v5:qm1,
+ * v10:m[vx], v11:m[vy]
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vle8.v v0, (%[vx])\n"
+ "vle8.v v2, (%[dq])\n"
+ "vxor.vv v0, v0, v2\n"
+ "vsrl.vi v1, v0, 4\n"
+ "vand.vi v0, v0, 0xf\n"
+ "vle8.v v4, (%[qm0])\n"
+ "vle8.v v5, (%[qm1])\n"
+ "vrgather.vv v10, v4, v0\n"
+ "vrgather.vv v11, v5, v1\n"
+ "vxor.vv v0, v10, v11\n"
+ "vle8.v v1, (%[vy])\n"
+ "vxor.vv v1, v0, v1\n"
+ "vse8.v v0, (%[dq])\n"
+ "vse8.v v1, (%[vy])\n"
+ ".option pop\n"
+ : :
+ [vx]"r"(q),
+ [vy]"r"(p),
+ [dq]"r"(dq),
+ [qm0]"r"(qmul),
+ [qm1]"r"(qmul + 16)
+ :);
+
+ bytes -= 16;
+ p += 16;
+ q += 16;
+ dq += 16;
+ }
+}
+
+static void raid6_2data_recov_rvv(int disks, size_t bytes, int faila,
+ int failb, void **ptrs)
+{
+ u8 *p, *q, *dp, *dq;
+ const u8 *pbmul; /* P multiplier table for B data */
+ const u8 *qmul; /* Q multiplier table (for both) */
+
+ p = (u8 *)ptrs[disks - 2];
+ q = (u8 *)ptrs[disks - 1];
+
+ /*
+ * Compute syndrome with zero for the missing data pages
+ * Use the dead data pages as temporary storage for
+ * delta p and delta q
+ */
+ dp = (u8 *)ptrs[faila];
+ ptrs[faila] = (void *)raid6_empty_zero_page;
+ ptrs[disks - 2] = dp;
+ dq = (u8 *)ptrs[failb];
+ ptrs[failb] = (void *)raid6_empty_zero_page;
+ ptrs[disks - 1] = dq;
+
+ raid6_call.gen_syndrome(disks, bytes, ptrs);
+
+ /* Restore pointer table */
+ ptrs[faila] = dp;
+ ptrs[failb] = dq;
+ ptrs[disks - 2] = p;
+ ptrs[disks - 1] = q;
+
+ /* Now, pick the proper data tables */
+ pbmul = raid6_vgfmul[raid6_gfexi[failb - faila]];
+ qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila] ^
+ raid6_gfexp[failb]]];
+
+ kernel_vector_begin();
+ __raid6_2data_recov_rvv(bytes, p, q, dp, dq, pbmul, qmul);
+ kernel_vector_end();
+}
+
+static void raid6_datap_recov_rvv(int disks, size_t bytes, int faila,
+ void **ptrs)
+{
+ u8 *p, *q, *dq;
+ const u8 *qmul; /* Q multiplier table */
+
+ p = (u8 *)ptrs[disks - 2];
+ q = (u8 *)ptrs[disks - 1];
+
+ /*
+ * Compute syndrome with zero for the missing data page
+ * Use the dead data page as temporary storage for delta q
+ */
+ dq = (u8 *)ptrs[faila];
+ ptrs[faila] = (void *)raid6_empty_zero_page;
+ ptrs[disks - 1] = dq;
+
+ raid6_call.gen_syndrome(disks, bytes, ptrs);
+
+ /* Restore pointer table */
+ ptrs[faila] = dq;
+ ptrs[disks - 1] = q;
+
+ /* Now, pick the proper data tables */
+ qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila]]];
+
+ kernel_vector_begin();
+ __raid6_datap_recov_rvv(bytes, p, q, dq, qmul);
+ kernel_vector_end();
+}
+
+const struct raid6_recov_calls raid6_recov_rvv = {
+ .data2 = raid6_2data_recov_rvv,
+ .datap = raid6_datap_recov_rvv,
+ .valid = rvv_has_vector,
+ .name = "rvv",
+ .priority = 1,
+};
diff --git a/lib/raid6/rvv.c b/lib/raid6/rvv.c
new file mode 100644
index 000000000000..7d82efa5b14f
--- /dev/null
+++ b/lib/raid6/rvv.c
@@ -0,0 +1,1220 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * RAID-6 syndrome calculation using RISC-V vector instructions
+ *
+ * Copyright 2024 Institute of Software, CAS.
+ * Author: Chunyan Zhang <zhangchunyan@iscas.ac.cn>
+ *
+ * Based on neon.uc:
+ * Copyright 2002-2004 H. Peter Anvin
+ */
+
+#include <asm/simd.h>
+#include <asm/vector.h>
+#include <crypto/internal/simd.h>
+#include <linux/raid/pq.h>
+#include <linux/types.h>
+#include "rvv.h"
+
+#define NSIZE (riscv_v_vsize / 32) /* NSIZE = vlenb */
+
+static int rvv_has_vector(void)
+{
+ return has_vector();
+}
+
+static void raid6_rvv1_gen_syndrome_real(int disks, unsigned long bytes, void **ptrs)
+{
+ u8 **dptr = (u8 **)ptrs;
+ u8 *p, *q;
+ unsigned long vl, d;
+ int z, z0;
+
+ z0 = disks - 3; /* Highest data disk */
+ p = dptr[z0 + 1]; /* XOR parity */
+ q = dptr[z0 + 2]; /* RS syndrome */
+
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsetvli %0, x0, e8, m1, ta, ma\n"
+ ".option pop\n"
+ : "=&r" (vl)
+ );
+
+ /* v0:wp0, v1:wq0, v2:wd0/w20, v3:w10 */
+ for (d = 0; d < bytes; d += NSIZE * 1) {
+ /* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vle8.v v0, (%[wp0])\n"
+ "vle8.v v1, (%[wp0])\n"
+ ".option pop\n"
+ : :
+ [wp0]"r"(&dptr[z0][d + 0 * NSIZE])
+ );
+
+ for (z = z0 - 1 ; z >= 0 ; z--) {
+ /*
+ * w2$$ = MASK(wq$$);
+ * w1$$ = SHLBYTE(wq$$);
+ * w2$$ &= NBYTES(0x1d);
+ * w1$$ ^= w2$$;
+ * wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE];
+ * wq$$ = w1$$ ^ wd$$;
+ * wp$$ ^= wd$$;
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsra.vi v2, v1, 7\n"
+ "vsll.vi v3, v1, 1\n"
+ "vand.vx v2, v2, %[x1d]\n"
+ "vxor.vv v3, v3, v2\n"
+ "vle8.v v2, (%[wd0])\n"
+ "vxor.vv v1, v3, v2\n"
+ "vxor.vv v0, v0, v2\n"
+ ".option pop\n"
+ : :
+ [wd0]"r"(&dptr[z][d + 0 * NSIZE]),
+ [x1d]"r"(0x1d)
+ );
+ }
+
+ /*
+ * *(unative_t *)&p[d+NSIZE*$$] = wp$$;
+ * *(unative_t *)&q[d+NSIZE*$$] = wq$$;
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vse8.v v0, (%[wp0])\n"
+ "vse8.v v1, (%[wq0])\n"
+ ".option pop\n"
+ : :
+ [wp0]"r"(&p[d + NSIZE * 0]),
+ [wq0]"r"(&q[d + NSIZE * 0])
+ );
+ }
+}
+
+static void raid6_rvv1_xor_syndrome_real(int disks, int start, int stop,
+ unsigned long bytes, void **ptrs)
+{
+ u8 **dptr = (u8 **)ptrs;
+ u8 *p, *q;
+ unsigned long vl, d;
+ int z, z0;
+
+ z0 = stop; /* P/Q right side optimization */
+ p = dptr[disks - 2]; /* XOR parity */
+ q = dptr[disks - 1]; /* RS syndrome */
+
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsetvli %0, x0, e8, m1, ta, ma\n"
+ ".option pop\n"
+ : "=&r" (vl)
+ );
+
+ /* v0:wp0, v1:wq0, v2:wd0/w20, v3:w10 */
+ for (d = 0 ; d < bytes ; d += NSIZE * 1) {
+ /* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vle8.v v0, (%[wp0])\n"
+ "vle8.v v1, (%[wp0])\n"
+ ".option pop\n"
+ : :
+ [wp0]"r"(&dptr[z0][d + 0 * NSIZE])
+ );
+
+ /* P/Q data pages */
+ for (z = z0 - 1; z >= start; z--) {
+ /*
+ * w2$$ = MASK(wq$$);
+ * w1$$ = SHLBYTE(wq$$);
+ * w2$$ &= NBYTES(0x1d);
+ * w1$$ ^= w2$$;
+ * wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE];
+ * wq$$ = w1$$ ^ wd$$;
+ * wp$$ ^= wd$$;
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsra.vi v2, v1, 7\n"
+ "vsll.vi v3, v1, 1\n"
+ "vand.vx v2, v2, %[x1d]\n"
+ "vxor.vv v3, v3, v2\n"
+ "vle8.v v2, (%[wd0])\n"
+ "vxor.vv v1, v3, v2\n"
+ "vxor.vv v0, v0, v2\n"
+ ".option pop\n"
+ : :
+ [wd0]"r"(&dptr[z][d + 0 * NSIZE]),
+ [x1d]"r"(0x1d)
+ );
+ }
+
+ /* P/Q left side optimization */
+ for (z = start - 1; z >= 0; z--) {
+ /*
+ * w2$$ = MASK(wq$$);
+ * w1$$ = SHLBYTE(wq$$);
+ * w2$$ &= NBYTES(0x1d);
+ * wq$$ = w1$$ ^ w2$$;
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsra.vi v2, v1, 7\n"
+ "vsll.vi v3, v1, 1\n"
+ "vand.vx v2, v2, %[x1d]\n"
+ "vxor.vv v1, v3, v2\n"
+ ".option pop\n"
+ : :
+ [x1d]"r"(0x1d)
+ );
+ }
+
+ /*
+ * *(unative_t *)&p[d+NSIZE*$$] ^= wp$$;
+ * *(unative_t *)&q[d+NSIZE*$$] ^= wq$$;
+ * v0:wp0, v1:wq0, v2:p0, v3:q0
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vle8.v v2, (%[wp0])\n"
+ "vle8.v v3, (%[wq0])\n"
+ "vxor.vv v2, v2, v0\n"
+ "vxor.vv v3, v3, v1\n"
+ "vse8.v v2, (%[wp0])\n"
+ "vse8.v v3, (%[wq0])\n"
+ ".option pop\n"
+ : :
+ [wp0]"r"(&p[d + NSIZE * 0]),
+ [wq0]"r"(&q[d + NSIZE * 0])
+ );
+ }
+}
+
+static void raid6_rvv2_gen_syndrome_real(int disks, unsigned long bytes, void **ptrs)
+{
+ u8 **dptr = (u8 **)ptrs;
+ u8 *p, *q;
+ unsigned long vl, d;
+ int z, z0;
+
+ z0 = disks - 3; /* Highest data disk */
+ p = dptr[z0 + 1]; /* XOR parity */
+ q = dptr[z0 + 2]; /* RS syndrome */
+
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsetvli %0, x0, e8, m1, ta, ma\n"
+ ".option pop\n"
+ : "=&r" (vl)
+ );
+
+ /*
+ * v0:wp0, v1:wq0, v2:wd0/w20, v3:w10
+ * v4:wp1, v5:wq1, v6:wd1/w21, v7:w11
+ */
+ for (d = 0; d < bytes; d += NSIZE * 2) {
+ /* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vle8.v v0, (%[wp0])\n"
+ "vle8.v v1, (%[wp0])\n"
+ "vle8.v v4, (%[wp1])\n"
+ "vle8.v v5, (%[wp1])\n"
+ ".option pop\n"
+ : :
+ [wp0]"r"(&dptr[z0][d + 0 * NSIZE]),
+ [wp1]"r"(&dptr[z0][d + 1 * NSIZE])
+ );
+
+ for (z = z0 - 1; z >= 0; z--) {
+ /*
+ * w2$$ = MASK(wq$$);
+ * w1$$ = SHLBYTE(wq$$);
+ * w2$$ &= NBYTES(0x1d);
+ * w1$$ ^= w2$$;
+ * wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE];
+ * wq$$ = w1$$ ^ wd$$;
+ * wp$$ ^= wd$$;
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsra.vi v2, v1, 7\n"
+ "vsll.vi v3, v1, 1\n"
+ "vand.vx v2, v2, %[x1d]\n"
+ "vxor.vv v3, v3, v2\n"
+ "vle8.v v2, (%[wd0])\n"
+ "vxor.vv v1, v3, v2\n"
+ "vxor.vv v0, v0, v2\n"
+
+ "vsra.vi v6, v5, 7\n"
+ "vsll.vi v7, v5, 1\n"
+ "vand.vx v6, v6, %[x1d]\n"
+ "vxor.vv v7, v7, v6\n"
+ "vle8.v v6, (%[wd1])\n"
+ "vxor.vv v5, v7, v6\n"
+ "vxor.vv v4, v4, v6\n"
+ ".option pop\n"
+ : :
+ [wd0]"r"(&dptr[z][d + 0 * NSIZE]),
+ [wd1]"r"(&dptr[z][d + 1 * NSIZE]),
+ [x1d]"r"(0x1d)
+ );
+ }
+
+ /*
+ * *(unative_t *)&p[d+NSIZE*$$] = wp$$;
+ * *(unative_t *)&q[d+NSIZE*$$] = wq$$;
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vse8.v v0, (%[wp0])\n"
+ "vse8.v v1, (%[wq0])\n"
+ "vse8.v v4, (%[wp1])\n"
+ "vse8.v v5, (%[wq1])\n"
+ ".option pop\n"
+ : :
+ [wp0]"r"(&p[d + NSIZE * 0]),
+ [wq0]"r"(&q[d + NSIZE * 0]),
+ [wp1]"r"(&p[d + NSIZE * 1]),
+ [wq1]"r"(&q[d + NSIZE * 1])
+ );
+ }
+}
+
+static void raid6_rvv2_xor_syndrome_real(int disks, int start, int stop,
+ unsigned long bytes, void **ptrs)
+{
+ u8 **dptr = (u8 **)ptrs;
+ u8 *p, *q;
+ unsigned long vl, d;
+ int z, z0;
+
+ z0 = stop; /* P/Q right side optimization */
+ p = dptr[disks - 2]; /* XOR parity */
+ q = dptr[disks - 1]; /* RS syndrome */
+
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsetvli %0, x0, e8, m1, ta, ma\n"
+ ".option pop\n"
+ : "=&r" (vl)
+ );
+
+ /*
+ * v0:wp0, v1:wq0, v2:wd0/w20, v3:w10
+ * v4:wp1, v5:wq1, v6:wd1/w21, v7:w11
+ */
+ for (d = 0; d < bytes; d += NSIZE * 2) {
+ /* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vle8.v v0, (%[wp0])\n"
+ "vle8.v v1, (%[wp0])\n"
+ "vle8.v v4, (%[wp1])\n"
+ "vle8.v v5, (%[wp1])\n"
+ ".option pop\n"
+ : :
+ [wp0]"r"(&dptr[z0][d + 0 * NSIZE]),
+ [wp1]"r"(&dptr[z0][d + 1 * NSIZE])
+ );
+
+ /* P/Q data pages */
+ for (z = z0 - 1; z >= start; z--) {
+ /*
+ * w2$$ = MASK(wq$$);
+ * w1$$ = SHLBYTE(wq$$);
+ * w2$$ &= NBYTES(0x1d);
+ * w1$$ ^= w2$$;
+ * wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE];
+ * wq$$ = w1$$ ^ wd$$;
+ * wp$$ ^= wd$$;
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsra.vi v2, v1, 7\n"
+ "vsll.vi v3, v1, 1\n"
+ "vand.vx v2, v2, %[x1d]\n"
+ "vxor.vv v3, v3, v2\n"
+ "vle8.v v2, (%[wd0])\n"
+ "vxor.vv v1, v3, v2\n"
+ "vxor.vv v0, v0, v2\n"
+
+ "vsra.vi v6, v5, 7\n"
+ "vsll.vi v7, v5, 1\n"
+ "vand.vx v6, v6, %[x1d]\n"
+ "vxor.vv v7, v7, v6\n"
+ "vle8.v v6, (%[wd1])\n"
+ "vxor.vv v5, v7, v6\n"
+ "vxor.vv v4, v4, v6\n"
+ ".option pop\n"
+ : :
+ [wd0]"r"(&dptr[z][d + 0 * NSIZE]),
+ [wd1]"r"(&dptr[z][d + 1 * NSIZE]),
+ [x1d]"r"(0x1d)
+ );
+ }
+
+ /* P/Q left side optimization */
+ for (z = start - 1; z >= 0; z--) {
+ /*
+ * w2$$ = MASK(wq$$);
+ * w1$$ = SHLBYTE(wq$$);
+ * w2$$ &= NBYTES(0x1d);
+ * wq$$ = w1$$ ^ w2$$;
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsra.vi v2, v1, 7\n"
+ "vsll.vi v3, v1, 1\n"
+ "vand.vx v2, v2, %[x1d]\n"
+ "vxor.vv v1, v3, v2\n"
+
+ "vsra.vi v6, v5, 7\n"
+ "vsll.vi v7, v5, 1\n"
+ "vand.vx v6, v6, %[x1d]\n"
+ "vxor.vv v5, v7, v6\n"
+ ".option pop\n"
+ : :
+ [x1d]"r"(0x1d)
+ );
+ }
+
+ /*
+ * *(unative_t *)&p[d+NSIZE*$$] ^= wp$$;
+ * *(unative_t *)&q[d+NSIZE*$$] ^= wq$$;
+ * v0:wp0, v1:wq0, v2:p0, v3:q0
+ * v4:wp1, v5:wq1, v6:p1, v7:q1
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vle8.v v2, (%[wp0])\n"
+ "vle8.v v3, (%[wq0])\n"
+ "vxor.vv v2, v2, v0\n"
+ "vxor.vv v3, v3, v1\n"
+ "vse8.v v2, (%[wp0])\n"
+ "vse8.v v3, (%[wq0])\n"
+
+ "vle8.v v6, (%[wp1])\n"
+ "vle8.v v7, (%[wq1])\n"
+ "vxor.vv v6, v6, v4\n"
+ "vxor.vv v7, v7, v5\n"
+ "vse8.v v6, (%[wp1])\n"
+ "vse8.v v7, (%[wq1])\n"
+ ".option pop\n"
+ : :
+ [wp0]"r"(&p[d + NSIZE * 0]),
+ [wq0]"r"(&q[d + NSIZE * 0]),
+ [wp1]"r"(&p[d + NSIZE * 1]),
+ [wq1]"r"(&q[d + NSIZE * 1])
+ );
+ }
+}
+
+static void raid6_rvv4_gen_syndrome_real(int disks, unsigned long bytes, void **ptrs)
+{
+ u8 **dptr = (u8 **)ptrs;
+ u8 *p, *q;
+ unsigned long vl, d;
+ int z, z0;
+
+ z0 = disks - 3; /* Highest data disk */
+ p = dptr[z0 + 1]; /* XOR parity */
+ q = dptr[z0 + 2]; /* RS syndrome */
+
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsetvli %0, x0, e8, m1, ta, ma\n"
+ ".option pop\n"
+ : "=&r" (vl)
+ );
+
+ /*
+ * v0:wp0, v1:wq0, v2:wd0/w20, v3:w10
+ * v4:wp1, v5:wq1, v6:wd1/w21, v7:w11
+ * v8:wp2, v9:wq2, v10:wd2/w22, v11:w12
+ * v12:wp3, v13:wq3, v14:wd3/w23, v15:w13
+ */
+ for (d = 0; d < bytes; d += NSIZE * 4) {
+ /* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vle8.v v0, (%[wp0])\n"
+ "vle8.v v1, (%[wp0])\n"
+ "vle8.v v4, (%[wp1])\n"
+ "vle8.v v5, (%[wp1])\n"
+ "vle8.v v8, (%[wp2])\n"
+ "vle8.v v9, (%[wp2])\n"
+ "vle8.v v12, (%[wp3])\n"
+ "vle8.v v13, (%[wp3])\n"
+ ".option pop\n"
+ : :
+ [wp0]"r"(&dptr[z0][d + 0 * NSIZE]),
+ [wp1]"r"(&dptr[z0][d + 1 * NSIZE]),
+ [wp2]"r"(&dptr[z0][d + 2 * NSIZE]),
+ [wp3]"r"(&dptr[z0][d + 3 * NSIZE])
+ );
+
+ for (z = z0 - 1; z >= 0; z--) {
+ /*
+ * w2$$ = MASK(wq$$);
+ * w1$$ = SHLBYTE(wq$$);
+ * w2$$ &= NBYTES(0x1d);
+ * w1$$ ^= w2$$;
+ * wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE];
+ * wq$$ = w1$$ ^ wd$$;
+ * wp$$ ^= wd$$;
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsra.vi v2, v1, 7\n"
+ "vsll.vi v3, v1, 1\n"
+ "vand.vx v2, v2, %[x1d]\n"
+ "vxor.vv v3, v3, v2\n"
+ "vle8.v v2, (%[wd0])\n"
+ "vxor.vv v1, v3, v2\n"
+ "vxor.vv v0, v0, v2\n"
+
+ "vsra.vi v6, v5, 7\n"
+ "vsll.vi v7, v5, 1\n"
+ "vand.vx v6, v6, %[x1d]\n"
+ "vxor.vv v7, v7, v6\n"
+ "vle8.v v6, (%[wd1])\n"
+ "vxor.vv v5, v7, v6\n"
+ "vxor.vv v4, v4, v6\n"
+
+ "vsra.vi v10, v9, 7\n"
+ "vsll.vi v11, v9, 1\n"
+ "vand.vx v10, v10, %[x1d]\n"
+ "vxor.vv v11, v11, v10\n"
+ "vle8.v v10, (%[wd2])\n"
+ "vxor.vv v9, v11, v10\n"
+ "vxor.vv v8, v8, v10\n"
+
+ "vsra.vi v14, v13, 7\n"
+ "vsll.vi v15, v13, 1\n"
+ "vand.vx v14, v14, %[x1d]\n"
+ "vxor.vv v15, v15, v14\n"
+ "vle8.v v14, (%[wd3])\n"
+ "vxor.vv v13, v15, v14\n"
+ "vxor.vv v12, v12, v14\n"
+ ".option pop\n"
+ : :
+ [wd0]"r"(&dptr[z][d + 0 * NSIZE]),
+ [wd1]"r"(&dptr[z][d + 1 * NSIZE]),
+ [wd2]"r"(&dptr[z][d + 2 * NSIZE]),
+ [wd3]"r"(&dptr[z][d + 3 * NSIZE]),
+ [x1d]"r"(0x1d)
+ );
+ }
+
+ /*
+ * *(unative_t *)&p[d+NSIZE*$$] = wp$$;
+ * *(unative_t *)&q[d+NSIZE*$$] = wq$$;
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vse8.v v0, (%[wp0])\n"
+ "vse8.v v1, (%[wq0])\n"
+ "vse8.v v4, (%[wp1])\n"
+ "vse8.v v5, (%[wq1])\n"
+ "vse8.v v8, (%[wp2])\n"
+ "vse8.v v9, (%[wq2])\n"
+ "vse8.v v12, (%[wp3])\n"
+ "vse8.v v13, (%[wq3])\n"
+ ".option pop\n"
+ : :
+ [wp0]"r"(&p[d + NSIZE * 0]),
+ [wq0]"r"(&q[d + NSIZE * 0]),
+ [wp1]"r"(&p[d + NSIZE * 1]),
+ [wq1]"r"(&q[d + NSIZE * 1]),
+ [wp2]"r"(&p[d + NSIZE * 2]),
+ [wq2]"r"(&q[d + NSIZE * 2]),
+ [wp3]"r"(&p[d + NSIZE * 3]),
+ [wq3]"r"(&q[d + NSIZE * 3])
+ );
+ }
+}
+
+static void raid6_rvv4_xor_syndrome_real(int disks, int start, int stop,
+ unsigned long bytes, void **ptrs)
+{
+ u8 **dptr = (u8 **)ptrs;
+ u8 *p, *q;
+ unsigned long vl, d;
+ int z, z0;
+
+ z0 = stop; /* P/Q right side optimization */
+ p = dptr[disks - 2]; /* XOR parity */
+ q = dptr[disks - 1]; /* RS syndrome */
+
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsetvli %0, x0, e8, m1, ta, ma\n"
+ ".option pop\n"
+ : "=&r" (vl)
+ );
+
+ /*
+ * v0:wp0, v1:wq0, v2:wd0/w20, v3:w10
+ * v4:wp1, v5:wq1, v6:wd1/w21, v7:w11
+ * v8:wp2, v9:wq2, v10:wd2/w22, v11:w12
+ * v12:wp3, v13:wq3, v14:wd3/w23, v15:w13
+ */
+ for (d = 0; d < bytes; d += NSIZE * 4) {
+ /* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vle8.v v0, (%[wp0])\n"
+ "vle8.v v1, (%[wp0])\n"
+ "vle8.v v4, (%[wp1])\n"
+ "vle8.v v5, (%[wp1])\n"
+ "vle8.v v8, (%[wp2])\n"
+ "vle8.v v9, (%[wp2])\n"
+ "vle8.v v12, (%[wp3])\n"
+ "vle8.v v13, (%[wp3])\n"
+ ".option pop\n"
+ : :
+ [wp0]"r"(&dptr[z0][d + 0 * NSIZE]),
+ [wp1]"r"(&dptr[z0][d + 1 * NSIZE]),
+ [wp2]"r"(&dptr[z0][d + 2 * NSIZE]),
+ [wp3]"r"(&dptr[z0][d + 3 * NSIZE])
+ );
+
+ /* P/Q data pages */
+ for (z = z0 - 1; z >= start; z--) {
+ /*
+ * w2$$ = MASK(wq$$);
+ * w1$$ = SHLBYTE(wq$$);
+ * w2$$ &= NBYTES(0x1d);
+ * w1$$ ^= w2$$;
+ * wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE];
+ * wq$$ = w1$$ ^ wd$$;
+ * wp$$ ^= wd$$;
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsra.vi v2, v1, 7\n"
+ "vsll.vi v3, v1, 1\n"
+ "vand.vx v2, v2, %[x1d]\n"
+ "vxor.vv v3, v3, v2\n"
+ "vle8.v v2, (%[wd0])\n"
+ "vxor.vv v1, v3, v2\n"
+ "vxor.vv v0, v0, v2\n"
+
+ "vsra.vi v6, v5, 7\n"
+ "vsll.vi v7, v5, 1\n"
+ "vand.vx v6, v6, %[x1d]\n"
+ "vxor.vv v7, v7, v6\n"
+ "vle8.v v6, (%[wd1])\n"
+ "vxor.vv v5, v7, v6\n"
+ "vxor.vv v4, v4, v6\n"
+
+ "vsra.vi v10, v9, 7\n"
+ "vsll.vi v11, v9, 1\n"
+ "vand.vx v10, v10, %[x1d]\n"
+ "vxor.vv v11, v11, v10\n"
+ "vle8.v v10, (%[wd2])\n"
+ "vxor.vv v9, v11, v10\n"
+ "vxor.vv v8, v8, v10\n"
+
+ "vsra.vi v14, v13, 7\n"
+ "vsll.vi v15, v13, 1\n"
+ "vand.vx v14, v14, %[x1d]\n"
+ "vxor.vv v15, v15, v14\n"
+ "vle8.v v14, (%[wd3])\n"
+ "vxor.vv v13, v15, v14\n"
+ "vxor.vv v12, v12, v14\n"
+ ".option pop\n"
+ : :
+ [wd0]"r"(&dptr[z][d + 0 * NSIZE]),
+ [wd1]"r"(&dptr[z][d + 1 * NSIZE]),
+ [wd2]"r"(&dptr[z][d + 2 * NSIZE]),
+ [wd3]"r"(&dptr[z][d + 3 * NSIZE]),
+ [x1d]"r"(0x1d)
+ );
+ }
+
+ /* P/Q left side optimization */
+ for (z = start - 1; z >= 0; z--) {
+ /*
+ * w2$$ = MASK(wq$$);
+ * w1$$ = SHLBYTE(wq$$);
+ * w2$$ &= NBYTES(0x1d);
+ * wq$$ = w1$$ ^ w2$$;
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsra.vi v2, v1, 7\n"
+ "vsll.vi v3, v1, 1\n"
+ "vand.vx v2, v2, %[x1d]\n"
+ "vxor.vv v1, v3, v2\n"
+
+ "vsra.vi v6, v5, 7\n"
+ "vsll.vi v7, v5, 1\n"
+ "vand.vx v6, v6, %[x1d]\n"
+ "vxor.vv v5, v7, v6\n"
+
+ "vsra.vi v10, v9, 7\n"
+ "vsll.vi v11, v9, 1\n"
+ "vand.vx v10, v10, %[x1d]\n"
+ "vxor.vv v9, v11, v10\n"
+
+ "vsra.vi v14, v13, 7\n"
+ "vsll.vi v15, v13, 1\n"
+ "vand.vx v14, v14, %[x1d]\n"
+ "vxor.vv v13, v15, v14\n"
+ ".option pop\n"
+ : :
+ [x1d]"r"(0x1d)
+ );
+ }
+
+ /*
+ * *(unative_t *)&p[d+NSIZE*$$] ^= wp$$;
+ * *(unative_t *)&q[d+NSIZE*$$] ^= wq$$;
+ * v0:wp0, v1:wq0, v2:p0, v3:q0
+ * v4:wp1, v5:wq1, v6:p1, v7:q1
+ * v8:wp2, v9:wq2, v10:p2, v11:q2
+ * v12:wp3, v13:wq3, v14:p3, v15:q3
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vle8.v v2, (%[wp0])\n"
+ "vle8.v v3, (%[wq0])\n"
+ "vxor.vv v2, v2, v0\n"
+ "vxor.vv v3, v3, v1\n"
+ "vse8.v v2, (%[wp0])\n"
+ "vse8.v v3, (%[wq0])\n"
+
+ "vle8.v v6, (%[wp1])\n"
+ "vle8.v v7, (%[wq1])\n"
+ "vxor.vv v6, v6, v4\n"
+ "vxor.vv v7, v7, v5\n"
+ "vse8.v v6, (%[wp1])\n"
+ "vse8.v v7, (%[wq1])\n"
+
+ "vle8.v v10, (%[wp2])\n"
+ "vle8.v v11, (%[wq2])\n"
+ "vxor.vv v10, v10, v8\n"
+ "vxor.vv v11, v11, v9\n"
+ "vse8.v v10, (%[wp2])\n"
+ "vse8.v v11, (%[wq2])\n"
+
+ "vle8.v v14, (%[wp3])\n"
+ "vle8.v v15, (%[wq3])\n"
+ "vxor.vv v14, v14, v12\n"
+ "vxor.vv v15, v15, v13\n"
+ "vse8.v v14, (%[wp3])\n"
+ "vse8.v v15, (%[wq3])\n"
+ ".option pop\n"
+ : :
+ [wp0]"r"(&p[d + NSIZE * 0]),
+ [wq0]"r"(&q[d + NSIZE * 0]),
+ [wp1]"r"(&p[d + NSIZE * 1]),
+ [wq1]"r"(&q[d + NSIZE * 1]),
+ [wp2]"r"(&p[d + NSIZE * 2]),
+ [wq2]"r"(&q[d + NSIZE * 2]),
+ [wp3]"r"(&p[d + NSIZE * 3]),
+ [wq3]"r"(&q[d + NSIZE * 3])
+ );
+ }
+}
+
+static void raid6_rvv8_gen_syndrome_real(int disks, unsigned long bytes, void **ptrs)
+{
+ u8 **dptr = (u8 **)ptrs;
+ u8 *p, *q;
+ unsigned long vl, d;
+ int z, z0;
+
+ z0 = disks - 3; /* Highest data disk */
+ p = dptr[z0 + 1]; /* XOR parity */
+ q = dptr[z0 + 2]; /* RS syndrome */
+
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsetvli %0, x0, e8, m1, ta, ma\n"
+ ".option pop\n"
+ : "=&r" (vl)
+ );
+
+ /*
+ * v0:wp0, v1:wq0, v2:wd0/w20, v3:w10
+ * v4:wp1, v5:wq1, v6:wd1/w21, v7:w11
+ * v8:wp2, v9:wq2, v10:wd2/w22, v11:w12
+ * v12:wp3, v13:wq3, v14:wd3/w23, v15:w13
+ * v16:wp4, v17:wq4, v18:wd4/w24, v19:w14
+ * v20:wp5, v21:wq5, v22:wd5/w25, v23:w15
+ * v24:wp6, v25:wq6, v26:wd6/w26, v27:w16
+ * v28:wp7, v29:wq7, v30:wd7/w27, v31:w17
+ */
+ for (d = 0; d < bytes; d += NSIZE * 8) {
+ /* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vle8.v v0, (%[wp0])\n"
+ "vle8.v v1, (%[wp0])\n"
+ "vle8.v v4, (%[wp1])\n"
+ "vle8.v v5, (%[wp1])\n"
+ "vle8.v v8, (%[wp2])\n"
+ "vle8.v v9, (%[wp2])\n"
+ "vle8.v v12, (%[wp3])\n"
+ "vle8.v v13, (%[wp3])\n"
+ "vle8.v v16, (%[wp4])\n"
+ "vle8.v v17, (%[wp4])\n"
+ "vle8.v v20, (%[wp5])\n"
+ "vle8.v v21, (%[wp5])\n"
+ "vle8.v v24, (%[wp6])\n"
+ "vle8.v v25, (%[wp6])\n"
+ "vle8.v v28, (%[wp7])\n"
+ "vle8.v v29, (%[wp7])\n"
+ ".option pop\n"
+ : :
+ [wp0]"r"(&dptr[z0][d + 0 * NSIZE]),
+ [wp1]"r"(&dptr[z0][d + 1 * NSIZE]),
+ [wp2]"r"(&dptr[z0][d + 2 * NSIZE]),
+ [wp3]"r"(&dptr[z0][d + 3 * NSIZE]),
+ [wp4]"r"(&dptr[z0][d + 4 * NSIZE]),
+ [wp5]"r"(&dptr[z0][d + 5 * NSIZE]),
+ [wp6]"r"(&dptr[z0][d + 6 * NSIZE]),
+ [wp7]"r"(&dptr[z0][d + 7 * NSIZE])
+ );
+
+ for (z = z0 - 1; z >= 0; z--) {
+ /*
+ * w2$$ = MASK(wq$$);
+ * w1$$ = SHLBYTE(wq$$);
+ * w2$$ &= NBYTES(0x1d);
+ * w1$$ ^= w2$$;
+ * wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE];
+ * wq$$ = w1$$ ^ wd$$;
+ * wp$$ ^= wd$$;
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsra.vi v2, v1, 7\n"
+ "vsll.vi v3, v1, 1\n"
+ "vand.vx v2, v2, %[x1d]\n"
+ "vxor.vv v3, v3, v2\n"
+ "vle8.v v2, (%[wd0])\n"
+ "vxor.vv v1, v3, v2\n"
+ "vxor.vv v0, v0, v2\n"
+
+ "vsra.vi v6, v5, 7\n"
+ "vsll.vi v7, v5, 1\n"
+ "vand.vx v6, v6, %[x1d]\n"
+ "vxor.vv v7, v7, v6\n"
+ "vle8.v v6, (%[wd1])\n"
+ "vxor.vv v5, v7, v6\n"
+ "vxor.vv v4, v4, v6\n"
+
+ "vsra.vi v10, v9, 7\n"
+ "vsll.vi v11, v9, 1\n"
+ "vand.vx v10, v10, %[x1d]\n"
+ "vxor.vv v11, v11, v10\n"
+ "vle8.v v10, (%[wd2])\n"
+ "vxor.vv v9, v11, v10\n"
+ "vxor.vv v8, v8, v10\n"
+
+ "vsra.vi v14, v13, 7\n"
+ "vsll.vi v15, v13, 1\n"
+ "vand.vx v14, v14, %[x1d]\n"
+ "vxor.vv v15, v15, v14\n"
+ "vle8.v v14, (%[wd3])\n"
+ "vxor.vv v13, v15, v14\n"
+ "vxor.vv v12, v12, v14\n"
+
+ "vsra.vi v18, v17, 7\n"
+ "vsll.vi v19, v17, 1\n"
+ "vand.vx v18, v18, %[x1d]\n"
+ "vxor.vv v19, v19, v18\n"
+ "vle8.v v18, (%[wd4])\n"
+ "vxor.vv v17, v19, v18\n"
+ "vxor.vv v16, v16, v18\n"
+
+ "vsra.vi v22, v21, 7\n"
+ "vsll.vi v23, v21, 1\n"
+ "vand.vx v22, v22, %[x1d]\n"
+ "vxor.vv v23, v23, v22\n"
+ "vle8.v v22, (%[wd5])\n"
+ "vxor.vv v21, v23, v22\n"
+ "vxor.vv v20, v20, v22\n"
+
+ "vsra.vi v26, v25, 7\n"
+ "vsll.vi v27, v25, 1\n"
+ "vand.vx v26, v26, %[x1d]\n"
+ "vxor.vv v27, v27, v26\n"
+ "vle8.v v26, (%[wd6])\n"
+ "vxor.vv v25, v27, v26\n"
+ "vxor.vv v24, v24, v26\n"
+
+ "vsra.vi v30, v29, 7\n"
+ "vsll.vi v31, v29, 1\n"
+ "vand.vx v30, v30, %[x1d]\n"
+ "vxor.vv v31, v31, v30\n"
+ "vle8.v v30, (%[wd7])\n"
+ "vxor.vv v29, v31, v30\n"
+ "vxor.vv v28, v28, v30\n"
+ ".option pop\n"
+ : :
+ [wd0]"r"(&dptr[z][d + 0 * NSIZE]),
+ [wd1]"r"(&dptr[z][d + 1 * NSIZE]),
+ [wd2]"r"(&dptr[z][d + 2 * NSIZE]),
+ [wd3]"r"(&dptr[z][d + 3 * NSIZE]),
+ [wd4]"r"(&dptr[z][d + 4 * NSIZE]),
+ [wd5]"r"(&dptr[z][d + 5 * NSIZE]),
+ [wd6]"r"(&dptr[z][d + 6 * NSIZE]),
+ [wd7]"r"(&dptr[z][d + 7 * NSIZE]),
+ [x1d]"r"(0x1d)
+ );
+ }
+
+ /*
+ * *(unative_t *)&p[d+NSIZE*$$] = wp$$;
+ * *(unative_t *)&q[d+NSIZE*$$] = wq$$;
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vse8.v v0, (%[wp0])\n"
+ "vse8.v v1, (%[wq0])\n"
+ "vse8.v v4, (%[wp1])\n"
+ "vse8.v v5, (%[wq1])\n"
+ "vse8.v v8, (%[wp2])\n"
+ "vse8.v v9, (%[wq2])\n"
+ "vse8.v v12, (%[wp3])\n"
+ "vse8.v v13, (%[wq3])\n"
+ "vse8.v v16, (%[wp4])\n"
+ "vse8.v v17, (%[wq4])\n"
+ "vse8.v v20, (%[wp5])\n"
+ "vse8.v v21, (%[wq5])\n"
+ "vse8.v v24, (%[wp6])\n"
+ "vse8.v v25, (%[wq6])\n"
+ "vse8.v v28, (%[wp7])\n"
+ "vse8.v v29, (%[wq7])\n"
+ ".option pop\n"
+ : :
+ [wp0]"r"(&p[d + NSIZE * 0]),
+ [wq0]"r"(&q[d + NSIZE * 0]),
+ [wp1]"r"(&p[d + NSIZE * 1]),
+ [wq1]"r"(&q[d + NSIZE * 1]),
+ [wp2]"r"(&p[d + NSIZE * 2]),
+ [wq2]"r"(&q[d + NSIZE * 2]),
+ [wp3]"r"(&p[d + NSIZE * 3]),
+ [wq3]"r"(&q[d + NSIZE * 3]),
+ [wp4]"r"(&p[d + NSIZE * 4]),
+ [wq4]"r"(&q[d + NSIZE * 4]),
+ [wp5]"r"(&p[d + NSIZE * 5]),
+ [wq5]"r"(&q[d + NSIZE * 5]),
+ [wp6]"r"(&p[d + NSIZE * 6]),
+ [wq6]"r"(&q[d + NSIZE * 6]),
+ [wp7]"r"(&p[d + NSIZE * 7]),
+ [wq7]"r"(&q[d + NSIZE * 7])
+ );
+ }
+}
+
+static void raid6_rvv8_xor_syndrome_real(int disks, int start, int stop,
+ unsigned long bytes, void **ptrs)
+{
+ u8 **dptr = (u8 **)ptrs;
+ u8 *p, *q;
+ unsigned long vl, d;
+ int z, z0;
+
+ z0 = stop; /* P/Q right side optimization */
+ p = dptr[disks - 2]; /* XOR parity */
+ q = dptr[disks - 1]; /* RS syndrome */
+
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsetvli %0, x0, e8, m1, ta, ma\n"
+ ".option pop\n"
+ : "=&r" (vl)
+ );
+
+ /*
+ * v0:wp0, v1:wq0, v2:wd0/w20, v3:w10
+ * v4:wp1, v5:wq1, v6:wd1/w21, v7:w11
+ * v8:wp2, v9:wq2, v10:wd2/w22, v11:w12
+ * v12:wp3, v13:wq3, v14:wd3/w23, v15:w13
+ * v16:wp4, v17:wq4, v18:wd4/w24, v19:w14
+ * v20:wp5, v21:wq5, v22:wd5/w25, v23:w15
+ * v24:wp6, v25:wq6, v26:wd6/w26, v27:w16
+ * v28:wp7, v29:wq7, v30:wd7/w27, v31:w17
+ */
+ for (d = 0; d < bytes; d += NSIZE * 8) {
+ /* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vle8.v v0, (%[wp0])\n"
+ "vle8.v v1, (%[wp0])\n"
+ "vle8.v v4, (%[wp1])\n"
+ "vle8.v v5, (%[wp1])\n"
+ "vle8.v v8, (%[wp2])\n"
+ "vle8.v v9, (%[wp2])\n"
+ "vle8.v v12, (%[wp3])\n"
+ "vle8.v v13, (%[wp3])\n"
+ "vle8.v v16, (%[wp4])\n"
+ "vle8.v v17, (%[wp4])\n"
+ "vle8.v v20, (%[wp5])\n"
+ "vle8.v v21, (%[wp5])\n"
+ "vle8.v v24, (%[wp6])\n"
+ "vle8.v v25, (%[wp6])\n"
+ "vle8.v v28, (%[wp7])\n"
+ "vle8.v v29, (%[wp7])\n"
+ ".option pop\n"
+ : :
+ [wp0]"r"(&dptr[z0][d + 0 * NSIZE]),
+ [wp1]"r"(&dptr[z0][d + 1 * NSIZE]),
+ [wp2]"r"(&dptr[z0][d + 2 * NSIZE]),
+ [wp3]"r"(&dptr[z0][d + 3 * NSIZE]),
+ [wp4]"r"(&dptr[z0][d + 4 * NSIZE]),
+ [wp5]"r"(&dptr[z0][d + 5 * NSIZE]),
+ [wp6]"r"(&dptr[z0][d + 6 * NSIZE]),
+ [wp7]"r"(&dptr[z0][d + 7 * NSIZE])
+ );
+
+ /* P/Q data pages */
+ for (z = z0 - 1; z >= start; z--) {
+ /*
+ * w2$$ = MASK(wq$$);
+ * w1$$ = SHLBYTE(wq$$);
+ * w2$$ &= NBYTES(0x1d);
+ * w1$$ ^= w2$$;
+ * wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE];
+ * wq$$ = w1$$ ^ wd$$;
+ * wp$$ ^= wd$$;
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsra.vi v2, v1, 7\n"
+ "vsll.vi v3, v1, 1\n"
+ "vand.vx v2, v2, %[x1d]\n"
+ "vxor.vv v3, v3, v2\n"
+ "vle8.v v2, (%[wd0])\n"
+ "vxor.vv v1, v3, v2\n"
+ "vxor.vv v0, v0, v2\n"
+
+ "vsra.vi v6, v5, 7\n"
+ "vsll.vi v7, v5, 1\n"
+ "vand.vx v6, v6, %[x1d]\n"
+ "vxor.vv v7, v7, v6\n"
+ "vle8.v v6, (%[wd1])\n"
+ "vxor.vv v5, v7, v6\n"
+ "vxor.vv v4, v4, v6\n"
+
+ "vsra.vi v10, v9, 7\n"
+ "vsll.vi v11, v9, 1\n"
+ "vand.vx v10, v10, %[x1d]\n"
+ "vxor.vv v11, v11, v10\n"
+ "vle8.v v10, (%[wd2])\n"
+ "vxor.vv v9, v11, v10\n"
+ "vxor.vv v8, v8, v10\n"
+
+ "vsra.vi v14, v13, 7\n"
+ "vsll.vi v15, v13, 1\n"
+ "vand.vx v14, v14, %[x1d]\n"
+ "vxor.vv v15, v15, v14\n"
+ "vle8.v v14, (%[wd3])\n"
+ "vxor.vv v13, v15, v14\n"
+ "vxor.vv v12, v12, v14\n"
+
+ "vsra.vi v18, v17, 7\n"
+ "vsll.vi v19, v17, 1\n"
+ "vand.vx v18, v18, %[x1d]\n"
+ "vxor.vv v19, v19, v18\n"
+ "vle8.v v18, (%[wd4])\n"
+ "vxor.vv v17, v19, v18\n"
+ "vxor.vv v16, v16, v18\n"
+
+ "vsra.vi v22, v21, 7\n"
+ "vsll.vi v23, v21, 1\n"
+ "vand.vx v22, v22, %[x1d]\n"
+ "vxor.vv v23, v23, v22\n"
+ "vle8.v v22, (%[wd5])\n"
+ "vxor.vv v21, v23, v22\n"
+ "vxor.vv v20, v20, v22\n"
+
+ "vsra.vi v26, v25, 7\n"
+ "vsll.vi v27, v25, 1\n"
+ "vand.vx v26, v26, %[x1d]\n"
+ "vxor.vv v27, v27, v26\n"
+ "vle8.v v26, (%[wd6])\n"
+ "vxor.vv v25, v27, v26\n"
+ "vxor.vv v24, v24, v26\n"
+
+ "vsra.vi v30, v29, 7\n"
+ "vsll.vi v31, v29, 1\n"
+ "vand.vx v30, v30, %[x1d]\n"
+ "vxor.vv v31, v31, v30\n"
+ "vle8.v v30, (%[wd7])\n"
+ "vxor.vv v29, v31, v30\n"
+ "vxor.vv v28, v28, v30\n"
+ ".option pop\n"
+ : :
+ [wd0]"r"(&dptr[z][d + 0 * NSIZE]),
+ [wd1]"r"(&dptr[z][d + 1 * NSIZE]),
+ [wd2]"r"(&dptr[z][d + 2 * NSIZE]),
+ [wd3]"r"(&dptr[z][d + 3 * NSIZE]),
+ [wd4]"r"(&dptr[z][d + 4 * NSIZE]),
+ [wd5]"r"(&dptr[z][d + 5 * NSIZE]),
+ [wd6]"r"(&dptr[z][d + 6 * NSIZE]),
+ [wd7]"r"(&dptr[z][d + 7 * NSIZE]),
+ [x1d]"r"(0x1d)
+ );
+ }
+
+ /* P/Q left side optimization */
+ for (z = start - 1; z >= 0; z--) {
+ /*
+ * w2$$ = MASK(wq$$);
+ * w1$$ = SHLBYTE(wq$$);
+ * w2$$ &= NBYTES(0x1d);
+ * wq$$ = w1$$ ^ w2$$;
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vsra.vi v2, v1, 7\n"
+ "vsll.vi v3, v1, 1\n"
+ "vand.vx v2, v2, %[x1d]\n"
+ "vxor.vv v1, v3, v2\n"
+
+ "vsra.vi v6, v5, 7\n"
+ "vsll.vi v7, v5, 1\n"
+ "vand.vx v6, v6, %[x1d]\n"
+ "vxor.vv v5, v7, v6\n"
+
+ "vsra.vi v10, v9, 7\n"
+ "vsll.vi v11, v9, 1\n"
+ "vand.vx v10, v10, %[x1d]\n"
+ "vxor.vv v9, v11, v10\n"
+
+ "vsra.vi v14, v13, 7\n"
+ "vsll.vi v15, v13, 1\n"
+ "vand.vx v14, v14, %[x1d]\n"
+ "vxor.vv v13, v15, v14\n"
+
+ "vsra.vi v18, v17, 7\n"
+ "vsll.vi v19, v17, 1\n"
+ "vand.vx v18, v18, %[x1d]\n"
+ "vxor.vv v17, v19, v18\n"
+
+ "vsra.vi v22, v21, 7\n"
+ "vsll.vi v23, v21, 1\n"
+ "vand.vx v22, v22, %[x1d]\n"
+ "vxor.vv v21, v23, v22\n"
+
+ "vsra.vi v26, v25, 7\n"
+ "vsll.vi v27, v25, 1\n"
+ "vand.vx v26, v26, %[x1d]\n"
+ "vxor.vv v25, v27, v26\n"
+
+ "vsra.vi v30, v29, 7\n"
+ "vsll.vi v31, v29, 1\n"
+ "vand.vx v30, v30, %[x1d]\n"
+ "vxor.vv v29, v31, v30\n"
+ ".option pop\n"
+ : :
+ [x1d]"r"(0x1d)
+ );
+ }
+
+ /*
+ * *(unative_t *)&p[d+NSIZE*$$] ^= wp$$;
+ * *(unative_t *)&q[d+NSIZE*$$] ^= wq$$;
+ * v0:wp0, v1:wq0, v2:p0, v3:q0
+ * v4:wp1, v5:wq1, v6:p1, v7:q1
+ * v8:wp2, v9:wq2, v10:p2, v11:q2
+ * v12:wp3, v13:wq3, v14:p3, v15:q3
+ * v16:wp4, v17:wq4, v18:p4, v19:q4
+ * v20:wp5, v21:wq5, v22:p5, v23:q5
+ * v24:wp6, v25:wq6, v26:p6, v27:q6
+ * v28:wp7, v29:wq7, v30:p7, v31:q7
+ */
+ asm volatile (".option push\n"
+ ".option arch,+v\n"
+ "vle8.v v2, (%[wp0])\n"
+ "vle8.v v3, (%[wq0])\n"
+ "vxor.vv v2, v2, v0\n"
+ "vxor.vv v3, v3, v1\n"
+ "vse8.v v2, (%[wp0])\n"
+ "vse8.v v3, (%[wq0])\n"
+
+ "vle8.v v6, (%[wp1])\n"
+ "vle8.v v7, (%[wq1])\n"
+ "vxor.vv v6, v6, v4\n"
+ "vxor.vv v7, v7, v5\n"
+ "vse8.v v6, (%[wp1])\n"
+ "vse8.v v7, (%[wq1])\n"
+
+ "vle8.v v10, (%[wp2])\n"
+ "vle8.v v11, (%[wq2])\n"
+ "vxor.vv v10, v10, v8\n"
+ "vxor.vv v11, v11, v9\n"
+ "vse8.v v10, (%[wp2])\n"
+ "vse8.v v11, (%[wq2])\n"
+
+ "vle8.v v14, (%[wp3])\n"
+ "vle8.v v15, (%[wq3])\n"
+ "vxor.vv v14, v14, v12\n"
+ "vxor.vv v15, v15, v13\n"
+ "vse8.v v14, (%[wp3])\n"
+ "vse8.v v15, (%[wq3])\n"
+
+ "vle8.v v18, (%[wp4])\n"
+ "vle8.v v19, (%[wq4])\n"
+ "vxor.vv v18, v18, v16\n"
+ "vxor.vv v19, v19, v17\n"
+ "vse8.v v18, (%[wp4])\n"
+ "vse8.v v19, (%[wq4])\n"
+
+ "vle8.v v22, (%[wp5])\n"
+ "vle8.v v23, (%[wq5])\n"
+ "vxor.vv v22, v22, v20\n"
+ "vxor.vv v23, v23, v21\n"
+ "vse8.v v22, (%[wp5])\n"
+ "vse8.v v23, (%[wq5])\n"
+
+ "vle8.v v26, (%[wp6])\n"
+ "vle8.v v27, (%[wq6])\n"
+ "vxor.vv v26, v26, v24\n"
+ "vxor.vv v27, v27, v25\n"
+ "vse8.v v26, (%[wp6])\n"
+ "vse8.v v27, (%[wq6])\n"
+
+ "vle8.v v30, (%[wp7])\n"
+ "vle8.v v31, (%[wq7])\n"
+ "vxor.vv v30, v30, v28\n"
+ "vxor.vv v31, v31, v29\n"
+ "vse8.v v30, (%[wp7])\n"
+ "vse8.v v31, (%[wq7])\n"
+ ".option pop\n"
+ : :
+ [wp0]"r"(&p[d + NSIZE * 0]),
+ [wq0]"r"(&q[d + NSIZE * 0]),
+ [wp1]"r"(&p[d + NSIZE * 1]),
+ [wq1]"r"(&q[d + NSIZE * 1]),
+ [wp2]"r"(&p[d + NSIZE * 2]),
+ [wq2]"r"(&q[d + NSIZE * 2]),
+ [wp3]"r"(&p[d + NSIZE * 3]),
+ [wq3]"r"(&q[d + NSIZE * 3]),
+ [wp4]"r"(&p[d + NSIZE * 4]),
+ [wq4]"r"(&q[d + NSIZE * 4]),
+ [wp5]"r"(&p[d + NSIZE * 5]),
+ [wq5]"r"(&q[d + NSIZE * 5]),
+ [wp6]"r"(&p[d + NSIZE * 6]),
+ [wq6]"r"(&q[d + NSIZE * 6]),
+ [wp7]"r"(&p[d + NSIZE * 7]),
+ [wq7]"r"(&q[d + NSIZE * 7])
+ );
+ }
+}
+
+RAID6_RVV_WRAPPER(1);
+RAID6_RVV_WRAPPER(2);
+RAID6_RVV_WRAPPER(4);
+RAID6_RVV_WRAPPER(8);
diff --git a/lib/raid6/rvv.h b/lib/raid6/rvv.h
new file mode 100644
index 000000000000..94044a1b707b
--- /dev/null
+++ b/lib/raid6/rvv.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright 2024 Institute of Software, CAS.
+ *
+ * raid6/rvv.h
+ *
+ * Definitions for RISC-V RAID-6 code
+ */
+
+#define RAID6_RVV_WRAPPER(_n) \
+ static void raid6_rvv ## _n ## _gen_syndrome(int disks, \
+ size_t bytes, void **ptrs) \
+ { \
+ void raid6_rvv ## _n ## _gen_syndrome_real(int d, \
+ unsigned long b, void **p); \
+ kernel_vector_begin(); \
+ raid6_rvv ## _n ## _gen_syndrome_real(disks, \
+ (unsigned long)bytes, ptrs); \
+ kernel_vector_end(); \
+ } \
+ static void raid6_rvv ## _n ## _xor_syndrome(int disks, \
+ int start, int stop, \
+ size_t bytes, void **ptrs) \
+ { \
+ void raid6_rvv ## _n ## _xor_syndrome_real(int d, \
+ int s1, int s2, \
+ unsigned long b, void **p); \
+ kernel_vector_begin(); \
+ raid6_rvv ## _n ## _xor_syndrome_real(disks, \
+ start, stop, (unsigned long)bytes, ptrs); \
+ kernel_vector_end(); \
+ } \
+ struct raid6_calls const raid6_rvvx ## _n = { \
+ raid6_rvv ## _n ## _gen_syndrome, \
+ raid6_rvv ## _n ## _xor_syndrome, \
+ rvv_has_vector, \
+ "rvvx" #_n, \
+ 0 \
+ }
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index 7582dfab7fe3..4af1c8b0775a 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -73,9 +73,9 @@ EXPORT_SYMBOL(sg_nents_for_len);
* Should only be used casually, it (currently) scans the entire list
* to get the last entry.
*
- * Note that the @sgl@ pointer passed in need not be the first one,
- * the important bit is that @nents@ denotes the number of entries that
- * exist from @sgl@.
+ * Note that the @sgl pointer passed in need not be the first one,
+ * the important bit is that @nents denotes the number of entries that
+ * exist from @sgl.
*
**/
struct scatterlist *sg_last(struct scatterlist *sgl, unsigned int nents)
@@ -345,7 +345,7 @@ EXPORT_SYMBOL(__sg_alloc_table);
* @gfp_mask: GFP allocation mask
*
* Description:
- * Allocate and initialize an sg table. If @nents@ is larger than
+ * Allocate and initialize an sg table. If @nents is larger than
* SG_MAX_SINGLE_ALLOC a chained sg table will be setup.
*
**/
diff --git a/lib/test_objagg.c b/lib/test_objagg.c
index d34df4306b87..222b39fc2629 100644
--- a/lib/test_objagg.c
+++ b/lib/test_objagg.c
@@ -899,8 +899,10 @@ static int check_expect_hints_stats(struct objagg_hints *objagg_hints,
int err;
stats = objagg_hints_stats_get(objagg_hints);
- if (IS_ERR(stats))
+ if (IS_ERR(stats)) {
+ *errmsg = "objagg_hints_stats_get() failed.";
return PTR_ERR(stats);
+ }
err = __check_expect_stats(stats, expect_stats, errmsg);
objagg_stats_put(stats);
return err;