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': {
>
prev parent 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.