All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
To: Zephyr Li <fritchleybohrer@gmail.com>, qemu-devel@nongnu.org
Cc: qemu-riscv@nongnu.org, Palmer Dabbelt <palmer@dabbelt.com>,
	Alistair Francis <alistair.francis@wdc.com>,
	Weiwei Li <liwei1518@gmail.com>,
	Liu Zhiwei <zhiwei_liu@linux.alibaba.com>,
	Chao Liu <chao.liu@processmission.com>
Subject: Re: [PATCH] target/riscv: save ELP in MPELP for NMIE=0 exceptions
Date: Wed, 2 Sep 2026 08:31:25 -0300	[thread overview]
Message-ID: <2d8f63f8-721f-42a4-843e-3ec79de2c2ce@oss.qualcomm.com> (raw)
In-Reply-To: <20260902015704.101990-1-fritchleybohrer@gmail.com>



On 9/1/2026 10:57 PM, Zephyr Li wrote:
> When an exception occurs in M-mode while mnstatus.NMIE is clear,
> Smrnmi only changes the exception handler address. Trap state is still
> saved in the regular M-mode CSRs and the handler returns with MRET.

I believe it's worth adding the quote from the smrnmi spec.  It's section 8.5,
"RNMI Operation":

"If the hart encounters an exception while executing in M-mode with the
  mnstatus.NMIE bit clear, the exception is an RNMI exception. Trap state
  is still saved in the regular M-mode CSRs and the handler returns with MRET."

> 
> riscv_cpu_do_interrupt() instead saves ELP in mnstatus.MNPELP on this
> path. MRET restores ELP from mstatus.MPELP, so the expected landing-pad
> state is lost.
> 
> Always save ELP in mstatus.MPELP for M-mode exceptions. Keep MNPELP for
> the actual RNMI interrupt path, which returns with MNRET.
> 
> Add a TCG test that checks ELP preservation across an NMIE=0 M-mode
> exception and MRET.
> 
> Fixes: 0266fd8b56a4 ("target/riscv: Add Zicfilp support for Smrnmi")
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4223
> Signed-off-by: Zephyr Li <fritchleybohrer@gmail.com>
> ---

Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>

