All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
To: TANG Tiancheng <lyndra@linux.alibaba.com>, qemu-devel@nongnu.org
Cc: "Zephyr Li" <fritchleybohrer@gmail.com>,
	"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>,
	qemu-riscv@nongnu.org,
	"Richard Henderson" <richard.henderson@linaro.org>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Philippe Mathieu-Daudé" <philmd@oss.qualcomm.com>
Subject: Re: [PATCH v2 14/14] target/riscv: Preserve fixed PMU state across reset
Date: Fri, 25 Sep 2026 13:45:44 -0300	[thread overview]
Message-ID: <ee7f09b9-7313-40a7-986b-063465272841@oss.qualcomm.com> (raw)
In-Reply-To: <20260910-riscv-pmu-correctness-v2-14-5da5159a0c64@linux.alibaba.com>



On 9/10/2026 11:39 AM, TANG Tiancheng wrote:
> Privilege filtering records cycle/instruction increments per mode. Reset
> overwrites privilege/V without adding the final interval to the old
> mode's total, so a counter filtering for that mode loses those counts.
> 
> Account for the old mode before entering M-mode with V=0 and rebuild the
> overflow timer after reset. On initial reset, only initialize baselines:
> no guest code has run, so pre-execution QEMU time must not count.
> Preserve architectural counter and selector state, as before.
> 
> Test that a VS-only cycle counter retains its counts across reset.
> 
> Signed-off-by: TANG Tiancheng <lyndra@linux.alibaba.com>
> ---


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

