All of lore.kernel.org
 help / color / mirror / Atom feed
From: Max Chou <max.chou@sifive.com>
To: Palmer Dabbelt <palmer@dabbelt.com>, richard.henderson@linaro.org
Cc: Richard Henderson <richard.henderson@linaro.org>,
	 qemu-devel@nongnu.org, qemu-riscv@nongnu.org,
	 Alistair Francis <Alistair.Francis@wdc.com>,
	daniel.barboza@oss.qualcomm.com, joel@jms.id.au
Subject: Re: [PATCH v2] tcg/riscv64: Set vtype before whole-register vector moves
Date: Sat, 19 Sep 2026 02:10:09 +0800	[thread overview]
Message-ID: <aq184D2BedTg-Jjc@sifive.com> (raw)
In-Reply-To: <mhng-2ECF390B-6BDB-4DF3-8133-18F4AC3A4DD2@Palmers-Mini.rwc.dabbelt.com>

On 2026-09-17 17:21, Palmer Dabbelt wrote:
> On Thu, 17 Sep 2026 14:49:07 PDT (-0700), Richard Henderson wrote:
> > On 9/17/26 10:59, Palmer Dabbelt wrote:
> > > On Thu, 17 Sep 2026 13:51:10 PDT (-0700), Richard Henderson wrote:
> > > > On 9/17/26 03:37, Max Chou wrote:
> > > > > According to the RISC-V unpriviledge spec,
> > > > >    "vset{i}vl{i} and whole register loads and stores do not depend upon
> > > > >     vtype."
> > > > > The whole-register vector move instructions reuqire legal vtype that
> > > > > trap when VILL is set.
> > > > > 
> > > > > The tcg_out_mov in tcg/riscv64 missed the vtype setup before emitting
> > > > > the
> > > > > OPC_VMVNR_V.
> > > > > 
> > > > > Fixes: d4be6ee1111 ("tcg/riscv: Implement vector mov/dup{m/i}")
> > > > > Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> > > > > Reviewed-by: Joel Stanley <joel@jms.id.au>
> > > > > Signed-off-by: Max Chou <max.chou@sifive.com>
> > > > > ---
> > > > >   tcg/riscv64/tcg-target.c.inc | 4 ++++
> > > > >   1 file changed, 4 insertions(+)
> > > > > 
> > > > > diff --git a/tcg/riscv64/tcg-target.c.inc b/tcg/riscv64/tcg-target.c.inc
> > > > > index 2ce9d47a633..e3cfedb579d 100644
> > > > > --- a/tcg/riscv64/tcg-target.c.inc
> > > > > +++ b/tcg/riscv64/tcg-target.c.inc
> > > > > @@ -778,6 +778,10 @@ static bool tcg_out_mov(TCGContext *s, TCGType
> > > > > type, TCGReg ret, TCGReg arg)
> > > > >           {
> > > > >               int lmul = type - riscv_lg2_vlenb;
> > > > >               int nf = 1 << MAX(lmul, 0);
> > > > > +
> > > > > +            if (s->riscv_cur_type == TCG_TYPE_COUNT) {
> > > > > +                set_vtype_len(s, type);
> > > > > +            }
> > > > >               tcg_out_opc_vi(s, OPC_VMVNR_V, ret, arg, nf - 1);
> > > > >           }
> > > > >           break;
> > > > 
> > > > Do you have a reproducer for this?  I ask because I still wonder how
> > > > this can occur.
> > > > 
> > > > Given that
> > > > 
> > > > (1) all vector registers are call-clobbered, there should be none live
> > > > across tcg_out_call_int (which clears the remembered vtype),
> > > > 
> > > > (2) the first vector action with no vector registers live must be a load
> > > > or movi (which will initialize vtype).
> > > > 
> > > > Performing a move between vector registers when all such registers must
> > > > be dead is... wrong.  It indicates that there's a bug elsewhere.
> > > 
> > > I'm not quite sure the commit message is right here, but this whole area
> > > is a bit of a landmine: one of the post-ratification changes to V was
> > > either this (or very close to this), so we've been through it for every
> > > project.
> > > 
> > > Here's the LLVM thread, which I think has links to everything else:
> > > https://github.com/llvm/llvm-project/issues/114518 (there's a GCC change
> > > as well).  IIRC hardware is a bit all over the place on this one, for
> > > the compilers we decided to just emit the code that's safe either way --
> > > that's not really an option for QEMU, though, so we'll have to pick one
> > > side or the other.
> > Yes, I get that.  But my point stands that after a function call (which
> > can set VILL), all vector registers should be dead.  A move of a dead
> > register is itself a bug.
> 
> That's true for standard ABI functions, but there's a variant for vector-ABI
> functions that allows some registers to be saved and that variant doesn't
> preserve vtype.  That's basically how we ended up in the mess with
> whole-register moves: pre-change vector-1.0 versions didn't trap
> whole-vector moves on vtype=VILL, so variant functions could use
> whole-register moves to save/restore registers and it was legal.  It was
> only when Linux started clobbering with VILL on implementations that
> respected the post-change ISA that we ended up with the traps.
> 
> That said, in GCC we just had a proper bug in there where we treated vytpe
> as saved over calls, so it was pretty easy to roll it up into that fix.
> Here's the GCC bug, if you're interested:
> <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117544>.  IIUC it was a little
> different in LLVM because they didn't have that bug and were thus actually
> correct for the pre-change ISA, but they also decided to just emit the code
> that's safe for both cases.
> 
> > There should have been *something* that brought the source vector
> > register back to life: a load or a movi.  Both of which reinitialize vtype.
> > 
> > That's why I'd like to see a reproducer, or if there isn't one,
> > 
> >      tcg_debug_assert(s->riscv_cur_type != TCG_TYPE_COUNT);
> > 
> > I'm currently running the assert through the testsuite to make sure I've
> > not gone loopy.
> 
> Ya, seems reasonable.  It's certainly pretty likely this is masking some
> other bug as it was in GCC.