>   target/riscv/tcg/cpu_helper.c             |  18 +---
>   tests/tcg/riscv64/Makefile.softmmu-target |   8 ++
>   tests/tcg/riscv64/test-zicfilp-smrnmi.S   | 117 ++++++++++++++++++++++
>   3 files changed, 127 insertions(+), 16 deletions(-)
>   create mode 100644 tests/tcg/riscv64/test-zicfilp-smrnmi.S
> 
> diff --git a/target/riscv/tcg/cpu_helper.c b/target/riscv/tcg/cpu_helper.c
> index 07d9222652..a0d79b33a5 100644
> --- a/target/riscv/tcg/cpu_helper.c
> +++ b/target/riscv/tcg/cpu_helper.c
> @@ -2264,23 +2264,9 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>   
>           src = env->sepc;
>       } else {
> -        /*
> -         * If the hart encounters an exception while executing in M-mode
> -         * with the mnstatus.NMIE bit clear, the exception is an RNMI exception.
> -         */
> -        nnmi_excep = cpu->cfg.ext_smrnmi &&
> -                     !get_field(env->mnstatus, MNSTATUS_NMIE) &&
> -                     !async;
> -
> -        /* handle the trap in M-mode */
> -        /* save elp status */
> +        /* Save ELP for MRET. */
>           if (cpu_get_fcfien(env)) {
> -            if (nnmi_excep) {
> -                env->mnstatus = set_field(env->mnstatus, MNSTATUS_MNPELP,
> -                                          env->elp);
> -            } else {
> -                env->mstatus = set_field(env->mstatus, MSTATUS_MPELP, env->elp);
> -            }
> +            env->mstatus = set_field(env->mstatus, MSTATUS_MPELP, env->elp);
>           }
>   
>           if (riscv_has_ext(env, RVH)) {
> diff --git a/tests/tcg/riscv64/Makefile.softmmu-target b/tests/tcg/riscv64/Makefile.softmmu-target
> index 6a219c306c..8522c3fe6f 100644
> --- a/tests/tcg/riscv64/Makefile.softmmu-target
> +++ b/tests/tcg/riscv64/Makefile.softmmu-target
> @@ -45,6 +45,14 @@ comma:= ,
>   run-test-crc32: test-crc32
>   	$(call run-test, $<, $(QEMU) -cpu rv64$(comma)xlrbr=true $(QEMU_OPTS)$<)
>   
> +EXTRA_RUNS += run-test-zicfilp-smrnmi
> +run-test-zicfilp-smrnmi: test-zicfilp-smrnmi
> +	$(call run-test, $<, \
> +	  $(QEMU) \
> +	  -cpu rv64$(comma)zicsr=true$(comma)zicfilp=true$(comma)smrnmi=true \
> +	  -global rv64-riscv-cpu.rnmi-exception-vector=0x80000100 \
> +	  $(QEMU_OPTS)$<)
> +
>   # Zicclsm: misaligned load/store support. Assemble one source twice: the
>   # default build expects every misaligned access to succeed (zicclsm=true),
>   # the -DZICCLSM_DISABLED build expects every one to trap (zicclsm=false).
> diff --git a/tests/tcg/riscv64/test-zicfilp-smrnmi.S b/tests/tcg/riscv64/test-zicfilp-smrnmi.S
> new file mode 100644
> index 0000000000..b5965bf705
> --- /dev/null
> +++ b/tests/tcg/riscv64/test-zicfilp-smrnmi.S
> @@ -0,0 +1,117 @@
> +/*
> + * Test that an M-mode exception taken with mnstatus.NMIE clear saves ELP in
> + * mstatus.MPELP, so that it is restored by MRET.  MNPELP is reserved for the
> + * actual RNMI path, which returns with MNRET.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +	.option	norvc
> +
> +	.equ	CSR_MNSTATUS, 0x744
> +	.equ	CSR_MSECCFG, 0x747
> +	.equ	MNSTATUS_NMIE, 1 << 3
> +	.equ	MNSTATUS_MNPELP, 1 << 9
> +	.equ	MSECCFG_MLPE, 1 << 10
> +	.equ	MSTATUS_MPELP, 1 << 41
> +	.equ	EXCP_INST_ACCESS_FAULT, 1
> +	.equ	EXCP_SW_CHECK, 18
> +	.equ	SW_CHECK_FCFI_TVAL, 2
> +
> +	.text
> +	.global	_start
> +_start:
> +	/* Verify that NMIE is clear before exercising the exception path. */
> +	csrr	t0, CSR_MNSTATUS
> +	andi	t0, t0, MNSTATUS_NMIE
> +	bnez	t0, fail_nmie
> +
> +	/* Enable landing-pad checks in M-mode, then start a new TB. */
> +	li	t0, MSECCFG_MLPE
> +	csrs	CSR_MSECCFG, t0
> +	j	tracked_jump
> +
> +tracked_jump:
> +	/* Make a Zicfilp-tracked indirect jump to an address that faults. */
> +	li	t1, 0
> +	jalr	zero, 0(t1)
> +
> +	/*
> +	 * The instruction access fault should have redirected to the handler.
> +	 */
> +	li	a0, 1
> +	j	_exit
> +
> +fail_nmie:
> +	li	a0, 6
> +	j	_exit
> +
> +	/* Must match rnmi-exception-vector in Makefile.softmmu-target. */
> +	.org	0x100
> +rnmi_exception:
> +	csrr	t0, mcause
> +	li	t1, EXCP_INST_ACCESS_FAULT
> +	beq	t0, t1, handle_fetch_fault
> +	li	t1, EXCP_SW_CHECK
> +	beq	t0, t1, handle_sw_check
> +
> +	li	a0, 4
> +	j	_exit
> +
> +handle_fetch_fault:
> +	/* This is an M-mode exception and will return with MRET. */
> +	csrr	t0, mstatus
> +	li	t1, MSTATUS_MPELP
> +	and	t0, t0, t1
> +	beqz	t0, fail_mpelp
> +
> +	csrr	t0, CSR_MNSTATUS
> +	andi	t0, t0, MNSTATUS_MNPELP
> +	bnez	t0, fail_mnpelp
> +
> +	lla	t0, resume_non_lpad
> +	csrw	mepc, t0
> +	mret
> +
> +resume_non_lpad:
> +	/* MRET must restore ELP, so this instruction must not retire. */
> +	li	a0, 1
> +	j	_exit
> +
> +handle_sw_check:
> +	csrr	t0, mtval
> +	li	t1, SW_CHECK_FCFI_TVAL
> +	bne	t0, t1, fail_tval
> +
> +	li	a0, 0
> +	j	_exit
> +
> +fail_mpelp:
> +	li	a0, 2
> +	j	_exit
> +
> +fail_mnpelp:
> +	li	a0, 3
> +	j	_exit
> +
> +fail_tval:
> +	li	a0, 5
> +
> +_exit:
> +	lla	a1, semiargs
> +	li	t0, 0x20026	/* ADP_Stopped_ApplicationExit */
> +	sd	t0, 0(a1)
> +	sd	a0, 8(a1)
> +	li	a0, 0x20	/* TARGET_SYS_EXIT_EXTENDED */
> +
> +	/* Semihosting call sequence. */
> +	.balign	16
> +	slli	zero, zero, 0x1f
> +	ebreak
> +	srai	zero, zero, 0x7
> +	j	.
> +
> +	.data
> +	.balign	16
> +semiargs:
> +	.space	16



      reply	other threads:[~2026-09-02 11:31 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-02  1:57 [PATCH] target/riscv: save ELP in MPELP for NMIE=0 exceptions Zephyr Li
2026-09-02 11:31 ` Daniel Henrique Barboza [this message]

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=2d8f63f8-721f-42a4-843e-3ec79de2c2ce@oss.qualcomm.com \
    --to=daniel.barboza@oss.qualcomm.com \
    --cc=alistair.francis@wdc.com \
    --cc=chao.liu@processmission.com \
    --cc=fritchleybohrer@gmail.com \
    --cc=liwei1518@gmail.com \
    --cc=palmer@dabbelt.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-riscv@nongnu.org \
    --cc=zhiwei_liu@linux.alibaba.com \
    /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.