>   target/riscv/cpu.c                   |  16 ++++++
>   target/riscv/tcg/pmu.c               |  11 ++++
>   target/riscv/tcg/pmu.h               |   1 +
>   tests/tcg/riscv64/pmu-reset-vs.S     | 105 +++++++++++++++++++++++++++++++++++
>   tests/tcg/riscv64/system/meson.build |   7 +++
>   5 files changed, 140 insertions(+)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index f60d7cca1e2f0008b09b1055c5cdeed3ec4ad1d3..e27312ac505dbee072c5a3c52073b00d703fd81d 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -42,6 +42,9 @@
>   #include "disas/capstone.h"
>   #if !defined(CONFIG_USER_ONLY)
>   #include "target/riscv/tcg/debug.h"
> +#ifdef CONFIG_TCG
> +#include "target/riscv/tcg/pmu.h"
> +#endif
>   #endif
>   
>   /* RISC-V CPU definitions */
> @@ -979,6 +982,16 @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
>       }
>   #ifndef CONFIG_USER_ONLY
>       env->misa_mxl = mcc->def->misa_mxl_max;
> +#ifdef CONFIG_TCG
> +    /* The initial reset has no guest execution to count. */
> +    if (tcg_enabled()) {
> +        if (qdev_is_realized(DEVICE(cpu))) {
> +            riscv_pmu_update_fixed_ctrs(env, PRV_M, false);
> +        } else {
> +            riscv_pmu_init_fixed_counter_baselines(env);
> +        }
> +    }
> +#endif
>       env->priv = PRV_M;
>       env->virt_enabled = false;
>       env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
> @@ -1092,6 +1105,9 @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
>   
>   #ifndef CONFIG_USER_ONLY
>   #ifdef CONFIG_TCG
> +    if (tcg_enabled()) {
> +        riscv_pmu_rebuild_timer(env);
> +    }
>       if (cpu->cfg.debug || cpu->cfg.ext_sdtrig) {
>           riscv_trigger_reset_hold(env);
>       }
> diff --git a/target/riscv/tcg/pmu.c b/target/riscv/tcg/pmu.c
> index df99b572a4c16cb1ac65c2f7cde35c6f8349e681..1d692a0a8e3f7759e033214d579103627d070b5b 100644
> --- a/target/riscv/tcg/pmu.c
> +++ b/target/riscv/tcg/pmu.c
> @@ -171,6 +171,17 @@ void riscv_pmu_update_fixed_ctrs(CPURISCVState *env,
>       riscv_pmu_update_fixed_ctrs_snapshot(env, newpriv, new_virt, &snapshot);
>   }
>   
> +void riscv_pmu_init_fixed_counter_baselines(CPURISCVState *env)
> +{
> +    RISCVPMUFixedSnapshot snapshot;
> +
> +    riscv_pmu_take_fixed_snapshot(env, &snapshot);
> +    env->pmu_fixed_ctrs[RISCV_PMU_FIXED_DOMAIN_CYCLE]
> +        .counter_prev[PRV_M] = snapshot.cycle;
> +    env->pmu_fixed_ctrs[RISCV_PMU_FIXED_DOMAIN_INSTRET]
> +        .counter_prev[PRV_M] = snapshot.instret;
> +}
> +
>   uint64_t
>   riscv_pmu_ctr_get_fixed_value(CPURISCVState *env, uint32_t ctr_idx,
>                                 const RISCVPMUFixedSnapshot *snapshot)
> diff --git a/target/riscv/tcg/pmu.h b/target/riscv/tcg/pmu.h
> index 1cfe6acf55b5468f5c00c4a136ece88981384341..fac84dbb1a8a6c637f7241ca27910e5e212223e9 100644
> --- a/target/riscv/tcg/pmu.h
> +++ b/target/riscv/tcg/pmu.h
> @@ -53,6 +53,7 @@ int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx);
>   void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name);
>   void riscv_pmu_update_fixed_ctrs(CPURISCVState *env, privilege_mode_t newpriv,
>                                    bool new_virt);
> +void riscv_pmu_init_fixed_counter_baselines(CPURISCVState *env);
>   void riscv_pmu_decr_instret(CPURISCVState *env);
>   RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val,
>                                     bool upper_half, uint32_t ctr_idx,
> diff --git a/tests/tcg/riscv64/pmu-reset-vs.S b/tests/tcg/riscv64/pmu-reset-vs.S
> new file mode 100644
> index 0000000000000000000000000000000000000000..d216faef17a2a395120cb3a71166a821a43dee88
> --- /dev/null
> +++ b/tests/tcg/riscv64/pmu-reset-vs.S
> @@ -0,0 +1,105 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +
> +/* CSR number for older assemblers. */
> +#define CSR_MCYCLECFG        0x321
> +
> +	.option	norvc
> +	.option	norelax
> +
> +	.equ	MSTATUS_MPP_S,  (1 << 11)
> +	.equ	MSTATUS_MPP,    (3 << 11)
> +	.equ	MSTATUS_SPP,    (1 << 8)
> +	.equ	HSTATUS_SPV,    (1 << 7)
> +	.equ	SIFIVE_TEST,    0x100000
> +	.equ	MTIMECMP,       0x2004000
> +	.equ	FINISHER_RESET, 0x7777
> +
> +	.text
> +	.global _start
> +_start:
> +	/* Preserve the reset marker and saved count in MTIMECMP. */
> +	li	t0, MTIMECMP
> +	ld	t1, 0(t0)
> +	srli	t2, t1, 48
> +	li	t3, 0xa5a5
> +	beq	t2, t3, after_reset
> +
> +	/* Count VS only, then remember the value before entering VS-mode. */
> +	li	t0, 0x1d		/* MINH | SINH | UINH | VUINH */
> +	slli	t0, t0, 58
> +	csrw	CSR_MCYCLECFG, t0
> +	csrr	t1, mcycle
> +	slli	t1, t1, 16
> +	srli	t1, t1, 16
> +	li	t2, 0xa5a5
> +	slli	t2, t2, 48
> +	or	t1, t1, t2
> +	li	t0, MTIMECMP
> +	sd	t1, 0(t0)
> +	li	t0, -1
> +	csrw	pmpaddr0, t0
> +	li	t0, 0x1f		/* RWX, NAPOT */
> +	csrw	pmpcfg0, t0
> +
> +	/* Enter HS-mode first. */
> +	csrr	t0, mstatus
> +	li	t1, MSTATUS_MPP
> +	not	t1, t1
> +	and	t0, t0, t1
> +	li	t1, MSTATUS_MPP_S
> +	or	t0, t0, t1
> +	csrw	mstatus, t0
> +	lla	t0, hs_enter
> +	csrw	mepc, t0
> +	mret
> +
> +hs_enter:
> +	li	t0, HSTATUS_SPV
> +	csrs	hstatus, t0
> +	li	t0, MSTATUS_SPP
> +	csrs	sstatus, t0
> +	lla	t0, vs_reset
> +	csrw	sepc, t0
> +	sret
> +
> +vs_reset:
> +	/* These VS-mode cycles must remain in mcycle after reset. */
> +	li	t0, 128
> +1:
> +	addi	t0, t0, -1
> +	bnez	t0, 1b
> +
> +	li	t0, SIFIVE_TEST
> +	li	t1, FINISHER_RESET
> +	sw	t1, 0(t0)
> +	j	.
> +
> +after_reset:
> +	csrr	t0, mcycle
> +	slli	t1, t1, 16		/* Clear the MTIMECMP marker. */
> +	srli	t1, t1, 16
> +	addi	t1, t1, 128
> +	bgeu	t1, t0, fail
> +	li	t3, 0
> +	j	exit
> +
> +fail:
> +	li	t3, 1
> +
> +exit:
> +	lla	a1, semiargs
> +	li	t0, 0x20026		/* ADP_Stopped_ApplicationExit */
> +	sd	t0, 0(a1)
> +	sd	t3, 8(a1)
> +	li	a0, 0x20		/* TARGET_SYS_EXIT_EXTENDED */
> +
> +	.balign	16
> +	slli	zero, zero, 0x1f
> +	ebreak
> +	srai	zero, zero, 0x7
> +	j	.
> +
> +	.data
> +	.balign	16
> +semiargs:
> +	.space	16
> diff --git a/tests/tcg/riscv64/system/meson.build b/tests/tcg/riscv64/system/meson.build
> index d2355090121ba7a7d0046c1fc1824d6a89c1267f..3f2043d100ff88cc39a21002a1e90ccab319001b 100644
> --- a/tests/tcg/riscv64/system/meson.build
> +++ b/tests/tcg/riscv64/system/meson.build
> @@ -142,6 +142,13 @@ tests += {
>     },
>   }
>   
> +tests += {
> +  'pmu-reset-vs.S': {
> +    'cflags': cflags,
> +    'qemu_args': ['-cpu', 'max,smcntrpmf=true', '-icount', 'shift=0', qemu_args],
> +  },
> +}
> +
>   if 'qemu-system-riscv64' in emulators
>     tcg_tests += {
>       'riscv64-softmmu': {
> 



      reply	other threads:[~2026-09-25 16:46 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-10 14:39 [PATCH v2 00/14] RISC-V TCG PMU correctness fixes TANG Tiancheng
2026-09-10 14:39 ` [PATCH v2 01/14] target/riscv: Preserve PMU state across event selector writes TANG Tiancheng
2026-09-11  3:47   ` Chao Liu
2026-09-10 14:39 ` [PATCH v2 02/14] target/riscv: Support multiple counters per PMU event TANG Tiancheng
2026-09-11  3:54   ` Chao Liu
2026-09-10 14:39 ` [PATCH v2 03/14] target/riscv: Use VM-elapsed sources for fixed PMU events TANG Tiancheng
2026-09-11  3:55   ` Chao Liu
2026-09-10 14:39 ` [PATCH v2 04/14] target/riscv: Preserve MINH on delegated config reads TANG Tiancheng
2026-09-11  3:56   ` Chao Liu
2026-09-10 14:39 ` [PATCH v2 05/14] target/riscv: Preserve minstretcfgh on RV32 minstretcfg writes TANG Tiancheng
2026-09-11  4:43   ` Chao Liu
2026-09-10 14:39 ` [PATCH v2 06/14] target/riscv: Fix RV32 accesses to delegated PMU registers TANG Tiancheng
2026-09-25 15:44   ` Daniel Henrique Barboza
2026-09-10 14:39 ` [PATCH v2 07/14] target/riscv: Preserve fixed counters across PMU state changes TANG Tiancheng
2026-09-25 15:47   ` Daniel Henrique Barboza
2026-09-10 14:39 ` [PATCH v2 08/14] target/riscv: Require Sscofpmf for non-fixed event overflow TANG Tiancheng
2026-09-25 16:08   ` Daniel Henrique Barboza
2026-09-10 14:39 ` [PATCH v2 09/14] target/riscv: Rebuild fixed-event PMU overflow deadlines TANG Tiancheng
2026-09-25 16:21   ` Daniel Henrique Barboza
2026-09-10 14:39 ` [PATCH v2 10/14] target/riscv: Apply minstret exception accounting to HPM counters TANG Tiancheng
2026-09-25 16:31   ` Daniel Henrique Barboza
2026-09-10 14:39 ` [PATCH v2 11/14] target/riscv: Process PMU timer expiry on the owner vCPU TANG Tiancheng
2026-09-25 16:34   ` Daniel Henrique Barboza
2026-09-10 14:39 ` [PATCH v2 12/14] target/riscv: Migrate fixed PMU counter state TANG Tiancheng
2026-09-25 16:40   ` Daniel Henrique Barboza
2026-09-10 14:39 ` [PATCH v2 13/14] target/riscv: Clear virtualization mode on reset TANG Tiancheng
2026-09-25 16:45   ` Daniel Henrique Barboza
2026-09-28  1:31     ` TianCheng TANG
2026-09-10 14:39 ` [PATCH v2 14/14] target/riscv: Preserve fixed PMU state across reset TANG Tiancheng
2026-09-25 16:45   ` 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=ee7f09b9-7313-40a7-986b-063465272841@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=lyndra@linux.alibaba.com \
    --cc=palmer@dabbelt.com \
    --cc=pbonzini@redhat.com \
    --cc=philmd@oss.qualcomm.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-riscv@nongnu.org \
    --cc=richard.henderson@linaro.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.