Hey @Aquaticfuller @DiyouS,
found when running some custom kernels. AI:
AraVlsu::isa_init() binds its handlers by instruction tag:
get_insns_from_tag("vload") -> handle_insn_load // unit-stride
get_insns_from_tag("vstore") -> handle_insn_store // unit-stride
get_insns_from_tag("vload_strided") -> handle_insn_load_strided
get_insns_from_tag("vstore_strided") -> handle_insn_store_strided
get_insns_from_tag("vload_indexed") -> handle_insn_load_indexed
get_insns_from_tag("vstore_indexed") -> handle_insn_store_indexed
In the ISA description every vector memory instruction carried tags=['vload']
or tags=['vstore'] — the strided vlse*.v/vsse*.v and the indexed
vluxei*/vloxei*/vsuxei*/vsoxei* included. No instruction carried the
strided or indexed tags, so those four handlers were dead code and every
strided/indexed access was executed by the unit-stride handler: the stride
register (or index vector) is ignored and addresses advance by element size.
Ara::isa_init() maps instructions to processing blocks by the same mechanism
(vload/vstore → VLSU, vothers → VFPU, vslide → vslide unit); vector
arithmetic carried no vothers tag either, so it was not dispatched to a
compute block.
Effect
vsse32.v v8, (dst), stride=16 writes 16 consecutive words instead of every
fourth word — it silently overwrites the records it was supposed to skip. In our
case this corrupted a linked list of DMA descriptors and the resulting pointer
loop hung the workload; in general any RVV code using vlse/vsse or indexed
accesses reads and writes the wrong addresses with no diagnostic.
Reproduction
uint32_t src[8], dst[32]; // dst pre-filled with a sentinel
asm volatile("vsetvli t0, %[n], e32, m1, ta, ma\n"
"vle32.v v8, (%[s])\n"
"vsse32.v v8, (%[d]), %[stride]\n"
:: [n]"r"(8), [s]"r"(src), [d]"r"(dst), [stride]"r"(16) : "memory");
Before the patch dst[1..3], dst[5..7], … are clobbered (the unit-stride
signature). After it, the eight words land at dst[0], dst[4], dst[8], … and
the words between them keep the sentinel.
Fix
Tag the instructions the handlers already expect: 4 strided loads, 4 strided
stores, 8 indexed loads, 8 indexed stores, and the arithmetic instructions as
vothers.
Hey @Aquaticfuller @DiyouS,
found when running some custom kernels. AI:
AraVlsu::isa_init()binds its handlers by instruction tag:In the ISA description every vector memory instruction carried
tags=['vload']or
tags=['vstore']— the stridedvlse*.v/vsse*.vand the indexedvluxei*/vloxei*/vsuxei*/vsoxei*included. No instruction carried thestrided or indexed tags, so those four handlers were dead code and every
strided/indexed access was executed by the unit-stride handler: the stride
register (or index vector) is ignored and addresses advance by element size.
Ara::isa_init()maps instructions to processing blocks by the same mechanism(
vload/vstore→ VLSU,vothers→ VFPU,vslide→ vslide unit); vectorarithmetic carried no
votherstag either, so it was not dispatched to acompute block.
Effect
vsse32.v v8, (dst), stride=16writes 16 consecutive words instead of everyfourth word — it silently overwrites the records it was supposed to skip. In our
case this corrupted a linked list of DMA descriptors and the resulting pointer
loop hung the workload; in general any RVV code using
vlse/vsseor indexedaccesses reads and writes the wrong addresses with no diagnostic.
Reproduction
Before the patch
dst[1..3],dst[5..7], … are clobbered (the unit-stridesignature). After it, the eight words land at
dst[0], dst[4], dst[8], …andthe words between them keep the sentinel.
Fix
Tag the instructions the handlers already expect: 4 strided loads, 4 strided
stores, 8 indexed loads, 8 indexed stores, and the arithmetic instructions as
vothers.