Hi Palmer and Richard,

Thanks Palmer for providing the toolchain discussion information and
links.

Richard, I have a reproducer for this issue listed below:

—
The reproducer follows this flow:

x86_64 `ls` executable -> qemu_x86-64 -> qemu-system-riscv64

1. Get x86_64 sysroot and `ls` executable from x86_64 host
```
$ podman create --name x86_64_container ubuntu:24.04
$ podman cp x86_64_container:/ {x86_64_sysroot}
```
2. Cross build qemu-x86_64
3. Obtain the riscv64 images (I built it using buildroot with
`qemu_riscv64_virt_defconfig` config).
4. Boot up riscv64 Linux on qemu-system-riscv64 and mount the
{x86_64_sysroot} (and the qemu-x86_64) directory.
5. Execute the x86_64 ls executable on qemu-x86_64 in
qemu-system-riscv64
```
# qemu-x86_64 -cpu max -L {x86_64_sysroot} {x86_64_sysroot}/usr/bin/ls
qemu-x86_64: QEMU internal SIGILL {code=ILLOPC, addr=0x7fff8c076450}
Illegal instruction
```
—

I understand that this reproducer could be simplified by building a
standalone executable without copying from the x86_64 container. I’ll
try to make it simpler.

rnax


  reply	other threads:[~2026-09-18 18:10 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-17 13:37 [PATCH v2] tcg/riscv64: Set vtype before whole-register vector moves Max Chou
2026-09-17 20:51 ` Richard Henderson
2026-09-17 20:59   ` Palmer Dabbelt
2026-09-17 21:49     ` Richard Henderson
2026-09-18  0:21       ` Palmer Dabbelt
2026-09-18 18:10         ` Max Chou [this message]
2026-09-18 19:15           ` Richard Henderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aq184D2BedTg-Jjc@sifive.com \
    --to=max.chou@sifive.com \
    --cc=Alistair.Francis@wdc.com \
    --cc=daniel.barboza@oss.qualcomm.com \
    --cc=joel@jms.id.au \
    --cc=palmer@dabbelt.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-riscv@nongnu.org \
    --cc=richard.henderson@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.